add_header 在错误页不生效是因默认仅作用于2xx/3xx响应;需确认错误是否由nginx自身生成、启用proxy_intercept_errors、正确使用always参数、在error_page对应location中显式配置头,并避免if/rewrite/internal导致头丢失。

add_header 在错误页(如 404、500)不生效,不是配置写错了,而是它根本就没打算生效——默认行为就是只作用于 2xx/3xx 响应。排查要从“是否触发了错误响应路径”和“是否覆盖了头配置”两方面入手。
确认错误响应是否由 Nginx 自身生成
只有 Nginx 自己返回的错误(比如 return 404、error_page 404 /404.html),add_header ... always 才能起作用。如果错误是后端返回的(例如 Spring Boot 抛出 500 并透传给浏览器),Nginx 不会自动加头,除非你在对应 location 中显式拦截并补全:
- 用
error_page 500 = @handle_500;拦截,再在location @handle_500 { internal; add_header ... always; return 500 "..."; }中重写响应 - 检查
proxy_intercept_errors on;是否开启,否则 5xx 会直接透传,绕过你所有 add_header - curl 测试时加
-v看响应头来源:若Server: nginx且无X-Powered-By类头,大概率是 Nginx 自产错误
验证 always 参数是否真被写对了
always 是硬性要求,不是可选项。漏掉、位置错、或只加在部分行都会失效:
- 必须每行
add_header后都紧跟着always,不能只写一次;例如:add_header Access-Control-Allow-Origin "*" always;add_header Access-Control-Allow-Methods "GET" always; - 不能写成
add_header ... "value" always;带多余引号包裹 always —— 语法错误会导致 reload 失败 - 运行
nginx -t可捕获这类语法问题;但注意:always写错位置(如换行后)可能不报错,却无效
检查 location 是否真正匹配到错误页路径
自定义错误页走的是独立 location 分支,很容易被忽略:
- 如果你配了
error_page 404 /404.html;,就必须有对应location = /404.html块 - 该 location 块里必须重新写全所需头,且每条都要带
always;上级 server 或 http 块的 add_header 完全不继承 - 用
curl -I http://your-domain.com/404.html直接测这个路径,看响应头是否含目标字段
排除 if、rewrite、internal 跳转导致的头丢失
这些结构会切断 add_header 的作用链:
- if 块内只要出现任意
add_header,就会丢弃外层所有同名或不同名头——必须在 if 里手动补全全部需要的头 - try_files + @named_location、rewrite last、error_page 指向 named location,都会触发 internal 重定向,原 location 的 add_header 全部作废
- 最终生效的只有目标 location(比如
location @backend)里明确写的 add_header,且每条都得带 always











