このURLにアクセスすると:http://localhost:8080/foo/%5B-%5D
サーバー(nc -l 8080
)はそのまま受け取ります。
GET /foo/%5B-%5D HTTP/1.1
ただし、nginx(1.1.19)を介してこのアプリケーションをプロキシすると、次のようになります。
location /foo {
proxy_pass http://localhost:8080/foo;
}
Nginxポート経由でルーティングされた同じリクエストは、パスがデコードされて転送されます。
GET /foo/[-] HTTP/1.1
GETパス内のデコードされた角括弧は、エスケープされずに到着するため、ターゲットサーバーでエラー(HTTPステータス400-パス内の不正な文字...)を引き起こしています。
ターゲットサーバーがnginx経由でルーティングされたときにまったく同じパスを取得するように、URLのデコードを無効にするかエンコードして戻す方法はありますか?巧妙なURL書き換えルール?
引用 Valentin V. Bartenev (この回答に対して完全なクレジットを取得する必要があります):
documentation からの引用:
Proxy_passが指定されている場合with URI、リクエストをサーバーに渡すときに、場所に一致するnormalizedリクエストURIの一部がディレクティブで指定されたURIに置き換えられます
proxy_pass
が指定されているRIなし、元の要求の処理時にクライアントが送信したのと同じ形式で要求URIがサーバーに渡されますあなたの場合の正しい設定は:
location /foo { proxy_pass http://localhost:8080; }
Nginxのドキュメント内で一般的に$uri
"normalization"として知られているURLデコードは、バックエンドIFFの前に発生することに注意してください:
末尾のスラッシュだけですべてのURIを指定した場合でも、proxy_pass
自体の中でURIを指定するか、
または、URIは処理中に変更されます(例:rewrite
)。
両方の条件は http://nginx.org/r/proxy_pass に明示的に文書化されています(鉱山を強調):
proxy_pass
ディレクティブが指定されている場合URIで、リクエストが渡されたときサーバーに対して、場所に一致するnormalizedリクエストURIの一部は、指定されたURIに置き換えられますディレクティブで
proxy_pass
が指定されている場合URIなし、リクエストURIはサーバーに渡されます元の要求が処理されるときにクライアントによって送信されるのと同じ形式で、または完全な正規化リクエストURIが渡されるwhenが変更されたURI
解決策は、OPの場合のようにURIを省略するか、実際に賢い rewrite
ルールを使用することです。
# map `/foo` to `/foo`:
location /foo {
proxy_pass http://localhost:8080; # no URI -- not even just a slash
}
# map `/foo` to `/bar`:
location /foo {
rewrite ^ $request_uri; # get original URI
rewrite ^/foo(/.*) /bar$1 break; # drop /foo, put /bar
return 400; # if the second rewrite won't match
proxy_pass http://localhost:8080$uri;
}
関連するスタックオーバーフローの回答でライブ表示する (コントロールグループを含む)。