304响应默认不携带add_header设置的头,除非显式加always参数;这是Nginx设计行为,非bug。原因包括缓存场景下不重执行add_header,以及未缓存时若无always且上游未返回对应头则不注入;always是唯一可靠方式,且需在每个location中显式声明,配合缓存时还需避免proxy_ignore_headers等误删,并验证304响应头是否生效。

304 响应默认不携带 add_header 设置的头,除非显式加 always 参数。这是 Nginx 的设计行为,不是 bug,也不依赖缓存开关。
为什么 304 响应通常不带安全头
Nginx 的 add_header 指令默认只对特定状态码生效,304 虽在白名单中,但实际执行时受两个关键限制:
- 若该响应来自缓存(如
proxy_cache或fastcgi_cache),Nginx 不会重新运行add_header指令,而是直接返回缓存的原始响应头 —— 即使原始缓存里没这些头,也不会补上; - 即使未缓存,若 location 中未配置
always,且上游(如后端服务)本身没返回对应头,304 响应体为空、响应头极简,add_header也不会自动注入。
必须用 always 才能覆盖 304 场景
always 是唯一可靠方式,它让 Nginx 在所有响应阶段(包括 304)都强制插入头字段。例如:
add_header X-Content-Type-Options nosniff always;add_header X-Frame-Options DENY always;add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
注意:不能只在 http 或 server 块写一次就完事 —— 若存在内部重定向(如 rewrite ... last 或 try_files),目标 location 必须也显式声明带 always 的 add_header,否则不会生效。
配合缓存时的额外要点
当启用 proxy_cache 或 fastcgi_cache 时,仅靠 always 还不够,需确保缓存机制允许这些头被存储和回传:
- 用
proxy_ignore_headers时,避免屏蔽Strict-Transport-Security等关键头(例如不要写proxy_ignore_headers Strict-Transport-Security;); - 对于 FastCGI,
fastcgi_ignore_headers同样会影响,需检查是否误删; - CDN 或反向代理前置时,确认其支持透传或缓存自定义响应头(如
Access-Control-Allow-Origin、X-Frame-Options),并设置Vary: Origin防止跨源污染。
验证是否真正生效
别只看 200 响应,重点测 304:
- 首次请求后记录
Etag或Last-Modified; - 第二次请求带上
If-None-Match或If-Modified-Since; - 用
curl -I或浏览器开发者工具检查响应头,确认X-Frame-Options等仍在且值正确; - 若缺失,回查 location 是否漏了
always,或是否被proxy_hide_header/fastcgi_hide_header意外过滤。


















