nginx で 内部リクエストを使ってコンテンツを書き換える
/user/xxx
のときは、普通に見せて、/user/json/xxx
のときは、JSONだけを返すような処理を nginxの前捌き(プロキシ)だけで実現したい。
Location と 内部リクエストを使って、コンテンツを書き換える.
location /a { default_type 'text/plain'; return 200 'a\n'; } location ~ /a/b(.+) { sub_filter 'a' 'x'; sub_filter_types *; sub_filter_once off; proxy_ssl_verify off; proxy_set_header Accept-Encoding ""; proxy_ssl_session_reuse on; proxy_set_header Host $server_name; proxy_pass https://127.0.0.1:443/$1; }
/a
へのリクエストはそのまま
$ curl -H example.tld http://localhost/a a
$ curl -H example.tld http://localhost/a/b.json x # ⇐ a がxにsubfilterされる
これで、内部リクエストの結果を書き換えることができる。
コレが意外と難しい。特定のアドレスのときだけ、コンテンツをsubfilterで書き換えたいとすると、自分自身に内部リクエストを送信する必要がある。
rewrite できない
rewrite
だと、sub_filterまで処理が届かず、コンテンツの中身を取れない。なぜなら、rewriteするとリクエスト書き換えて別のリクエストとして処理が始まるからだ。
lua でもうまくいかない。
lua
のngx.location.capture
だと、http/2 のリクエストでは動作がめんどくさい。nginx/luaモジュールをコンパイルし直しになる。やってられん。
proxy_pass を使う。
proxy_pass
だと内部でリクエストを生成するので、まだマシ。ほんとうはrewrite で転送時に、もとのPATHの処理へ戻ってきてくれればいいが、apacheならで来たと思うけど、nginxではできない。そういう再帰的なところを省いてるからnginx速いってのもあるし仕方ない。