ApacheにはコンテンツのMIME-typeに応じてフィルターをかけるAddOutputFilterByTypeディレクティブがありますが、Apache 2.1 以降で非推奨になり、代わりにmod_filterでフィルターをかけることが勧められているようです。
しかしながら、mod_filterの実例があまりにも少ないため、どう使っていいか分からないのが現状です。なので、AddOutputFilterByType DEFLATE text/htmlを書き換えてみることにしました。
mod_deflateのドキュメントには、実例として画像以外をすべて圧縮する方法が以下のように書かれています。
<Location /> # Insert filter SetOutputFilter DEFLATE # Netscape 4.x has some problems... BrowserMatch ^Mozilla/4 gzip-only-text/html # Netscape 4.06-4.08 have some more problems BrowserMatch ^Mozilla/4.0[678] no-gzip # MSIE masquerades as Netscape, but it is fine # BrowserMatch bMSIE !no-gzip !gzip-only-text/html # NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48 # the above regex won't work. You can use the following # workaround to get the desired effect: BrowserMatch bMSI[E] !no-gzip !gzip-only-text/html # Don't compress images SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary # Make sure proxies don't deliver the wrong content Header append Vary User-Agent env=!dont-vary </Location>
これをベースにMIME-typeがtext/*、application/xhtml、application/xmlの場合、deflateするようにしたものが以下になります。
<Location /> # Netscape 4.x has some problems... BrowserMatch ^Mozilla/4 gzip-only-text/html # Netscape 4.06-4.08 have some more problems BrowserMatch ^Mozilla/4.0[678] no-gzip # MSIE masquerades as Netscape, but it is fine BrowserMatch bMSIE !no-gzip !gzip-only-text/html # ここからフィルター設定 FilterDeclare Compression CONTENT_SET FilterProvider Compression DEFLATE Content-Type $text/plain FilterProvider Compression DEFLATE Content-Type $text/css FilterProvider Compression DEFLATE Content-Type $application/xhtml FilterProvider Compression DEFLATE Content-Type $application/xml FilterProvider Compression DEFLATE Content-Type $application/xhtml+xml FilterProvider Compression DEFLATE Content-Type $application/rss+xml FilterProvider Compression DEFLATE Content-Type $application/atom+xml FilterProvider Compression DEFLATE Content-Type $application/x-javascript FilterProvider Compression DEFLATE Content-Type $image/svg+xml FilterChain Compression # ここまでフィルター設定 # Don't append Vary heder for specific files SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|zip|lzh|exe)$ dont-vary # Make sure proxies don't deliver the wrong content Header append Vary User-Agent env=!dont-vary Header append Vary Accept-Encoding env=!dont-vary </Location>
まず、FilterDeclareディレクティブでCompressionという名前のフィルター群のタイプがCONTENT_SETであると宣言します(これはなぜそうする必要があるのかよく分からないので教えてください)。
次にFilterProviderディレクティブでCompressionフィルター群にフィルターを追加しています。FilterProviderディレクティブの第一引数はフィルター群に付ける名前(今回はCompression)、第二引数はフィルターのプロバイダー名です。mod_deflateモジュールを読み込むと、ap_register_output_filter関数でDEFLATEというプロバイダー名が自動的に登録されます(そのプロバイダーがdeflateを行います)。第三引数(Content-type $text/plain)はフィルターを実行する条件を指定するもので、今回はHTTPレスポンスヘッダのContent-typeがtext/plainに部分一致した場合のみ、フィルターを実行するという条件をつけています。
最後のFilterChainディレクティブでCompressionフィルター群がApacheのリクエストを通じて呼び出されるようにします(つまりFilterChainディレクティブを使わないと、定義されたフィルター群は実行されません)。
ここで気になるのが、BrowserMatchディレクティブで環境変数に設定したno-gzipやgzip-only-text/htmlがフィルター実行の条件の絞込み(FilterProviderディレクティブの第三引数)に使われていないということです。実はこれらの環境変数はmod_deflateモジュール内で参照され、たとえばno-gzipが設定されていた場合は、自動的にフィルターが外れるようになっています。