web-dev-qa-db-ja.com

nginxプロキシでのURLデコードの無効化

この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書き換えルール?

21

引用 Valentin V. Bartenev (この回答に対して完全なクレジットを取得する必要があります):

documentation からの引用:

  • Proxy_passが指定されている場合with URI、リクエストをサーバーに渡すときに、場所に一致するnormalizedリクエストURIの一部がディレクティブで指定されたURIに置き換えられます

  • proxy_passが指定されているRIなし、元の要求の処理時にクライアントが送信したのと同じ形式で要求URIがサーバーに渡されます

あなたの場合の正しい設定は:

location /foo {
   proxy_pass http://localhost:8080;
}
19

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;
}

関連するスタックオーバーフローの回答でライブ表示する (コントロールグループを含む)。

3
cnst