それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

nginx で 内部リクエストを使ってコンテンツを書き換える。

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

/a/b へのリクエストは、a をリクエストして書き換え

$ curl -H example.tld http://localhost/a/b.json

x # ⇐ a がxにsubfilterされる

これで、内部リクエストの結果を書き換えることができる。

コレが意外と難しい。特定のアドレスのときだけ、コンテンツをsubfilterで書き換えたいとすると、自分自身に内部リクエストを送信する必要がある。

rewrite できない

rewriteだと、sub_filterまで処理が届かず、コンテンツの中身を取れない。なぜなら、rewriteするとリクエスト書き換えて別のリクエストとして処理が始まるからだ。

lua でもうまくいかない。

luangx.location.captureだと、http/2 のリクエストでは動作がめんどくさい。nginx/luaモジュールをコンパイルし直しになる。やってられん。

proxy_pass を使う。

proxy_passだと内部でリクエストを生成するので、まだマシ。ほんとうはrewrite で転送時に、もとのPATHの処理へ戻ってきてくれればいいが、apacheならで来たと思うけど、nginxではできない。そういう再帰的なところを省いてるからnginx速いってのもあるし仕方ない。

rewrite だともともとのユーザーリクエストがrewrite 先だったとしてしまう。