需同时配置add_header Vary Origin always、proxy_cache_key含$http_origin(用map处理空值)及动态Access-Control-Allow-Origin,三者缺一不可,否则将导致缓存污染或碎片化。

直接在对应 location 块中写 add_header Vary Origin; 即可强制带上该头部,但仅加这行不够——它必须和缓存键、跨域策略协同生效,否则可能引发缓存污染或碎片化。
确保 Vary: Origin 出现在所有目标响应中
add_header 默认只对 2xx/3xx 响应生效。若需在 404、500 等错误响应中也携带该头(例如 CDN 需依据 Origin 缓存错误页),要显式加上 always 参数:
add_header Vary Origin always;- 建议紧接在
add_header Access-Control-Allow-Origin之后设置,逻辑更清晰 - 若后端已返回
Vary: Origin,Nginx 默认透传;但显式配置可兜底,避免上游遗漏
同步调整 proxy_cache_key 包含 $http_origin
仅加 Vary 头不能自动隔离缓存,必须让缓存系统“知道”Origin 不同就应存不同副本:
- 使用
proxy_cache_key "$scheme$request_method$host$request_uri$http_origin"; - $http_origin 在非跨域请求中为空,会导致缓存分裂。稳妥做法是用
map将空值映射为固定字符串,例如:
map $http_origin $origin_key {
default "null";
~. $http_origin;
}
再写proxy_cache_key "$scheme$request_method$host$request_uri$origin_key";
区分通配符与具体 Origin 的适用场景
不是所有跨域响应都该加 Vary: Origin:
- 若返回
Access-Control-Allow-Origin: *,说明接口不支持带凭证的跨域,此时不应加 Vary,否则缓存会因每个 Origin 都生成新副本而严重碎片化 - 只有当后端或 Nginx 动态返回具体 Origin(如
https://a.com)且设置了Access-Control-Allow-Credentials: true时,才需要三者齐备:具体 Origin + Vary Origin + 含 Origin 的 cache_key
验证是否真正生效
用 curl 模拟不同源请求,观察响应头与缓存行为:
curl -I -H "Origin: https://a.com" https://api.example.com/datacurl -I -H "Origin: https://b.com" https://api.example.com/data- 两个响应都应含
Vary: Origin - 检查缓存标识头(如
X-Cache: HIT):若一个 HIT 一个 MISS,说明缓存键已区分 Origin;若都 HIT,说明缓存隔离成功;若都 MISS,需排查proxy_cache_valid或路径匹配问题


















