フィルタ
nginxは、レスポンスのヘッダとボディを2つのフィルタチェーンに通して送ります。レスポンスを作ったのがどのハンドラでも、upstreamでも同じです。ngx_mrubyは、それぞれのチェーンにフィルタを1つずつ加えます。ヘッダに対してRubyを実行するのはmruby_output_header_filterとその_codeの形で、ボディに対して実行するのはmruby_output_body_filterとその_codeの形です。設定に2つのディレクティブのどちらかがあると、ngx_mrubyはヘッダフィルタを加えます。ボディフィルタは、設定にボディフィルタのディレクティブがあるときに加えます。
ヘッダフィルタ
nginxのnot modifiedのヘッダフィルタ
mruby_output_header_filter:nginxのほかのモジュールのヘッダフィルタ
nginxがヘッダを書き出す
ボディフィルタ
nginxのrangeとcopyのボディフィルタ
mruby_output_body_filter:Content-Lengthのnginxのほかのモジュールのボディフィルタ
nginxのwriteフィルタがボディを送る
0c72e3970の行です。src/http/ngx_http_mruby_module.cの591行から595行、1676行から1677行、1955行から1965行、2041行から2054行、2085行から2122行、2135行から2154行config.inの48行から69行- nginx 1.31.6のソースツリーにある
auto/modulesの165行から187行、386行から427行、1494行から1495行 - nginx 1.31.6のソースツリーにある
auto/moduleの23行から30行
- nginxは、各チェーンのフィルタを先頭から順に呼びます。ngx_mrubyのフィルタは、nginxのnot modifiedのヘッダフィルタと、rangeとcopyのボディフィルタの後に動きます。また、
gzipやchunkedのフィルタのような、nginxのほかのモジュールのフィルタより先に動きます。そのため、ngx_mrubyのフィルタは、nginxが圧縮したりチャンクに分けたりする前のレスポンスを受け取ります。nginxは、auto/modulesに並んだモジュールの順にチェーンを組みます。その順では、ngx_mrubyはnginx自身のフィルタのモジュールの後、copy、range body、not modified、sliceの各フィルタの前にあります。チェーンを組むとき、nginxは各フィルタを、それより前に並んだフィルタの手前に入れます。sliceのフィルタは、--with-http_slice_moduleを付けたビルドにだけあります。 - ヘッダフィルタは、
Nginx::RequestとNginx::Headers_outでステータスとヘッダを読み、書き換えます。ヘッダフィルタはボディを読む前に動くので、そこではNginx::Filter#bodyは空の文字列を返します。 - ボディフィルタの処理には、レスポンスの長さが要ります。
Content-Lengthのあるレスポンスでは、ngx_mrubyはボディ全体を1つのバッファに集め、そのボディをNginx::Filter#bodyに入れてスクリプトを1回実行します。そして、ngx_mrubyは、スクリプトがNginx::Filter#body=に入れたものを送ります。upstreamのチャンク形式のレスポンスのような、Content-Lengthの無いレスポンスは、読まれずにフィルタを通ります。ngx_mrubyは、そのことをnoticeのレベルでログに書きます。 - locationにボディフィルタがあると、ngx_mrubyは、ボディフィルタが動き終わるまでヘッダを送らずに待ちます。こうして、
Content-Lengthを新しいボディの長さにします。 - どちらのフィルタでも待てません。フィルタの中では、
Nginx::Async.sleepとNginx::Async::HTTP.sub_requestはRuntimeErrorを起こし、Nginx.rputsとNginx.echoは使えません。
ガイドのレスポンスのボディを変えるには、CIが実行する両方のフィルタのサンプルがあります。フィルタの構文は、ディレクティブのリファレンスにあります。