For an ASP.NET 4.0 / IIS7 web app, I would like to support compressed HTTP requ开发者_运维技巧ests. Basically, I would like to support clients that would add Content-Encoding: gzip
in the request headers, and compress the body accordingly.
Does anyone known how I achieve such a behavior?
Ps: concerning, I have multiple endpoints REST and SOAP, and it feels a better solution to support compression at the HTTP level rather than custom encoders for each endpoint.
For those who might be interested, the implementation is rather straightforward with an IHttpModule
that simply filters incoming requests.
public class GZipDecompressModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += BeginRequest;
}
void BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if ("gzip" == app.Request.Headers["Content-Encoding"])
{
app.Request.Filter = new GZipStream(
app.Request.Filter, CompressionMode.Decompress);
}
}
public void Dispose()
{
}
}
Update: It appears that this approach trigger a problem in WCF, as WCF relies on the original Content-Length
and not the value obtained after decompressing.
Try Wiktor's answer to my similar question here:
How do I enable GZIP compression for POST (upload) requests to a SOAP WebService on IIS 7?
...but please note his implementation on his blog contained a couple of bugs / compatibility issues, so please try my patched version of the HttpCompressionModule class posted on the same page.
Although hacky, you can get around WCF using the original Content-Length
even after the request has been decompressed by setting the private _contentLength
field in the HttpRequest
class using reflection. Using Joannes Vermorel's code:
void BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if ("gzip" == app.Request.Headers["Content-Encoding"])
{
app.Request.Filter = new GZipStream(
app.Request.Filter, CompressionMode.Decompress);
// set private _contentLength field with new content length after the request has been decompressed
var contentLengthProperty = typeof(HttpRequest).GetField("_contentLength", BindingFlags.NonPublic | BindingFlags.Instance);
contentLengthProperty.SetValue(app.Request, (Int32)app.Request.InputStream.Length);
}
}
精彩评论