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


11

興味深い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を読み取ることができるかどうかを確認しようとしましたが${cookie_proxy_override}、コンテンツを正常に読み取ることがわかりますが、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リダイレクトを返します-これは私がやろうとしていることではありません:サーバーが必要です要求をバックエンドに透過的に中継し、応答を元のクライアントにパイプします。

何が悪いのですか?

回答:


16

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

基本的に、あなたは定義maphttpセクション

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

次に、単にセクションで使用$my_upstreamしますlocation

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

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


3
おかげで、これは私の方法よりも優れたアプローチです。特に、名前付きCookie変数を直接使用でき(なぜに入れられないのかわからないif)、それを実装したためです。ただし、1つの問題があります-Nginx(少なくとも私のバージョン:1.0.0)はでの番号付きキャプチャが好きではないmapため、~^(?P<name>[\w-]+) $name;代わりに使用する必要がありました。私はそれに応じてあなたの答えを編集しました。
ガス、2011

3

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

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によって上書きされた変数名を使用します。


0

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

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


特定のCookie名に対して単にテストできないのはなぜかはわかりませんが、これは実際にテストに役立ちました。私が気に入らなかったことrewriteは、実際にはプロキシの書き換えを行わず、代わりにクライアントにリダイレクトを返し、ifブロックでproxy_passを使用できないことです。私はそれに応じて質問を更新しました。
Guss

0

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

どのバージョンのNginxを使用していますか?私は1.0を使用していますし、あなたがここで指定したように、私はproxy_passを使用する場合、私は、このエラーメッセージが表示されます:nginx: [emerg] "proxy_pass" may not have URI part in location given by regular expression, or inside named location, or inside the "if" statement, or inside the "limit_except" block in /etc/nginx/conf.d/proxy.conf:47
GUSS

私はnginx-0.8.53-1.el5を使用します
Chocripple


フォーラムの解決策は、別のサーバーにプロキシするときにリクエストURIを変更しないことですが、それはまさに私がする必要があることです-リクエストURIを書き換えて、元のURLに含まれているものとは異なるアプリケーションをターゲットにします。また、あなたの例はproxy_passコマンドでリクエストURIも使用しているようですので、上記のフォーラムの議論を考えると、それがどのように機能するかわかりません。
Guss
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.