web-dev-qa-db-ja.com

Cookieを使用してNginxプロキシターゲットを制御していますか?

興味深いApache mod_rewrite設定を使用してリバースプロキシを変換し、代わりにNginxを使用しようとしています(外部の懸念により、ApacheからNginxに移行しているため、この部分を除いてほとんどすべてが正常に機能します)。

私の最初のセットアップは、HTTP Cookie(アプリケーションによって設定された)を読み取り、その値に応じて、リバースプロキシを別のバックエンドに転送することでした。それはこのようなものでした:

RewriteCond %{HTTP_COOKIE}  proxy-target-A
RewriteRule ^/original-request/ http://backend-a/some-application [P,QSA]

RewriteCond %{HTTP_COOKIE}  proxy-target-B
RewriteRule ^/original-request http://backend-b/another-application [P,QSA]

RewriteRule ^/original-request http://primary-backend/original-application [P,QSA]

私はNginxを使用して同じことを達成しようとしています、そして私の初期設定は次のようなものでした(「proxy_override」はCookieの名前です):

location /original-request {
    if ($cookie_proxy_override = "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($cookie_proxy_override = "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

しかし、そうではありませんでした。 Nginxが${cookie_proxy_override}に基づいて何かにリダイレクトするプライマリプロキシを作成することでcookieを読み取ることができるかどうかを確認しようとしましたが、コンテンツを正常に読み取ることがわかりますが、ifsは常に不合格。

リキの答えによると、私の次の試みはこれでした:

location /original-request {
    if ($http_cookie ~ "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($http_cookie ~ "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

そして今、私はifブロックがアクティブになるのを見ることができますが、リクエストをプロキシするのではなく(私がそうするだろうと思ったように)、指定されたURLへの302リダイレクトを返します-これは私が試みているものではありません行う:サーバーがバックエンドにリクエストを透過的にリレーし、レスポンスを元のクライアントにパイプする必要があります。

何が悪いのですか?

11
Guss

this answer に似ています。この種の問題に対するNginxの慣用的なアプローチは、mapを介したものです。

基本的に、mapセクションでhttpを定義します

map $cookie_proxy_override $my_upstream {
  default default-server-or-upstream;
  ~^(?P<name>[\w-]+) $name;
}

次に、単に$my_upstreamlocationセクション内:

location /original-request {
  proxy_pass http://$my_upstream$uri;
}

Nginxはマップ変数を(リクエストごとに)1回だけ、そしてそれらを使用しているときに遅延評価します。

16

最終的に私の解決策はこれに要約されます:

server {
    ...
    set $upstream "default-server-or-upstream";
    if ($http_cookie ~ "proxy_override=([\w-]+)") {
        set $upstream $1;                                   
    }

    location /original-request {
        proxy_pass http://$upstream/original-application
    }
}

テストは各リクエストのserverスコープで(実際のリダイレクトが解決される前に)行われ、変数を設定するためだけに使用されます。これは明らかにNginx "rewrite"モジュールのサポートされる使用法です。また、$http_cookie @Rikihのように提案されていますが、人々が私に投げつけているかもしれないランダムなものと一致しないようにCookieの名前が含まれています。

次に、リダイレクトを行うlocationスコープで、デフォルトのアップストリーム構成を含むか、Cookieによって上書きされた変数名を使用します。

3
Guss

$ http_cookieを試しましたか? http://wiki.nginx.org/HttpRewriteModule

if($ http_cookie〜* "proxy-target-A"){foo; }

0
chocripple

私はudidに基づいてリクエストヘッダーを検出するために使用するサンプルがあり、それは機能しています。

   location / {
      proxy_set_header Host $http_Host;
  if ($request_uri ~ ^/(.*)udid=xxxxxxxxxxxxxx(.*)$) {
    proxy_pass   http://1.1.1.1$request_uri;
    break;
  }
  if ($request_uri ~ ^/(.*)udid=yyyyyyyyyyyyyy(.*)$) {
    proxy_pass   http://3.3.3.3$request_uri;
    break;
  }
       proxy_pass http://2.2.2.2$request_uri;
    }
0
chocripple