6

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.

1
  • I think you can only do this via an ISAPI module in classic mode. Mar 25, 2011 at 15:54

2 Answers 2

2

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));
}
4
  • indeed - although really hoping not to use reflection for this piece of production code that would be called on every single request.
    – Rob Levine
    Mar 28, 2011 at 12:02
  • 1
    @Rob Try this approach ( rogeralsing.com/2008/02/26/… ) with compiled lambdas. Seems to make a huge perf difference. Mar 28, 2011 at 12:06
  • Now that is an interesting approach - I'll give that a go.
    – Rob Levine
    Mar 28, 2011 at 12:20
  • This does not work for me. The _headers field of the response object is returned as null. Dec 6, 2013 at 8:18
1

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

1
  • 1
    This does not work for me. Response.Filter is a Stream and .ToString() simply returns the name of the Stream-class. Dec 6, 2013 at 7:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.