Nginx 如何查看和处理来自上游(upstream)的响应头?
Nginx 上游响应头的查看与改写:$upstream_http_* 变量记日志、proxy_hide_header 隐藏、add_header 透传注意点、proxy_pass_header 解禁,调试方法与 FAQ。
三个核心手段:日志里用 $upstream_http_头名 记录上游返回的任意响应头;proxy_hide_header 屏蔽不想给客户端的;add_header 在反代场景下追加自己的头(注意默认只在部分状态码生效)。
1. 查看:把上游响应头记进日志
调试"上游到底返回了什么",最直接的办法是写日志:
log_format upstream_debug '$remote_addr - $uri → $status '
'up-ct=$upstream_http_content_type '
'up-cache=$upstream_http_cache_control '
'up-time=$upstream_response_time';
access_log /var/log/nginx/upstream.log upstream_debug;
$upstream_http_xxx 变量名规则:头名转小写、连字符变下划线(X-Request-Id → $upstream_http_x_request_id)。
命令行侧的直接查看:
curl -I https://yoursite/path # 看最终到客户端的头
curl -I http://backend:8080/path # 绕过 Nginx 直连上游对比
2. 隐藏上游的头
上游是应用服务器,常带出不该暴露的信息(X-Powered-By: PHP/8.2、Server 细节):
location / {
proxy_pass http://backend;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
3. 传递被默认屏蔽的头
Nginx 默认不转发上游的部分头(Date、Server、X-Pad、X-Accel-* 等)。确实需要透传时:
proxy_pass_header X-Accel-Redirect; # 例:内部重定向头放行
4. 自己加头(add_header 的坑)
location / {
proxy_pass http://backend;
add_header X-Cache-Status $upstream_cache_status always;
}
两个坑必须知道:
- 默认只对 200/201/204/206/301/302/303/304/307/308 生效——错误响应(4xx/5xx)上不加。要全状态码生效,加
always参数。 - 继承规则:一个层级里只要写了任何
add_header,父级的add_header就全部失效——子块里要重新定义。
观测云对照
上游响应头承载着大量诊断信息(缓存命中、应用版本、链路 ID),把它们写进访问日志并接入观测云,就能在日志查看器里按这些维度聚合分析——比如按 up-cache 统计缓存命中率、按上游版本对比发布后错误率。分析不了的维度,多半是日志格式里没记。
常见问题(FAQ)
Q:改了上游的头配置但客户端看到的没变?
A:检查是否被 CDN/浏览器缓存了旧响应;以及你的 add_header 是否缺 always,恰好响应是 304/4xx 这类默认不生效的状态码。
Q:上游返回了 Set-Cookie,Nginx 会转发吗?
A:会,Set-Cookie 不在默认屏蔽列表。若要在反代间改写 cookie 域/路径,用 proxy_cookie_domain / proxy_cookie_path。
Q:能按上游响应头做条件处理吗?
A:可以——$upstream_http_xxx 是普通变量,能进 map 或 if(谨慎)做分支,比如上游返回某标记头时切换缓存行为。