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
我有一个asp.net .asmx webservice,用于处理来自第三方工具的请求。第三方工具向Web服务发出http POST请求以获取用户信息。我正在使用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.
运行Fiddler并选中“删除所有编码”,我可以看到webservice调用,并且一切正常。如果取消选中“删除所有编码”,则Web服务调用将失败,并显示400 Bad Request。我看到的差异是Fiddler正在删除标题“Content-Encoding:gzip”,内容正在解压缩。
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.
因此,当删除Content-Encoding标头并解压缩内容时,我的webservice功能完美。当标头存在并且内容被压缩时,web服务失败。
How can I either:
我怎么能:
- Configure my webservice to tell the client that it won't accept compressed requests (and hope that the third party tool respects that)
- 配置我的webservice告诉客户端它不会接受压缩请求(并希望第三方工具尊重它)
- Decompress the content early in the asp.net handling
- 在asp.net处理的早期解压缩内容
- Modify my webservice to work with compressed data
- 修改我的Web服务以使用压缩数据
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.
更新:要清楚,我不需要在Response中配置gzip编码,我需要处理一个请求到我的web服务,这是gzip编码的。
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)
更新2:第三方工具是Salesforce.com Outlook插件。因此,我无权修改它,许多其他公司也没有遇到麻烦。它必须是我正在做的事情(或不做)
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?
更新3:我在这里发现一条帖子说IIS不支持带压缩数据的传入POST请求,它只支持压缩响应。这仍然可以吗?
5 个解决方案
#1
5
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:
最简单的技术是创建一个替换请求过滤器的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()
{
}
}
To activate this module, add the following section into your web.config:
要激活此模块,请将以下部分添加到web.config中:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="AnyUniqueName"
type="YourNamespace.GZipRequestDecompressingModule, YourAssembly"
preCondition="integratedMode" />
</modules>
</system.webServer>
#2
2
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.
由于第三方服务只是向您发送POST,我认为不可能告诉他们不要发送压缩文件。
You could try to override GetWebRequest and decompress it on the way in
您可以尝试覆盖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;
}
}
#3
1
GZIP compression is a function of the server.
GZIP压缩是服务器的功能。
If you're using IIS6, consult this link.
如果您使用的是IIS6,请参阅此链接。
If you're using IIS7, you could use ISAPI_Rewrite to disable gzip. See this link.
如果您使用的是IIS7,则可以使用ISAPI_Rewrite来禁用gzip。看到这个链接。
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.
也就是说,因为gzip是IIS的一个功能,所以你真的不需要做任何“特殊”的事情来使它与Web服务一起工作(IIS应该处理解压缩和压缩请求)。希望这些信息可以帮助您进一步解决问题并解决问题。
#4
1
I am not sure that IIS supports decompressing incoming requests, so this might have to be done further down the pipe.
我不确定IIS是否支持解压缩传入的请求,因此可能需要在管道中进一步完成。
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.
如果这不起作用,您可以考虑将服务器.asmx服务切换到WCF,虽然设置它有点困难,但也提供了更大的灵活性。
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.
在WCF方面,我可以提出两件事。第一个很容易实现,它基于设置WCF使用的WebRequest对象自动接受压缩。你可以在这里找到详细信息。这个是WCF,相当于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.
如果这有帮助或者您需要更多帮助,请告诉我。
#5
1
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.
我说部分答案,因为即使我现在可以处理传入的请求,响应也会得到一个“Content-Encoding:gzip”标题,即使响应没有被编码。我可以在Fiddler中验证内容未编码。
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.
如果我对响应进行编码,则Web服务的客户端将失败。似乎即使它发送“Accept-Encoding:gzip”,它实际上也不接受gzip压缩响应。我可以在Fiddler中验证响应是否被压缩,Fiddler将成功解压缩。
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.
所以,现在我一直试图从响应中删除一个流浪的“Content-Encoding:gzip”标头。我从应用程序,web.config和IIS中删除了所有可以找到压缩的引用。
#1
5
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:
最简单的技术是创建一个替换请求过滤器的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()
{
}
}
To activate this module, add the following section into your web.config:
要激活此模块,请将以下部分添加到web.config中:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="AnyUniqueName"
type="YourNamespace.GZipRequestDecompressingModule, YourAssembly"
preCondition="integratedMode" />
</modules>
</system.webServer>
#2
2
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.
由于第三方服务只是向您发送POST,我认为不可能告诉他们不要发送压缩文件。
You could try to override GetWebRequest and decompress it on the way in
您可以尝试覆盖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;
}
}
#3
1
GZIP compression is a function of the server.
GZIP压缩是服务器的功能。
If you're using IIS6, consult this link.
如果您使用的是IIS6,请参阅此链接。
If you're using IIS7, you could use ISAPI_Rewrite to disable gzip. See this link.
如果您使用的是IIS7,则可以使用ISAPI_Rewrite来禁用gzip。看到这个链接。
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.
也就是说,因为gzip是IIS的一个功能,所以你真的不需要做任何“特殊”的事情来使它与Web服务一起工作(IIS应该处理解压缩和压缩请求)。希望这些信息可以帮助您进一步解决问题并解决问题。
#4
1
I am not sure that IIS supports decompressing incoming requests, so this might have to be done further down the pipe.
我不确定IIS是否支持解压缩传入的请求,因此可能需要在管道中进一步完成。
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.
如果这不起作用,您可以考虑将服务器.asmx服务切换到WCF,虽然设置它有点困难,但也提供了更大的灵活性。
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.
在WCF方面,我可以提出两件事。第一个很容易实现,它基于设置WCF使用的WebRequest对象自动接受压缩。你可以在这里找到详细信息。这个是WCF,相当于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.
如果这有帮助或者您需要更多帮助,请告诉我。
#5
1
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.
我说部分答案,因为即使我现在可以处理传入的请求,响应也会得到一个“Content-Encoding:gzip”标题,即使响应没有被编码。我可以在Fiddler中验证内容未编码。
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.
如果我对响应进行编码,则Web服务的客户端将失败。似乎即使它发送“Accept-Encoding:gzip”,它实际上也不接受gzip压缩响应。我可以在Fiddler中验证响应是否被压缩,Fiddler将成功解压缩。
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.
所以,现在我一直试图从响应中删除一个流浪的“Content-Encoding:gzip”标头。我从应用程序,web.config和IIS中删除了所有可以找到压缩的引用。