コンテンツにスキップ

フィルタ

nginxは、レスポンスのヘッダとボディを2つのフィルタチェーンに通して送ります。レスポンスを作ったのがどのハンドラでも、upstreamでも同じです。ngx_mrubyは、それぞれのチェーンにフィルタを1つずつ加えます。ヘッダに対してRubyを実行するのはmruby_output_header_filterとその_codeの形で、ボディに対して実行するのはmruby_output_body_filterとその_codeの形です。設定に2つのディレクティブのどちらかがあると、ngx_mrubyはヘッダフィルタを加えます。ボディフィルタは、設定にボディフィルタのディレクティブがあるときに加えます。

nginxが呼ぶ順にヘッダフィルタとボディフィルタを並べ、ngx_mrubyのフィルタと、それぞれが受け取るものを示します。ngx_mrubyとnginxのソースの次の行から描きました。ngx_mrubyの行は、2026-10-19のコミット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が実行する両方のフィルタのサンプルがあります。フィルタの構文は、ディレクティブのリファレンスにあります。