これは mod_mruby ngx_mruby Advent Calendar 2014 の18日目(12/18)の投稿です。
この投稿の位置づけとしては、アドベントカレンダーの16日目に書いた記事(静的リソースをリバースプロキシで配信する)の応用編です。
Apache では、リバースプロキシしたコンテンツに対して、更に出力フィルタをかけて処理することが出来ます。(有名な出力フィルタだと mod_deflate など。)
イメージは次のとおり。
Apache のフィルタについての説明はこちら。ちなみにコンテンツハンドラ(例:PHP、Perl)の前に起動されるのが入力フィルタで、後に起動されるのが出力フィルタです。
⇒ http://httpd.apache.org/docs/current/ja/filter.html
もちろん mod_mruby でもフィルタを作成できますので、同様にリバースプロキシしたコンテンツに対して任意のフィルタ処理をすることが可能です。
mod_mruby でのプロキシの設定については16日目に書いたので、今回はWEBサービスにおける通信の削減を目的としたフィルタの設定を2例、紹介します。
前提となる環境はアドベントカレンダーの3日目、Apache のディレクティブ設定や mod_mruby スクリプトの例は10日目に書いたので、宜しければそちらも参照ください。
⇒ mod_mruby を Amazon EC2、Apache2.4 へ導入する(Apache のバージョンは2.4.10
、mod_mruby のバージョンは1.9.7
です)
⇒ mod_mruby の可能性とディレクティブ設定/スクリプトの例
① リバースプロキシしたコンテンツのHTTPレスポンスヘッダを操作
リバースプロキシ先から返ってきた画像ファイルに対し、mod_mruby で Cache-Control
ヘッダを操作して、ブラウザにキャッシュさせる時間を任意に指定する例です。
r = Apache::Request.new
if /\.(gif|jpe?g|png)$/ =~ r.filename
r.headers_out['Cache-Control'] = 'max-age=20'
end
この例だと 20秒だけブラウザにキャッシュさせます。上記のスクリプトを出力フィルタとしてフックします。
SetOutputFilter mruby
mrubyOutputFilter /usr/local/apache2/mruby/respose_header.rb
するとブラウザへのHTTPレスポンスヘッダは次のようになります。
(リバースプロキシ先は GitHub Pages の例です。)
フィルタのディレクティブ設定については公式ページをご覧ください。
⇒ http://httpd.apache.org/docs/current/ja/filter.html
<Files>
等のディレクティブと組み合わせたり、.htaccess
に書いたりもできます。また上記の例ではスクリプト内で拡張子を判定していますが、拡張子をキーに出力フィルタを定義することも出来ると思います。
ただ出力フィルタのフェーズで Apache の HTTPリクエストやヘッダにアクセスするのは行儀が悪いかも^^; まあこういう設定もできるよということで..
② リバースプロキシしたコンテンツを gzip 圧縮して配信
静的コンテンツを gzip 圧縮して、ネットワーク帯域を節約します。gzip 圧縮は mod_deflate を利用します。ちなみに mod_deflate が何をしてくれるかというと、ブラウザが gzip 圧縮に対応している場合は次のようなヘッダを送ってくるので、
mod_deflate はコンテンツを圧縮して送出し、ヘッダは次のように返します。ブラウザはこれで圧縮されたコンテンツだと判断し解凍します。
もし mod_deflate がサーバに入ってない(mod_deflate.so が存在しない)場合は、次のように configure し直してから Apache を再コンパイルすると導入できます。
$ ./configure --enable-deflate
設定方法については、まず .conf
ファイルにて mod_deflate を有効にします。
LoadModule deflate_module modules/mod_deflate.so
例として PNG 形式の画像ファイルを gzip 圧縮する場合は次のようにします。
AddOutputFilterByType DEFLATE image/png
するとブラウザへのHTTPレスポンスヘッダは次のようになります。
(これもリバースプロキシ先は GitHub Pages の例です。)
ちなみにフィルタは複数を併用できるので、例えば上記の①②を同時に設定することもできます。
おわりに
今回は mod_mruby でリーバスプロキシしたコンテンツに対して、更に通信の削減を目的としたフィルタを適用する例を紹介しました。
これ以外にも、フィルタで色々できそうです。mod_mruby では最も簡単なフィルタは次のように書けます。(何もしないコード。)下記の例だと、変数 content
には HTTPレスポンスのコンテンツ内容(HTML、JavaScript、CSS、画像バイナリ、JSON、etc..)が格納されているので、ここで加工が出来ちゃいます。
ただ大きいコンテンツはメモリに注意と思われ。
f = Apache::Filter.new
content = f.flatten
f.cleanup
f.insert_tail content
f.insert_eos
またの機会に、スマホ用の画像変換をしてみようかなと^^
明日(12/19)は inokappa さんによる記事です!よろしくお願いします。