Nginx默认忽略或限制Set-Cookie、Connection/Keep-Alive/Transfer-Encoding、Expires/Cache-Control/ETag/Last-Modified、Server/X-Powered-By等响应头;可通过proxy_pass_header(旧版)或proxy_hide_header反向控制透传。

在 Nginx 中使用 ngx_http_proxy_module 时,后端服务返回的某些响应头(如 Set-Cookie、Cache-Control、Expires、Server 等)默认可能被 Nginx 忽略或覆盖。这并非 bug,而是模块的默认安全策略和缓存逻辑所致。
哪些响应头会被自动忽略或限制?
Nginx 默认不会原样透传所有后端响应头。以下几类尤其常见:
-
Set-Cookie:当启用
proxy_buffering或存在缓冲行为时,若后端返回多个Set-Cookie,Nginx 可能只保留第一个;若值含逗号、空格或特殊字符且未正确编码,也可能被截断或丢弃。 - Connection / Keep-Alive / Transfer-Encoding:这些属于“逐跳首部”(hop-by-hop headers),Nginx 会主动移除,不转发给客户端。
-
Expires / Cache-Control / ETag / Last-Modified:当开启
proxy_cache时,Nginx 可能根据自身缓存策略重写或忽略这些头,尤其是与缓存有效性冲突时。 -
Server / X-Powered-By:若配置了
server_tokens off;,Nginx 会屏蔽自身的Server头,但不影响后端的同名头;不过部分旧版本或特定编译选项下,后端Server也可能被覆盖。
如何让 Nginx 透传指定响应头?
使用 proxy_pass_header 指令可显式启用原本被屏蔽的响应头(注意:仅对默认被禁用的头有效,不是所有头都需要此配置):
示例:
location /api/ {
proxy_pass https://backend;
proxy_pass_header Set-Cookie;
proxy_pass_header Expires;
proxy_pass_header Cache-Control;
}⚠️ 注意:proxy_pass_header 在较新版本(1.19.1+)中已标记为 deprecated,推荐改用 proxy_hide_header 的反向控制方式 —— 即先清空屏蔽列表,再按需隐藏不需要的头:
location /api/ {
proxy_pass https://backend;
proxy_hide_header X-Powered-By; # 显式隐藏(如果不想暴露)
# 其余头(如 Set-Cookie)默认不再被自动过滤,只要没被 proxy_hide_header 屏蔽,就会透传
}确保未配置 proxy_hide_header Set-Cookie; 或类似语句,否则它会被主动删除。
调试与验证方法
快速确认响应头是否被 Nginx 修改或丢弃:
- 用
curl -I对比直接访问后端与通过 Nginx 访问的响应头差异; - 在 Nginx 配置中临时添加日志记录响应头:
log_format full '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_http_set_cookie"';
然后在access_log中使用该格式,观察$upstream_http_*变量是否捕获到后端原始头; - 开启
error_log debug;(仅测试环境),搜索upstream sent相关日志行,可看到 Nginx 实际发送给客户端的响应头。
其他影响透传的关键配置
以下设置虽不直接删除响应头,但会间接导致其失效或被覆盖:
-
proxy_buffering on;:启用缓冲时,Nginx 会读取完整响应后再发给客户端,期间可能合并或修改Set-Cookie;设为off可减少干扰(但影响性能); -
proxy_cache相关指令:如proxy_cache_valid会强制设置Cache-Control,覆盖后端值; -
add_header指令:若在 location 中用了add_header Cache-Control ...,它会覆盖后端同名头(除非加always参数且后端头未被屏蔽)。

















