首页/网络/协议速查/Vary 缓存键维度
HTTP 头与缓存70 条

Vary 缓存键维度

告诉(共享)缓存:该响应依赖哪些请求头来区分版本;同一 URL 不同 Accept-Encoding/Origin 必须分别缓存。

协议速查网络更新于 2026-10-13

Vary 决定缓存怎么分辨版本

同一个 URL 可能因为请求头不同而返回不同内容:带 Accept-Encoding 是 br 版本,带 Origin 是给某个站的跨域头。Vary 就是告诉缓存「这份响应依赖哪些请求头」,让缓存把这些头纳入缓存键。不写 Vary 的后果是缓存把某个版本当成通用版本发出去,典型表现是 A 站点拿到 B 站点的跨域响应,或者压缩版本被发给不支持的客户端。

基本信息

响应头名Vary
作用扩展缓存键,避免不同变体互相污染
规范RFC 9110 第 12.5.5 节,缓存键规则见 RFC 9111
高频取值Accept-Encoding(压缩),Origin(跨域),Accept(内容协商)
特殊取值Vary: * 表示响应不可缓存
方向只在响应里出现,客户端不需要发送

配置与验证

配置与验证
curl -sI https://www.example.com/ | grep -i vary                     # 看站点声明了哪些变体维度
curl -sI -H 'Accept-Encoding: gzip' https://www.example.com/ | grep -iE 'vary|content-encoding'
# nginx 跨域场景:回显 Origin 时必须同时声明 Vary,否则缓存会串站
# location /api/ {
#   add_header Vary "Origin";
#   add_header Access-Control-Allow-Origin "$http_origin" always;
# }
curl -sI -H 'Origin: https://a.example.com' https://api.example.com/x | grep -iE 'vary|access-control'

取值与含义

写法含义典型场景
Vary: Accept-Encoding按压缩算法区分版本几乎所有压缩过的响应都应带
Vary: Origin按请求来源区分版本动态回显跨域来源的接口
Vary: Accept按可接受的媒体类型区分同一地址返回 JSON 与 HTML 两种表示
Vary: User-Agent按客户端标识区分移动端与桌面端返回不同页面
Vary: *响应不可缓存高度个性化且无法用头部维度描述的内容

典型使用场景

  • 排查跨域内容串站:A 站点拿到 B 站点的跨域响应头,通常是缺少 Vary: Origin
  • 排查乱码与解压失败:客户端拿到不支持的压缩版本,属于缺少 Vary: Accept-Encoding
  • 多端适配场景:移动端与桌面端返回不同内容时必须声明区分维度
  • 缓存命中率优化:核对 Vary 维度是否过多,避免缓存被切得过碎
  • 灰度与个性化内容:确认响应是否真的可缓存,必要时改为不可缓存
动态回显请求头的接口必须同时声明 Vary,否则 CDN 会把某个来源的响应发给其它来源。跨域与压缩是最容易踩到的两处,配置时应把两者当成固定搭配。

易错点

  • 回显 Origin 却不加 Vary: Origin,CDN 可能把 A 站点的跨域响应发给 B 站点,属于典型的安全问题
  • 响应压缩不带 Vary: Accept-Encoding,只支持 gzip 的客户端可能收到 br 内容并解压失败
  • Vary 里堆了大量请求头,缓存被切成无数变体,命中率骤降、回源量暴涨
  • 误以为写了 Vary: * 就等于不缓存,实际上部分场景下会让缓存直接跳过存储,行为与预期不一致

数据来源与参考

  • RFC 9110 §12.5.5 Vary
  • RFC 9111 §4.1(缓存键)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌