asp.net webservice处理gzip压缩请求
我有一个asp.net .asmx webservice编写来处理来自第三方工具的请求。第三方工具向web服务发出http POST请求以获取用户信息。我正在使用IIS7asp.net webservice处理gzip压缩请求
选中“删除所有编码”运行Fiddler,我可以看到web服务调用和一切功能正常。如果我取消选中“删除所有编码”,则web服务调用将失败并显示400错误请求。我看到的差异是标题“Content-Encoding:gzip”正在被Fiddler删除,并且内容正在被解压。
因此,当Content-Encoding标头被移除并且内容被解压时,我的webservice功能完美。当头部出现并且内容被压缩时,web服务失败。
我怎样才能既:
- 配置我的web告诉客户端,它不会接受压缩的请求(并希望第三方工具尊重是)
- 解压缩的内容早在asp.net处理
- 修改我的web服务与压缩后的数据
更新工作:要清楚,我不需要要在Response中配置gzip编码,我需要处理gzip编码的Request to my webservice请求。
更新2:第三方工具是Salesforce.com Outlook插件。所以,我无法修改它,并且很多其他公司都毫无困难地使用它。它有要的东西我做(或不做)
更新3:我发现一个职位here,指出IIS不支持压缩数据传入POST请求,它只支持压缩响应。这仍然是真的吗?
我已经找到了部分答案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中删除了所有可以压缩的引用。
由于第三方服务只是发送一个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;
}
}
解压的方式,我不知道,IIS支持解压缩传入的请求,所以这可能要沿管路进一步完成。
设拉子的答案有潜力工作,这将是我会尝试的第一件事。
如果不工作,你可能会考虑你的服务器的.asmx服务切换到WCF,这同时位设置更加困难,也提供了更多的灵活性。
在WCF端有两件事我可以建议。第一个很容易实现,它基于将WCF使用的WebRequest对象设置为自动接受压缩。你可以找到详细信息here。这一个是WCF相当于西拉提出的解决方案。
二是更加复杂,因为它涉及到创建自定义消息编码器,但如果没有上述方法的工作,这应该解决的问题。创建一个消息压缩编码器描述here。您可能还想检查here中的答案,该答案显示了消息编码器的示例配置。
请让我知道这是否有帮助,或者您是否需要更多帮助。
最简单的技术是建立一个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>
谢谢,但这样远没有这个帮助。通过取消选中配置设置中的复选框,我可以在IIS7中关闭压缩功能,但是,这似乎只影响服务器的响应。我需要处理请求到被压缩的服务器。 – Geoff 2010-12-07 14:45:59
下面列出了gzip客户端/服务器对话的正常工作原理:http://www.websiteoptimization.com/speed/tweak/compress/ – 2010-12-07 14:55:08
这可能是您的第三方工具播放不好。 – 2010-12-07 14:56:44