多层nginx反向代理中vary头须由后端接入层唯一生成,边缘与网关层仅透传且禁用添加;通过map校验白名单、统一origin_key标准化缓存键,杜绝中继污染与缓存错乱。

多层 Nginx 反向代理级联时,Vary 响应头若未经统一管控,极易在各层间被重复添加、覆盖或遗漏,造成“中继污染”——即缓存系统收到不一致、冗余甚至冲突的 Vary 值(如 Vary: Origin, Origin 或 Vary: Origin, Accept-Encoding, Origin),进而导致 CDN 缓存错乱、跨域响应复用错误、CORS 失败率上升。治理核心不是“加头”,而是“控源、归一、透传有度”。
明确每层职责:谁该加 Vary,谁只透传
级联系统中,Vary 头应由最靠近后端服务的一层 Nginx(即最后一跳代理)负责生成和权威设置,其余中间层仅做安全透传,不修改、不追加。
- 边缘层(接 CDN/用户):禁用所有
add_header Vary ...,仅启用proxy_pass_request_headers on;,确保原始 Vary 头完整到达下一层 - 网关层(路由/鉴权):同样禁用主动添加 Vary;若需改写响应(如动态注入 CORS 头),必须先清除旧 Vary(
proxy_hide_header Vary;),再由后端层重新生成 - 后端接入层(直连应用):唯一可配置
add_header Vary Origin;的位置;且必须与proxy_cache_key中的$http_origin严格对应
拦截重复与非法 Vary 值
中间层 Nginx 应主动过滤异常 Vary 字段,防止污染向下传递:
- 用
proxy_hide_header Vary;清除上游可能误加的 Vary 头,避免叠加 - 配合
map指令校验 Vary 值合法性,例如禁止出现重复字段或非预期字段:map $upstream_http_vary $safe_vary { ~*Origin.*Origin "Origin"; ~*Accept-Encoding.*Accept-Encoding "Accept-Encoding"; ~*^(Origin|Accept-Encoding|User-Agent)$ $upstream_http_vary; default ""; } - 在后端接入层,用
add_header Vary $safe_vary;替代硬编码,实现白名单式输出
统一 Origin 处理逻辑,避免空值分裂
多层代理中,$http_origin 在非跨域请求中为空,若各层缓存键未标准化,会导致同一资源产生“有 Origin”和“无 Origin”两套缓存,浪费空间且易命中错误版本。
- 在后端接入层的
http块中统一定义:map $http_origin $origin_key { "" "null"; default $http_origin; } - 将缓存键设为:
proxy_cache_key "$scheme$request_method$host$request_uri$origin_key"; - 确保所有涉及缓存的 location 块都使用该
$origin_key,而非裸$http_origin
验证中继链路是否干净
用 curl 沿链路逐层抓包,确认 Vary 行为符合预期:
- 从客户端发起请求:
curl -I -H "Origin: https://a.com" https://api.example.com/data - 在边缘 Nginx 查看 access 日志中的
$upstream_http_vary,应为空(因它不加头) - 在网关层日志中检查
$upstream_http_vary,应与后端接入层输出一致 - 最终响应中只出现一次
Vary: Origin,且无逗号重复、无多余字段 - 对比不同 Origin 请求的缓存状态头(如
X-Cache),确保 HIT 率稳定、无交叉命中











