2010-12-07 133 views
9

我有一个asp.net .asmx webservice编写来处理来自第三方工具的请求。第三方工具向web服务发出http POST请求以获取用户信息。我正在使用IIS7asp.net webservice处理gzip压缩请求

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

因此,当Content-Encoding标头被移除并且内容被解压时,我的webservice功能完美。当头部出现并且内容被压缩时,web服务失败。

我怎样才能既:

  1. 配置我的web告诉客户端,它不会接受压缩的请求(并希望第三方工具尊重是)
  2. 解压缩的内容早在asp.net处理
  3. 修改我的web服务与压缩后的数据

更新工作:要清楚,我不需要要在Response中配置gzip编码,我需要处理gzip编码的Request to my webservice请求。

更新2:第三方工具是Salesforce.com Outlook插件。所以,我无法修改它,并且很多其他公司都毫无困难地使用它。它有要的东西我做(或不做)

更新3:我发现一个职位here,指出IIS不支持压缩数据传入POST请求,它只支持压缩响应。这仍然是真的吗?

回答

1

我已经找到了部分答案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; 
    } 

    ... 
} 

然后我就可以指定这样的请求对象上的过滤器:

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); 
     } 
    } 

我说部分答案,因为即使我现在可以处理传入的请求,响应得到一个“内容编码:gzip“头,即使响应未被编码。我可以在Fiddler中验证内容没有编码。

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

所以,现在我卡试图让流浪“内容编码:gzip”头从响应中删除。我已经从应用程序,web.config和IIS中删除了所有可以压缩的引用。

1

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

如果您使用IIS6,请参阅this link

如果您使用IIS7,则可以使用ISAPI_Rewrite来禁用gzip。见this link。这就是说,因为gzip是IIS的一个功能,所以你真的不需要做任何“特殊”的事情来让它与Web服务一起工作(IIS应该处理解压缩和压缩请求)。希望这些信息能够帮助您进一步解决问题和解决问题。

+0

谢谢,但这样远没有这个帮助。通过取消选中配置设置中的复选框,我可以在IIS7中关闭压缩功能,但是,这似乎只影响服务器的响应。我需要处理请求到被压缩的服务器。 – Geoff 2010-12-07 14:45:59

+0

下面列出了gzip客户端/服务器对话的正常工作原理:http://www.websiteoptimization.com/speed/tweak/compress/ – 2010-12-07 14:55:08

+0

这可能是您的第三方工具播放不好。 – 2010-12-07 14:56:44

2

由于第三方服务只是发送一个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; 
} 
} 
1

解压的方式,我不知道,IIS支持解压缩传入的请求,所以这可能要沿管路进一步完成。

设拉子的答案有潜力工作,这将是我会尝试的第一件事。

如果不工作,你可能会考虑你的服务器的.asmx服务切换到WCF,这同时位设置更加困难,也提供了更多的灵活性。

在WCF端有两件事我可以建议。第一个很容易实现,它基于将WCF使用的WebRequest对象设置为自动接受压缩。你可以找到详细信息here。这一个是WCF相当于西拉提出的解决方案。

二是更加复杂,因为它涉及到创建自定义消息编码器,但如果没有上述方法的工作,这应该解决的问题。创建一个消息压缩编码器描述here。您可能还想检查here中的答案,该答案显示了消息编码器的示例配置。

请让我知道这是否有帮助,或者您是否需要更多帮助。

5

最简单的技术是建立一个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>