ngx_mruby の Nginx::Async::HTTP でハマったとこ

ngx_mruby にはノンブロッキングhttpリクエストできるNginx::Async::HTTPというものが用意されている。

外部からリクエストを受け付ける nginx(便宜上frontとする) とfrontからリクエストを受け付けるnginx(便宜上apiとする)を用意して Nginx::Async::HTTP を試してみた。

front の設定

user  nginx;
worker_processes  1;
load_module modules/ndk_http_module.so;
load_module modules/ngx_http_mruby_module.so;

events {
    worker_connections  1024;
}

master_process off;

http {
    include       mime.types;

    server {
        listen       80;
        server_name  localhost;

        location /sub_req_proxy_pass {
            proxy_pass http://nginx-api:8080/api;
        }

        location /front {
            mruby_rewrite_handler_code '
              Nginx::Async::HTTP.sub_request "/sub_req_proxy_pass"
              res = Nginx::Async::HTTP.last_response
              Nginx.rputs res.body
            ';
        }
    }
}

api の設定

user  nginx;
worker_processes  1;
load_module modules/ndk_http_module.so;
load_module modules/ngx_http_mruby_module.so;

events {
    worker_connections  1024;
}

master_process off;

http {
    include       mime.types;

    server {
        listen       8080;
        server_name  localhost;

        location /api {
            mruby_content_handler_code '
              Nginx.echo "Hello World"
            ';
        }
    }
}

上記の設定の nginx を立てて front にリクエストしたところ、レスポンスが返ってこなかった。

$ curl localhost:8000/front
curl: (52) Empty reply from server

ngx_mruby/nginx.conf at master · matsumotory/ngx_mruby · GitHub

この辺りを眺めているとサブリクエストでは mruby_output_body_filter ディレクティブをつけているので以下のようにサブリクエストのlocationディレクティブに mruby_output_body_filter ディレクティブを追加するとレスポンスが返ってくるようになった

location /sub_req_proxy_pass {
    proxy_pass http://nginx-api:8080/api;
    mruby_output_body_filter_code '';
}
$ curl localhost:8000/front
Hello World

知識不足でなぜ mruby_output_body_filterディレクティブ が必要なのかは理解できていないが、Nginx::Async::HTTP を利用してサブリクエストを行う場合、サブリクエストのlocationディレクティブで mruby_output_body_filter ディレクティブが必須のようだった