A month ago I challenged Simone to a friendly duel about who could get the best YSlow score. I did all sorts of things to improve the score but the one thing I never figured out was how to gzip compress the WebResource.axd handler. Then yesterday I was playing around with Fiddler and noticed that IE doesn’t cache WebResource.axd but loads it at every request to a page. Then I knew I had to do something about it and I might as well give the gzip compression another try.
I already have a HTTP compression module that works like a charm, so I just needed it to compress WebResource.axd and implement the right client cache mechanisms as well. Sounds simple right?
I knew this was my Achilles heel since I’ve failed at it before. Lucky for me, Miron Abramson just did it a week ago so I took a look at his solution. It was exactly what I needed, so I picked out the parts I needed and stuck them into my own compression module.
What Mirons code does is to create an HTTP request to the WebResource.axd, copy the response to a memory stream, compress it and serve it back to the client. That is a very clever approach but had a big problem. Every time the browser requested the WebResource.axd handler his module created an HTTP request. That was too big an overhead for me. I fixed it easily by caching the response at the first request and then served the compressed bytes from the cache from then on. Apart from that, his code rocks.
First of all I set the expires, last-modified and ETag HTTP headers that let’s any browser cache the response. Browsers are a little different when it comes to caching web resources so by specifying both an ETag and last-modified header takes care of them all.
Further more I added support for the If-None-Match request header. What it does is that when a page is refreshed by hitting F5 or similar, the browser sends the If-None-Match header to the server with the ETag as the value. Then I can simply check if the incoming ETag value is the same as the server ETag and terminate the response with a 304 Not modified response header.
That saves bandwidth and tells the browser to use the version from its cache instead of loading the content from the server again. The thing is that files served from WebResource.axd are always static so no harm can be done by using all means to let the browser cache them.
Get the CompressionModule.cs file below to compress both your pages and WebResource.axd handler.
PS. I won the YSlow challenge.