在nginx反向代理中更改主机头(Host header)

39

我正在使用nginx作为反向代理来负载均衡运行在后端服务器上的ruby应用程序,以服务于example.com网站。我在nginx中有以下proxy_set_header字段,将主机标头传递到后端ruby中。这对于ruby应用程序识别子域名非常重要。

location / {
    proxy_pass http://rubyapp.com;
    proxy_set_header Host $http_host;
}

现在我想创建一个别名 beta.example.com,但是传递到后端的主机头应该仍然是www.example.com,否则ruby应用程序将拒绝请求。因此,我希望在location指令中使用类似于以下内容的东西。

if ($http_host = "beta.example.com") {
    proxy_pass http://rubyapp.com;
    proxy_set_header Host www.example.com;
}

最好的方法是什么?


4
这更适合于[科幻]。 - Didi Kohen
4个回答

42

在if块中不能使用proxy_pass,因此建议在设置代理标头之前执行以下操作:

set $my_host $http_host;
if ($http_host = "beta.example.com") {
  set $my_host "www.example.com";
}

现在你可以直接使用proxy_passproxy_set_header,无需if块:

location / {
  proxy_pass http://rubyapp.com;
  proxy_set_header Host $my_host;
}

4
我应该在什么范围内编写if语句?服务器还是位置? - Dimitri Kopriwa
需要注意的是,由于文档所述,此指令仅可在当前级别的标头上使用一次。
proxy_set_header 允许重新定义或附加传递给代理服务器的请求标头字段。...如果当前级别上没有定义proxy_set_header指令,则从前一个配置级别继承指令。
- re-gor

35

mapset+if更好。

map $http_host $served_host {
    default $http_host;
    beta.example.com www.example.com;
}

server {
    [...]

    location / {
        proxy_pass http://rubyapp.com;
        proxy_set_header Host $served_host;
    }
}

在nginx文档中提到,如果不在location中而是在server中,set和if是可以的。然而,map也是一个很好的替代方案。 - Ethan
你能提供一下你提到的文档来源吗?我从未阅读过。此外,涉及 if 的 nginx 票据通常指出与其使用相关的问题。例如:#1383。避免使用 setif 的建议仍然适用。 - Bernard Rosset

4

小贴士:有时您可能需要使用 X-Forwarded-Host 而不是 Host 标头。这就是我的情况,其中 Host 标头适用于标准 HTTP 端口 80。如果应用程序暴露在非标准端口上,则当应用程序生成重定向时,该端口会丢失。所以最终对我有用的是:

proxy_set_header X-Forwarded-Host $http_host;

4

我试图解决相同的情况,但是使用的是 uwsgi_pass

经过一些研究,我发现在这种情况下需要:

uwsgi_param HTTP_HOST $my_host;

希望这能帮助其他人。

这正是我一直在寻找的,非常感谢! - emyller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接