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をお送りしていますがどーなることやら。また、僕が根本的に勘違いをしていて実は設定上の変更で対応できる、というお話の場合は失礼。
