Can I detect if content has been compressed in my HttpModule?
I have an HttpModule which is used to dynamically compress content from an ASP.NET (MVC3) web application. The approach is very similar to the CompressionModule in this article (where the module applies a GZip filter to the HttpResponse and sets the correct Content-encoding header).
For one reason and another, this needs to run in classic mode, not integrated pipeline mode.
The problem I've got, is that on some servers that have IIS compression enabled, IIS compresses the content and then my module compresses that.
The upshot is that I get content compressed twice, with an encoding:
Content-encoding: gzip,gzip
one from IIS, and one from this line in my code:
httpResponse.AppendHeader("Content-encoding", "gzip");
Does anyone know a way, in classic mode, that I can check to see if the content is already compressed, or if compression is enabled on the server, in order to bypass my own compression?
In pipeline mode, this check is as simple as
if (httpResponse.Headers["Content-encoding"]!= null)
{
return;
}
i.e. check if anything has already set a content-encoding and 开发者_运维百科if so, do nothing.
However, I'm stumped in classic mode. Unfortunately, accessing HttpResponse.Headers
is not allowed in classic mode, so I can't do my barrier check.
All ideas gratefully received.
Theoretically, you can use reflection to peek into HttpRequest._cacheHeaders
field, where ASP.NET apparently stores all yet-to-be sent headers in classic mode:
if (this._wr is IIS7WorkerRequest)
{
this.Headers.Add(HttpResponseHeader.MaybeEncodeHeader(name), HttpResponseHeader.MaybeEncodeHeader(value));
}
else if (flag)
{
if (this._cacheHeaders == null)
{
this._cacheHeaders = new ArrayList();
}
this._cacheHeaders.Add(new HttpResponseHeader(knownResponseHeaderIndex, value));
}
I found a relatively easy way to check if the output is already compressed or not; my approach works even with IIS running in classic mode and although it may be considered a "hack" I found it to be working quite consistently; the idea is more or less the following
// checks if the response is already compressed
private bool IsResponseCompressed(HttpApplication app)
{
string filter = app.Response.Filter.ToString().ToLower();
if (filter.Contains("gzip") | filter.Contains("deflate"))
{
return true;
}
return false;
}
basically the code works by checking the response filter name; if the output stream is compressed the name contains "gzip" or "deflate" so it's easy to check for compression
精彩评论