Apache deflation and negotiation
Friday, April 17, 2009 - 04:38 PM
Sometimes, wasting time isn't entirely unproductive.
This week, while thinking of getting work done on some longer term projects that are standing nearby and mocking me, I somehow got conned into installing Yahoo's YSlow Firefox extension.
The idea is to auto-compress any text being served back so that the payload delivered to the clients (you and your web browser) is smaller, gets to you faster, and loads faster. Computers are fast enough, and the files are small enough that the compression speed-hit is far outweighed by the network latency speed-gain.
As an added bonus, since the server has to hold the network connection, with all it's associated memory and resource usage, open until the client is finished getting all its content, this frees up those resources a little bit faster.
Compress only a few types
AddOutputFilterByType DEFLATE text/html text/plain text/xml
Nifty! Now let's check the documentation for AddOutputFilterByType:
Compatibility: Available in Apache 2.0.33 and later; deprecated in Apache 2.1 and later
I'm running Apache 2.2 (which is also what all the documentation links point to), so I probably shouldn't start by implementing this with a deprecated config directive.
It does point us in the direction of its replacement, the mod_filter module. Reading through all this documentation is not entirely unconfusing, as there are a lot of parts without a very coherent picture of a whole. At the end of the day, what it comes down to is that I need to first define my filter, and then apply it where and how I want to. To define it, I put at the top of my config:
FilterProvider compress-response DEFLATE resp=Content-Type $text/
Nice and easy!
For the purposes of full disclosure, there's also some stuff in the mod_deflate documentation that I used for determining browsers where this will and won't work, so the full set of directives is:
# Insert filter
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0 no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary
I'll probably eliminate a bunch of those at some point as I don't think we need to worry about Netscape 4 a whole lot these days.
This worked, and made me happy. It's been live for most of this week, and nobody noticed, commented, or complained. Success!
I'm about a decade too late to be the first person to think of this, so it's also conveniently built into Apache. Content Negotiation also supports sending back pages in multiple languages, but for my purposes I wanted to send back a ".gz" file instead of a ".js" if there was one available. The two important things to do are: add
MultiViews to your enabled Options, and do an
AddEncoding for the .gz files:
AddEncoding x-gzip .gz
I also had to add the
ForceType directive, because otherwise the .gz version of the file would be served back with
If you want to test this using curl from the command line, add "
-H "Accept-Encoding: gzip,deflate"" to your requests, e.g.:
curl -vI -H "Accept-Encoding: gzip,deflate" http://www.dumbrellahosting.com/
As a final remark, I'm pretty sure that most of the above is pretty obvious to all good Apache administrators. However, for those of us doing that as just one part of a larger job, it seems remarkably difficult to find a coherent set of task-oriented how-tos. Mostly I document this so I'll remember what the hell I was thinking when I look at this config again next year.
Hell, let's face it, we're not responsible for anything; including the things we say, do, or think. And if you sue us because you think we are? Well, we're not responsible for that either.