2015年3月9日月曜日

Headersモジュール: Header ディレクティブの処理対象レスポンスヘッダテーブル

ちょっと、調べたことをメモする。

参考: http://httpd.apache.org/docs/2.4/en/mod/mod_headers.html#header

Headerディレクティブは指定子の直後に、省略可能なパラメータとしてconditionを取ることになっている。
conditiononsuccessalwaysを指定できる。
省略した場合はonsuccessを指定したことになる。

これは、マニュアルに書かれている通り、レスポンスヘッダ情報を持つ内部テーブルを指定する。
内部テーブルは2つあってrequest_recの持つテーブルだ。


(httpd-2.4.9/include/httpd.h)

    781 struct request_rec {
    :
    911     /** MIME header environment for the response */
    912     apr_table_t *headers_out;
    913     /** MIME header environment for the response, printed even on errors and
    914      * persist across internal redirects */
    915     apr_table_t *err_headers_out;
    :

condition毎の処理対象のテーブルは以下の通りの対応になっている。

onsuccess headers_out
always err_headers_out

厄介なことに、"成功時"、"常時"、といった意味のconditionのパラメータになっているが、
必ずしも、その字義通りの条件で機能しない。
私の把握する限りでは、CGIスクリプトの返すレスポンスヘッダの多くは、err_headers_outテーブルにセットされる(Locationや、Content-Lengthなどheaders_outにセットされるものもある)。
mod_proxy_ajpから返されるレスポンスヘッダのほとんどは、逆にheaders_outにセットされる。

つまり mod_proxy_ajpで繋いだ先のTomcatが
X-RESPONSE-HEADER: this is test
というレスポンスを返した場合、このヘッダ情報は、headers_outに格納されることになる。

もし、
Header onsuccess append X-RESPONSE-HEADER "set at Apache"
と指定すると、最終的なレスポンスヘッダは、
X-RESPONSE-HEADER: this is test, set at Apache
となる。

これは、headers_outテーブルに対して存在するX-RESPONSE-HEADERヘッダ情報に対して処理が行われたためだ。

他方、同じヘッダをmod_cgid経由で実行されるCGIスクリプトが返した場合、
レスポンスのヘッダは、
X-RESPONSE-HEADER: this is test
X-RESPONSE-HEADER: set at Apache
と2行になってしまう。

CGIスクリプトから返されたヘッダは、err_headers_outテーブルに格納されるが、
一方、Headersディレクティブは、headers_outテーブルにappendが指示されている。
そのため、結局2つのテーブルに同じヘッダが作成されてしまうことになってしまう。
そして、最後にレスポンスを返す時、この2つのテーブルがマージされるためにこうなってしまっている。

もし逆に、
Header always append X-RESPONSE-HEADER "set at Apache"
とalwaysを指定した場合、
mod_proxy_ajp経由だと、次のようなヘッダになる。
X-RESPONSE-HEADER: set at Apache
X-RESPONSE-HEADER: this is test
mod_cgid経由だと、次のようなヘッダになる。
X-RESPONSE-HEADER: this is test, set at Apache

onsuccessの結果が分かれば、こちらは予想通りだろう。
これは、httpd-2.2系でも同じだ。