いくつかのTomcatの前で、nginxをロードバランサーとして使用します。着信リクエストでは、クエリパラメータをエンコードしています。ただし、リクエストがTomcatに到着すると、パラメーターはデコードされます。
nginxへの着信リクエスト:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http%3A%2F%2Fwww.google.com%2F"
tomcatへの着信リクエスト:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http:/www.google.com/"
その場合、Tomcatは405エラーをスローするため、要求パラメーターを変換したくありません。
私のnginx設定は次のとおりです:
upstream tracking {
server front-01.server.com:8080;
server front-02.server.com:8080;
server front-03.server.com:8080;
server front-04.server.com:8080;
}
server {
listen 80;
server_name tracking.server.com;
access_log /var/log/nginx/tracking-access.log;
error_log /var/log/nginx/tracking-error.log;
location / {
proxy_pass http://tracking/webapp;
}
}
現在のApacheロードバランサーの構成には、エンコードされたパラメーターを保持する AllowEncodedSlashes ディレクティブがあります。
AllowEncodedSlashes NoDecode
Apacheからnginxに移行する必要があります。
私の質問はこの質問とは正反対です: proxy_pass でnginxがクエリパラメータをエスケープしないようにします
私は最終的に解決策を見つけました: $request_uri
パラメータ :
location / {
proxy_pass http://tracking/webapp$request_uri;
}
そのようにして、元のリクエストでエンコードされた文字はnotデコードされません。つまり、プロキシされたサーバーにそのまま渡されます。
Jeanの答え は良いですが、サブロケーションでは機能しません。その場合、より一般的な答えは次のとおりです。
location /path/ {
if ($request_uri ~* "/path/(.*)") {
proxy_pass http://tracking/webapp/$1;
}
}
Nginx proxy_pass ディレクティブには、文書化されたオプションが1つあります
未処理の形式でURIを送信する必要がある場合、ディレクティブproxy_passを使用する必要がありますURI部分なし:
location /some/path/ {
proxy_pass http://127.0.0.1;
}
あなたの場合、このようになります。リクエストURIが上流サーバーに渡されることを心配しないでください
location / {
proxy_pass http://tracking;
}
それが役に立てば幸い。
一般に$uri
"normalisation"として知られているURLデコードは、nginxのドキュメント内で、バックエンドIFFの前に発生することに注意してください。
末尾のスラッシュだけがすべて単独である場合でも、proxy_pass
自体内でURIを指定するか、
または、URIは処理中に変更されます(例:rewrite
を使用)。
両方の条件は http://nginx.org/r/proxy_pass (emphasis mine)で明示的に文書化されています:
proxy_pass
ディレクティブがとURIで指定されている場合、リクエストが渡されたときサーバーに対して、場所に一致するnormalizedリクエストURIの部分は、指定されたURIに置き換えられます指令で
proxy_pass
が指定されている場合URIなし、リクエストURIはサーバーに渡されます元のリクエストが処理されるときにクライアントによって送信されたものと同じ形式で、orフルnormalizedリクエストURIが渡されるwhen処理変更されたURI
解決策は、フロントエンドとバックエンドの間でURLを変更する必要があるかどうかによって異なります。
URIの変更が必要ない場合:
# map `/foo` to `/foo`:
location /foo {
proxy_pass http://localhost:8080; # no URI -- not even just a slash
}
それ以外の場合、フロントエンドの/api
をバックエンドの/app
と交換またはマッピングする必要がある場合、 $request_uri
から元のURIを取得できます。 =変数、およびDFAに似た$uri
変数に対してrewrite
ディレクティブを使用します(ところで、rewrite
DFAアクションをさらに必要とする場合は、 mdoc.s )。誰かが2番目の書き換えルールを回避しようとする場合、return 400
のようなものと一致しないため、//api/
部分が必要であることに注意してください。
# map `/api` to `/app`:
location /foo {
rewrite ^ $request_uri; # get original URI
rewrite ^/api(/.*) /app$1 break; # drop /api, put /app
return 400; # if the second rewrite won't match
proxy_pass http://localhost:8080$uri;
}
バックエンドにプレフィックスを追加するだけの場合は、$request_uri
変数をすぐに使用できます。
# add `/webapp` to the backend:
location / {
proxy_pass http://localhost:8080/webapp$request_uri;
}
関連する回答 もご覧ください。これは、上記と同様のコードのいくつかのテスト実行を示しています。