使用proxy_pass时如何在nginx上添加响应标头?


90

我想为从nginx之后的服务器收到的响应添加一个自定义标头。

虽然add_header适用于nginx处理的响应,但proxy_pass使用时不执行任何操作。


因此,您将请求传递给代理服务器,并且该代理服务器设置了响应,并且您希望在此响应上添加自定义标头,然后再将其发送给用户,对吗?
emka86

Answers:


29

有一个名为HttpHeadersMoreModule的模块,它使您可以更好地控制标头。它不是Nginx随附的,需要其他安装。有了它,您可以执行以下操作:

location ... {
  more_set_headers "Server: my_server";
}

这将“将服务器输出标头设置为任何状态代码和任何内容类型的自定义值”。它将替换已经设置的标题,或者如果未设置则添加它们。


是否可以在响应cookie上添加SecureHttpOnly标记?虽然目标响应cookie 具有cookie 和属性。nameexpire
JPaulPunzalan

2
您不一定需要一个库就可以更改或添加响应标头,并且与投票最多的答案相反,您可以覆盖标头,只需要先将其删除即可。请在下面查看我的答案以获取详细信息。
Wilt

155

add_headerproxy_pass无论有没有,效果都很好。我今天刚刚设置了一个配置,在该配置中,我恰好使用了该指令。不过,我必须承认,我在努力设置这一点的同时并没有确切地回忆起原因。

现在,我有一个有效的配置,它包含以下内容(以及其他内容):

server {
    server_name  .myserver.com
    location / {
        proxy_pass  http://mybackend;
        add_header  X-Upstream  $upstream_addr;
    }
}

在nginx之前,1.7.5 add_header仅对成功的响应起作用,这与塞巴斯蒂安·古德曼Sebastian Goodman)在回答中提到的HttpHeadersMoreModule相反。

从nginx开始,1.7.5always甚至可以在错误响应中使用关键字来包含自定义标头。例如:

add_header X-Upstream $upstream_addr always;

限制:您不能使用覆盖server标题值add_header


40
自nginx 1.7.5起,您可以使用add_header使用“始终”在错误响应中包含自定义标头:add_header X-Upstream $upstream_addr always;
Shane

无论如何,具有不公开代理服务器的IP /端口组合的类似功能?例如X-Upstream: 10.10.10.10vs X-Upstream: 53c2d28edefdf501ab7c92e02a0c1687(md5可能对掩盖基础结构没有帮助,但是它传达了这个想法)。
zamnuts 2015年

@zamnuts:传递上游IP和端口号只是使用add_header伪指令的一个示例。您根本不必发送它们。
奥利弗

@Oliver,我知道这一点,但是我在询问除IP /端口号以外的其他单独/唯一上游标识符,或对其进行混淆。也许我的问题超出了范围,我应该创建一个新帖子:)
zamnuts

@zamnuts:我也建议您提出一个新问题:-)
Oliver

25

正如Oliver写道:

add_headerproxy_pass无论有没有,效果都很好。

但是,正如Shane所写的那样,从Nginx 1.7.5开始,您必须通过always才能add_header进行错误响应,如下所示:

add_header  X-Upstream  $upstream_addr always;

5
我花了很长时间想知道为什么我的标题没有显示,试图将它们移到服务器块,位置块中……这是原因:nginx不在错误响应中添加它们:F谢谢
Shautieh

我也是:)尽管有这个答案,但第二天又发生在我身上。不得不回顾我自己的答案。
德米特里·明科夫斯基


14

您可以尝试以下解决方案:

在您location使用的代码块中,proxy_pass执行以下操作:

location ... {

  add_header yourHeaderName yourValue;
  proxy_pass xxxx://xxx_my_proxy_addr_xxx;

  # Now use this solution:
  proxy_ignore_headers yourHeaderName // but set by proxy

  # Or if above didn't work maybe this:
  proxy_hide_header yourHeaderName // but set by proxy

}

我不确定这是否正是您所需要的,但是请尝试对此方法进行一些操作,也许结果会适合您的问题。

您也可以使用以下组合:

proxy_hide_header headerSetByProxy;
set $sent_http_header_set_by_proxy yourValue;

6
我必须使用此方法,因为nginx会添加重复的标头,而不是覆盖现有的标头。location / { proxy_pass http://127.0.0.1:8080/; proxy_hide_header "Access-Control-Allow-Origin"; if ($http_origin ~* "^https://(example.com|www.example.com)$") { add_header Access-Control-Allow-Origin "$http_origin"; } }
ether6

11

隐藏响应标题,然后添加新的自定义标题值

添加add_header带有代理的标头可以很好地与代理传递配合使用,但是如果响应中存在现有的标头值,它将堆栈这些值。

如果要设置或替换标题值(例如,替换Access-Control-Allow-Origin标题以匹配客户端以允许跨源资源共享),则可以执行以下操作:

# 1. hide the Access-Control-Allow-Origin from the server response
proxy_hide_header Access-Control-Allow-Origin;
# 2. add a new custom header that allows all * origins instead
add_header Access-Control-Allow-Origin *;

因此,proxy_hide_header与结合使用add_header可以设置/替换响应标头值。

可以在ServerFault上找到类似的答案

更新:

注意: proxy_set_header用于在进一步发送请求之前设置请求标头,而不是用于设置响应标头(标头的这些配置属性可能会有些混乱)。


谢谢,有很大的帮助
Lancer.Yan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.