Compressing Web Content with mod_gzip and mod_deflate
The mod_gzip module is available for both Apache 1.3.x and Apache 2.0.x., and it can be compiled into Apache as a dynamic shared object (DSO) or as a static module. The compilation for a DSO is simple; from the uncompressed source directory, perform the following steps as root:
make APXS=/path/to/apxs make install APXS=/path/to/apxs /path/to/apachectl graceful
mod_gzip must be loaded last in the module list, as Apache 1.3.x processes content in module order, and compression is the final step performed before data is sent. mod_gzip installs itself in the httpd.conf file, but it is commented out.
A basic configuration for mod_gzip in the httpd.conf should include:
This allows PostScript files to be GZIP-encoded, while not compressing PDF files. PDF files should not be compressed; doing so leads to problems when attempting to display the files in Adobe Acrobat Reader. To be even more careful, you may want to exclude PDF files explicitly from being compressed:
mod_gzip_item_eclude mime ^application/pdf$
The mod_deflate module for Apache 2.0.x is included with the source for this server, which makes compiling it into the server rather simple:
./configure --enable-modules=all \ --enable-mods-shared=all --enable-deflate make make install
With mod_deflate for Apache 2.0.x, the GZIP encoding of documents can be enabled in one of two ways: explicit exclusion of files by extension or explicit inclusion of files by MIME type. These methods are specified in the httpd.conf file. Explicit exclusion looks like:
SetOutputFilter DEFLATE DeflateFilterNote ratio SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ \ no-gzip dont-vary SetEnvIfNoCase Request_URI \ \.(?:exe|t?gz|zip|bz2|sit|rar)$ \ no-gzip dont-vary SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
Explicit inclusion looks like:
DeflateFilterNote ratio AddOutputFilterByType DEFLATE text/* AddOutputFilterByType DEFLATE application/ms* \ application/vnd* application/postscript
In the explicit exclusion method, the same exclusions are present as in the mod_gzip file, namely images and PDF files.
If your site uses dynamic content—XSSI, CGI and the like—nothing special needs to be done to compress the output of these modules. As mod_gzip and mod_deflate process all outgoing content before it is placed on the wire, all content from Apache that matches either the MIME types or the file extensions mapped in the configuration directives is compressed.
The output from PHP, the most popular dynamic scripting language for Apache, also can be compressed in one of three possible ways: using the built-in output handler, ob_gzhandler; using the built-in ZLIB compression; or using one of the Apache compression modules. Configuring PHP's built-in compression is simply a matter of compiling PHP with the --with-zlib configure option and then reconfiguring the php.ini file.
Below is what the output buffer method looks like:
output_buffering = On output_handler = ob_gzhandler zlib.output_compression = Off
The ZLIB method uses:
output_buffering = Off output_handler = zlib.output_compression = On
The output buffer method produces marginally better compression, but both methods work. The output buffer, ob_gzhandler, also can be added on a script-by-script basis, if you do not want to enable compression across the entire site.
If you do not want to reconfigure PHP with ZLIB enabled, the Apache compression modules can compress the content generated by PHP. I have configured my server so that Apache modules handle all of the compression, and all pages are compressed in a consistent manner, regardless of their origin.
Can compressed content be cached? The answer is an unequivocal yes. With mod_gzip and mod_deflate, Apache sends the Vary header, indicating to caches that this object differs from other requests for the same object based on certain criteria—user-agent, character set and so on. When a compressed object is received by a cache, it notes that the server returned a Vary: Accept-Encoding response. This response indicates it was generated based on the request containing the Accept-Encoding: gzip header.
Caching compressed content can lead to a situation where a cache stores two copies of the same document, one compressed and one uncompressed. This is a design feature of HTTP 1.1, and it allows clients with and without the ability to receive compressed content to benefit from the performance enhancements gained from local proxy caches.