クエリ文字列パラメーターは、nginxでproxy_passを介してどのように転送できますか?


114
upstream apache {
   server 127.0.0.1:8080;
}
server{
   location ~* ^/service/(.*)$ {
      proxy_pass http://apache/$1;
      proxy_redirect off;
   }
 }

上記のスニペットは、URLに「service」という文字列が含まれるリクエストを別のサーバーにリダイレクトしますが、クエリパラメータは含まれません。

回答:


163

proxy_passドキュメントから:

特別なケースは、proxy_passステートメントで変数を使用することです。要求されたURLは使用されず、自分でターゲットURLを作成するのはユーザーの責任です。

ターゲットで$ 1を使用しているので、nginxは渡すものを正確に指示するためにあなたに依存します。これは2つの方法で修正できます。まず、proxy_passを使用してURIの先頭を削除するのは簡単です。

location /service/ {
  # Note the trailing slash on the proxy_pass.
  # It tells nginx to replace /service/ with / when passing the request.
  proxy_pass http://apache/;
}

または、正規表現の場所を使用する場合は、argsを含めます。

location ~* ^/service/(.*) {
  proxy_pass http://apache/$1$is_args$args;
}

1
私はあなたが後者を行うことができるとは思わない。私は試みました、そして、nginxは私に不平を言いました。
ドゥーマ

3
どのように不平を言いましたか?nginx 1.3.4でテストしたところ、問題なく動作しました。
kolbyjack

うーん..今は思い出せません:(しかし、「〜*」に関連している可能性があるようです。しかし、チェックしたところ、nginx 1.2.3(homebrew経由)を使用しています。たぶんそれだけですか?
duma

「proxy_redirect default」は、変数を含む「proxy_pass」ディレクティブと一緒に使用できません
Jean-Philippe Caruana

1
書き換えを使用する必要がある location /service/ { rewrite ^\/service\/(.*) /$1 break; proxy_pass http://apache; }
Andrew Arnautov

27

~代わりに、少し変更したバージョンのkolbyjackの2番目のアプローチを使用してい~*ます。

location ~ ^/service/ {
  proxy_pass http://apache/$uri$is_args$args;
}

10

私はそれが動作するように@kolbyjackコードを変更しました

http://website1/service
http://website1/service/

パラメータ付き

location ~ ^/service/?(.*) {
    return 301 http://service_url/$1$is_args$args;
}

1
これにより、リダイレクトする前にサーバーがクライアントに301応答を返すことに注意してください。上記のproxy_passディレクティブは、サーバー側でリダイレクトを行います。
ルーク・ピーターソン、

1
これは、クエリパラメータにURL(%)でエンコードされた文字が含まれていると機能しなくなります。代わりにAndrewの回答を使用してください。
デビッドウェバー

9

ここでは、rewriteを使用して、proxy_passを使用してパラメータを渡す必要があります。

S3静的Webサイトホスティングは、Index.htmlへのすべてのパスをルーティングします

あなたのニーズに合わせて

location /service/ {
    rewrite ^\/service\/(.*) /$1 break;
    proxy_pass http://apache;
}

最終的にhttp://127.0.0.1:8080/query/params/にしたい場合

最終的にhttp://127.0.0.1:8080/service/query/params/にし たい場合は、次のようなものが必要になります

location /service/ {
    rewrite ^\/(.*) /$1 break;
    proxy_pass http://apache;
}

1
これはパスparams(/path/params)をうまく処理しますが、クエリparams(?query=params)は処理しないようですか?
ウィル

ああ、間違いです。クエリパラメータは自動的に追加されます(これらは私のテスト段階です)。
ウィル

2

github gist https://gist.github.com/anjia0532/da4a17f848468de5a374c860b17607e7

#set $token "?"; # deprecated

set $token ""; # declar token is ""(empty str) for original request without args,because $is_args concat any var will be `?`

if ($is_args) { # if the request has args update token to "&"
    set $token "&";
}

location /test {
    set $args "${args}${token}k1=v1&k2=v2"; # update original append custom params with $token
    # if no args $is_args is empty str,else it's "?"
    # http is scheme
    # service is upstream server
    #proxy_pass http://service/$uri$is_args$args; # deprecated remove `/`
    proxy_pass http://service$uri$is_args$args; # proxy pass
}

#http://localhost/test?foo=bar ==> http://service/test?foo=bar&k1=v1&k2=v2

#http://localhost/test/ ==> http://service/test?k1=v1&k2=v2

1

クエリ文字列なしでリダイレクトするには、以下の行をリッスンポート行の下のサーバーブロックに追加します。

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/;
}

クエリ文字列あり:

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/?$query_string;
}

1
nginxのドキュメントはif、可能な限り使用しないように明示されています。この場合、location別の回答に示されているように、ソリューションは適切に使用できます。
アンドレスモラレス2017年

2
とにかく、欠点があるとしても、もう1つのソリューションの方が優れています
Dmitry Malugin

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.