🐥

nginxのlocationでデコードされた文字をエンコードし直したい

2022/03/06に公開

はじめに

nginxのlocationディレクティブはデコードなどをされたURIに対して行われる。

The matching is performed against a normalized URI, after decoding the text encoded in the “%XX” form, resolving references to relative path components “.” and “..”, and possible compression of two or more adjacent slashes into a single slash.

nginx documentation

環境

nginx 1.20.2

問題

以下のような設定では、デコードされていると困る。

location ~ /([^/]+)/foo/(.*) {
  proxy_pass http://proxied.example/$1/$2;
}

正規表現でキャプチャして格納された変数の値はデコードされているので、これをproxy_passに使うと、URIに使えない文字が含まれている場合エラーとなる。

対応

setディレクティブを使う。

location ~ /([^/]+)/foo/(.*) {
  set $x $1;
  set $y $2;
  proxy_pass http://proxied.example/$x/$y;
}

setディレクティブは見ての通り第2引数を第1引数の変数に格納する。このとき、setした変数がURIの一部に使われることを考えてか、エンコードしてくれるようだ。

参照 stackoverflow

Discussion