やりたいこと
いろいろあって、nginxでリバースプロキシしているときに、upstreamから渡ってくるlocationヘッダの中身を書き換えないといけない場面に出くわしました。
普通ならproxy_redirectでどうにかするものですが、upstreamが返してくるlocationヘッダが自分の管理しているサイトとは全然別のところで、それをどうにか書き換えないといけません。ちなみにいじっている環境はモジュールが導入できないので、デフォルトで有効になっている機能でどうにかする必要があります。
やりたいことを図にするとこんな感じですね。
これを
upstream--(Location: http://example.com?hogehoge)--> nginx--> クライアント
こうしたい。
upstream--(Location: http://example.com?hogehoge)--> nginx (Location: http://example.jp?hogehoge)--> クライアント
失敗した方法
最初「if使って書き換えればいいじゃん」と思って試したのが以下。
location / {
if ($upstream_http_location ~ example.com(.*)){
proxy_hide_header location;
add_header location http://example.jp$1;
}
}
おそらくifの評価タイミングが$upstream_http_locationに値が設定される後ではなく前のため、どう頑張っても評価がfalseになってしまいました。そもそもlocation内でifを使うのは事故の元なのであんまりよくないです。
If Is Evil | NGINX
期待通りに動作した方法
じゃあmapならどうだと思って試したのが以下。
map $upstream_http_location $location{
~example.com(.*) http://example.jp$1;
default $upstream_http_location;
}
location / {
proxy_hide_header location;
add_header location $location
}
動きました。ifは評価タイミングがクライアントからリクエストを受けた直後で、mapはレスポンス返す直前なのかな…。そこは理解できていません。
Module ngx_http_rewrite_module
Module ngx_http_map_module