使用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相同,我的初始configuration是这样的(其中“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是否可以通过写主代理来redirect到基于${cookie_proxy_override}东西来读取我的cookie,我可以看到它读取的内容很好,但是if似乎总是失败。

我的下一个尝试,根据Rikih的回答是这样的:

 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块被激活,而不是代理请求(就像我以为会这样做),它返回一个302redirect到指定的URL – 这不是我想要做的:我需要服务器将请求透明地中继到后端,并将响应传递给原始客户端。

我究竟做错了什么?

类似于这个答案 。 Nginx对这类问题的惯用方法是通过map

基本上,你在http部分定义一个map

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

然后,您只需在location部分中使用$my_upstream

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

Nginx懒惰地评估地图variables,只有一次(每个请求),当你使用它们。

最终我的解决scheme归结为:

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

testing在每个请求的server范围内完成(在实际的redirect被parsing之前),并且只是用来设置一个variables – 这显然是Nginx“rewrite”模块支持的使用。 它也testing整个$http_cookie像@Rikihbuild议的,但包括cookie的名称,以确保我不匹配随机的东西,人们可能会扔在我身上。

然后在我要执行redirect的location范围中,使用包含默认上游configuration的variables名或被Cookie覆盖。

你有没有尝试$ http_cookie? http://wiki.nginx.org/HttpRewriteModule

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

我有样本,我使用基于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; }