处理 gzip 压缩请求的 asp.net webservice

发布于 2024-10-07 02:07:06 字数 796 浏览 0 评论 0原文

我编写了一个 asp.net .asmx Web 服务来处理来自第三方工具的请求。第三方工具向 Web 服务发出 http POST 请求以获取用户信息。我正在使用 IIS7

运行 Fiddler,选中“删除所有编码”,我可以看到 Web 服务调用,并且一切正常。如果我取消选中“删除所有编码”,Web 服务调用将失败并显示 400 错误请求。我看到的区别是标头“Content-Encoding: gzip”被 Fiddler 删除并且内容正在解压缩。

因此,当删除 Content-Encoding 标头并解压缩内容时,我的 Web 服务可以完美运行。当标头存在并且内容被压缩时,Web 服务将失败。

我怎样才能:

  1. 配置我的 Web 服务以告诉客户端它不会接受压缩请求(并希望第三方工具尊重这一点)
  2. 在 ASP.NET 处理早期解压缩内容
  3. 修改我的 Web 服务以使用压缩数据

<更新:需要明确的是,我不需要在响应中配置 gzip 编码,我需要处理对我的 web 服务进行 gzip 编码的请求。

更新 2:第三方工具是 Salesforce.com Outlook 插件。因此,我无权修改它,并且许多其他公司都可以毫无问题地使用它。这一定是我正在做(或没有做)的事情

更新3:我发现了一篇文章这里表示 IIS 不支持带有压缩数据的传入 POST 请求,它只支持压缩响应。这仍然是真的吗?

I have an asp.net .asmx webservice written to handle requests from a third party tool. The third party tool makes an http POST request to the webservice to get user information. I'm using IIS7

Running Fiddler with "Remove All Encodings" checked, I can see the webservice call and and everything functions properly. If I uncheck "Remove All Encodings", the webservice call fails with a 400 Bad Request. The difference I see is that the header "Content-Encoding: gzip" is being removed by Fiddler and the content is being decompressed.

So, when the Content-Encoding header is removed and the content is decompressed, my webservice functions perfectly. When the header is present and the content is compressed, the webservice fails.

How can I either:

  1. Configure my webservice to tell the client that it won't accept compressed requests (and hope that the third party tool respects that)
  2. Decompress the content early in the asp.net handling
  3. Modify my webservice to work with compressed data

Update: To be clear, I don't need to configure gzip encoding in the Response, I need to deal with a Request TO my webservice that is gzip encoded.

Update 2: The third-party tool is the Salesforce.com Outlook plugin. So, I don't have access to modify it and it is used by many other companies without trouble. It's got to be something I'm doing (or not doing)

Update 3: I found one post here that says that IIS does not support incoming POST requests with compressed data, it only supports compressed Responses. Can this still be true?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

迷雾森÷林ヴ 2024-10-14 02:07:07

我不确定 IIS 支持解压缩传入请求,因此这可能需要进一步完成。

设拉子的答案有可能发挥作用,这将是我首先要尝试的事情。

如果这不起作用,您可能会考虑将服务器 .asmx 服务切换到 WCF,这虽然设置起来有点困难,但也提供了更大的灵活性。

在 WCF 方面,我可以建议两件事。第一个非常容易实现,并且基于设置 WCF 使用的 WebRequest 对象来自动接受压缩。您可以在此处找到详细信息。这就是相当于Shiraz提出的解决方案的WCF。

第二种更复杂,因为它涉及创建自定义消息编码器,但如果上述方法都不起作用,这应该可以解决问题。 此处介绍了创建消息压缩编码器。您可能还想检查 这里提供了消息编码器的示例配置。

请告诉我这是否有帮助或者您是否需要更多帮助。

I am not sure that IIS supports decompressing incoming requests, so this might have to be done further down the pipe.

Shiraz's answer has the potential of working and it would be the first thing I would try.

If that doesn't work you might consider switching your server .asmx service to WCF, which while a bit more difficult to setup it also gives more flexibility.

On the WCF side there are two things I can suggest. The first is quite easy to implement and is based on setting the WebRequest object used by WCF to automatically accept compression. You can find the details here. This one is the WCF equivalent to the solution proposed by Shiraz.

The second is more complicated, since it involves creating Custom Message Encoders, but if none of the above methods work, this should solve the problem. Creating a message compression encoder is described here. You might also want to check the answer in here which presents a sample config for the message encoder.

Please let me know if this helped or if you need more help.

山色无中 2024-10-14 02:07:07

我在此处找到了部分答案。

class DecompressStream : Stream
{
    ...

    public override int Read(byte[] buffer, int offset, int count)
    {
        GZipStream test = new GZipStream(_sink, CompressionMode.Decompress);

        int c = test.Read(buffer, offset, count);

        return c;
    }

    ...
}

然后,我可以在请求对象上指定过滤器,如下所示:

void Application_BeginRequest(object sender, EventArgs e)
    {
        string contentEncoding = Request.Headers["Content-Encoding"];
        Stream prevCompressedStream = Request.Filter;

        if(contentEncoding == null || contentEncoding.Length == 0)
            return;

        contentEncoding = contentEncoding.ToLower();

        if(contentEncoding.Contains("gzip"))
        {
            Request.Filter = new DecompressStream(Request.Filter);
        }
    }

我说部分答案,因为即使我现在可以处理传入请求,响应也会获取“Content-Encoding:gzip”标头响应未编码。我可以在 Fiddler 中验证内容是否未编码。

如果我对响应进行编码,则 Web 服务的客户端将失败。看起来,即使它正在发送“Accept-Encoding:gzip”,但实际上它并不接受 gzip 压缩响应。我可以在 Fiddler 中验证响应是否已压缩,并且 Fiddler 将成功解压缩它。

所以,现在我一直试图从响应中删除杂散的“Content-Encoding:gzip”标头。我已经删除了应用程序、web.config 和 IIS 中可以找到的所有压缩引用。

I've found a partial answer here.

class DecompressStream : Stream
{
    ...

    public override int Read(byte[] buffer, int offset, int count)
    {
        GZipStream test = new GZipStream(_sink, CompressionMode.Decompress);

        int c = test.Read(buffer, offset, count);

        return c;
    }

    ...
}

I can then specify the filter on the request object like this:

void Application_BeginRequest(object sender, EventArgs e)
    {
        string contentEncoding = Request.Headers["Content-Encoding"];
        Stream prevCompressedStream = Request.Filter;

        if(contentEncoding == null || contentEncoding.Length == 0)
            return;

        contentEncoding = contentEncoding.ToLower();

        if(contentEncoding.Contains("gzip"))
        {
            Request.Filter = new DecompressStream(Request.Filter);
        }
    }

I say partial answer because even though I can now process the incoming request, the response is getting a "Content-Encoding: gzip" header even though the response is not encoded. I can verify in Fiddler that the content is not encoded.

If I do encode the response, the client for the webservice fails. It seems that even though it is sending "Accept-Encoding: gzip", it does not in fact accept gzip compressed response. I can verify in Fiddler that the response is compressed and Fiddler will decompress it successfully.

So, now I'm stuck trying to get a stray "Content-Encoding: gzip" header removed from the response. I've removed all references I can find to compression from the application, the web.config, and IIS.

最美不过初阳 2024-10-14 02:07:06

最简单的技术是创建一个 HttpModule 来替换请求过滤器。它更具可重用性,并且避免使用 Global.asax。也无需创建新的解压缩流类,因为 GZipStream 已为此做好准备。这是完整的代码,它还删除了不再需要的 Content-Encoding: gzip

public class GZipRequestDecompressingModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, e) =>
        {
            var request = (sender as HttpApplication).Request;

            string contentEncoding = request.Headers["Content-Encoding"];

            if (string.Equals(contentEncoding, "gzip",
                StringComparison.OrdinalIgnoreCase))
            {
                request.Filter = new GZipStream(request.Filter,
                    CompressionMode.Decompress);
                request.Headers.Remove("Content-Encoding");
            }
        };
    }
    public void Dispose()
    {
    }
}

要激活此模块,请将以下部分添加到您的 web.config 中:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="AnyUniqueName"
            type="YourNamespace.GZipRequestDecompressingModule, YourAssembly"
            preCondition="integratedMode" />
    </modules>
</system.webServer>

The simplest technique is to create an HttpModule that replaces the request filter. It is more reusable and avoids having a Global.asax. There is also no need to create a new decompress stream class as the GZipStream is ready for that. Here is the full code, that also removes the Content-Encoding: gzip that is not needed any more:

public class GZipRequestDecompressingModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, e) =>
        {
            var request = (sender as HttpApplication).Request;

            string contentEncoding = request.Headers["Content-Encoding"];

            if (string.Equals(contentEncoding, "gzip",
                StringComparison.OrdinalIgnoreCase))
            {
                request.Filter = new GZipStream(request.Filter,
                    CompressionMode.Decompress);
                request.Headers.Remove("Content-Encoding");
            }
        };
    }
    public void Dispose()
    {
    }
}

To activate this module, add the following section into your web.config:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="AnyUniqueName"
            type="YourNamespace.GZipRequestDecompressingModule, YourAssembly"
            preCondition="integratedMode" />
    </modules>
</system.webServer>
緦唸λ蓇 2024-10-14 02:07:06

由于第 3 方服务只是向您发送 POST,因此我认为不可能告诉他们不要以压缩形式发送。

您可以尝试覆盖 GetWebRequest 并在途中解压缩它

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol

{
protected override WebRequest GetWebRequest(Uri uri)
{
    base.GetWebRequest(uri);request.AutomaticDecompression = System.Net.DecompressionMethods.GZip;
    return request;
}
}

Since the 3rd party service is just sending you a POST, I do not think that it is possible to tell them not to send in compressed.

You could try to override GetWebRequest and decompress it on the way in

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol

{
protected override WebRequest GetWebRequest(Uri uri)
{
    base.GetWebRequest(uri);request.AutomaticDecompression = System.Net.DecompressionMethods.GZip;
    return request;
}
}
温柔戏命师 2024-10-14 02:07:06

GZIP 压缩是服务器的一项功能。

如果您使用的是 IIS6,请参阅此链接

如果您使用的是 IIS7,则可以使用 ISAPI_Rewrite 禁用 gzip。请参阅此链接

也就是说,因为 gzip 是 IIS 的一项功能,所以您实际上不需要做任何“特殊”的事情来让它与 Web 服务一起工作(IIS 应该处理解压缩和压缩请求)。希望这些信息能够帮助您进一步排除故障并解决问题。

GZIP compression is a function of the server.

If you're using IIS6, consult this link.

If you're using IIS7, you could use ISAPI_Rewrite to disable gzip. See this link.

That said, because gzip is a function of IIS, you really shouldn't need to do anything "special" to get it to work with a web service (IIS should handle decompressing and compressing requests). Hopefully this info will get you further down the road to troubleshooting and resolving the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文