mod_layoutで動的なContent-Typeもきちんとチェックさせる方法。ダイナミックに出力した画像やxmlが書換えられて困る人へ。
mod_layoutの動作
mod_layoutは配信されるHTMLに、広告やCopyrightなどのメッセージを自動的に埋め込むために利用されるApacheモジュールです。このモジュールは静的なファイルのみならず、CGIやPHPやJava Servlet等々動的に出力されるコンテンツも書換えることができます。mod_layoutはApacheがコンテンツを送信する一つ手前のfixupフェーズに介入し、対象となるURIへのリクエストをlayoutハンドラで処理するようr->handlerを書換えます。その後コンテンツの配信をlayoutハンドラが行うことになります。この際CGIやPHPなどへのリクエストの場合は ap_sub_req_method_uri() を発行し、本来のハンドラ(この場合CGIやPHP)を呼び出して動的なコンテンツを取得します。
layoutハンドラは取得したコンテンツが静的か動的かに関わらず、所定のルールに基づいて書き換えた後にクライアントに配送します。
静的なコンテンツはfixupフェーズの時点でcontent_typeが確定しているため、image/pngやapplication/xmlなどmod_layoutが通常は相手にしないコンテンツに対しては介入しません。しかし動的なコンテンツのcontent_typeはCGIプログラム等を実行した後に確定するため、fixupフェーズで事前にチェックすることはできませんん。このため動的に出力する画像やRSSなど書換えられては困るコンテンツまでmod_layoutが処理してしまう問題が起こりえます。
もちろん
LayoutIgnoreURI *nolayout*.cgiなど、特定のURIではmod_layoutが介入しないようにも設定できますが、本来はlayoutハンドラが動的に取得したコンテンツのContent-Typeヘッダをチェックして、介入する or しないといった判定処理が必要だと思います。
ちなみにmod_layoutバージョン3.2.1ではこの類いのチェックは実装されていません。
ヘッダをチェックする
mod_layoutのlayoutハンドラ(layout_handler)は、動的なコンテンツをlayout_origin()関数で取得し、チェックを行った後に書き換え処理を行っています。このチェックの段階(mod_layoutのis_ignored関数)でコンテンツのContent-Typeヘッダを調べれば目的を達成することができそうです。*** utility.c Sat Aug 30 07:49:54 2003 --- utility.c.new Thu Apr 15 00:17:46 2004 *************** *** 499,504 **** --- 499,514 ---- } LAYOUT_EXPORT(int) is_ignored(request_rec *r, layout_conf *cfg, layout_request *info, char *body) { + char *type, *tsep; + + /* Check to Content-Type */ + type = ap_pstrdup(r->pool, info->type); + if((tsep = strchr((const char *)type, ';')) != NULL) + *tsep = '\0'; + if(!table_find(cfg->types, type)) { + return 1; + } + if(cfg->tag_ignore) { if(table_search(r, cfg->tag_ignore, body)){ info->header = OFF;このpatchをmod_layout 3.2.1のutility.cにあてるだけです。えーっと言うまでもありませんがコーディングスタイルを作者に合わせた結果なので、
if(とかは僕の趣味ではありませんので注意。
動的コンテンツのContent-Typeは、mod_layoutのlayout_requestポインタのtypeフィールドで参照できます。ただし、Content-Typeヘッダにcharsetオプションを付与したり
AddDefaultCharset EUC-JPなどと設定している場合は
Content-Type: text/xml; charset=EUC-JPなどと出力されることになるので、';'以降の文字列を切り落としてチェックする必要があります。
作者のBrian Aker氏には一応patchをお送りしていますがどーなることやら。また、僕が根本的に勘違いをしていて実は設定上の変更で対応できる、というお話の場合は失礼。