Nginx 如何查看和处理来自上游(upstream)的响应头?

Nginx 上游响应头的查看与改写:$upstream_http_* 变量记日志、proxy_hide_header 隐藏、add_header 透传注意点、proxy_pass_header 解禁,调试方法与 FAQ。

最佳实践
Nginx 如何查看和处理来自上游(upstream)的响应头?封面

三个核心手段:日志里用 $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 发送 HEAD,未必与实际 GET 响应一致;对照 GET 可用 curl -sS -D - -o /dev/null URL。add_header 是追加,若上游已有同名头可能产生重复,替换时需按语义先隐藏。

命令行侧的直接查看:

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-Pad;   # 仅示例:确认确有需要才放行

proxy_hide_header 只控制向客户端转发,不能等同于停止处理头部语义。X-Accel-Redirect 会触发内部重定向;若确需改变其处理,应单独评估 proxy_ignore_headers,不能把它当普通诊断头透传。

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 不再继承;新版本提供 add_header_inherit 等控制,需按部署版本核对。

验证响应头时,同时检查客户端收到的值与上游原始值。需要追查缓存或版本差异,可将选定的头字段写进访问日志,再通过观测云 DataKit采集并按该字段查询;只记录必要字段,避免把鉴权令牌或会话信息一并写入。

常见问题(FAQ)

Q:改了上游的头配置但客户端看到的没变?
A:检查是否被 CDN/浏览器缓存了旧响应;以及你的 add_header 是否缺 always,恰好响应是 4xx/5xx 等默认不生效的状态码;304 本来就在默认支持列表中。

Q:上游返回了 Set-Cookie,Nginx 会转发吗?
A:会,Set-Cookie 不在默认屏蔽列表。若要在反代间改写 cookie 域/路径,用 proxy_cookie_domain / proxy_cookie_path。

Q:能按上游响应头做条件处理吗?
A:可以用于读取上游响应后的阶段,但请求重写阶段执行的 if 通常还拿不到响应头;map 也不能让变量提前产生。需要按所用指令阶段设计处理。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台