加always参数可解决405响应缺CORS头问题,但仅当405由Nginx自身返回时有效;若由后端返回或为内置错误页,则需拦截OPTIONS请求return 204或用error_page 405=200重写。

直接加 always 就能解决 405 响应里缺 CORS 头的问题,但前提是:这个 405 真的是 Nginx 自己返回的,而不是后端服务返回后被 Nginx 转发出去的。
为什么 405 响应默认没有 CORS 头
Nginx 的 add_header 指令默认只对成功响应(2xx、3xx)生效。遇到 405 这类错误响应时,Nginx 不会自动添加你配置的头——哪怕你在 location 块里写了 add_header Access-Control-Allow-Origin "*",它也不会出现在 405 响应里。
这会导致两个实际问题:
- 前端发 OPTIONS 预检请求,Nginx 因路径不匹配或方法不支持直接返回 405,但没带 CORS 头,浏览器直接报错“preflight response has invalid HTTP status code”
- 漏洞扫描工具检测到 405 响应缺少安全头(如
Access-Control-Allow-Origin),标记为风险项
add_header … always 的作用和写法
always 参数让 add_header 强制作用于所有响应,包括 4xx 和 5xx。这是最直接有效的修复方式。
正确写法示例:
location /api/ {
proxy_pass http://backend;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Content-Type,Authorization' always;
}
注意:always 必须紧接在 add_header 后面,不能换行,也不能加引号包裹 always。
但光加 always 可能还不够:先确认 405 是谁返回的
如果 405 是后端服务返回的(比如 Spring Boot 或 Node.js 接口不支持 OPTIONS),Nginx 默认只是透传响应,不会重写头。此时 add_header ... always 依然无效——因为 Nginx 不会修改已存在的响应头,除非你显式开启透传控制。
应对方法有两种:
- 推荐:在
location块中拦截 OPTIONS 请求,主动 return 204(或 200),并在 if 块内加全 CORS 头(含always) - 次选:启用
proxy_pass_request_headers on并配合add_header ... always,但有安全风险,一般不建议
拦截写法示例:
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Content-Type,Authorization' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
add_header 'Content-Length' 0 always;
return 204;
}
proxy_pass http://backend;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
}
顺便解决 405 页面无法显示 CORS 头的连带问题
有些场景下,用户访问一个不存在的接口路径(如 /v1/xxx),Nginx 因未配置对应 location,回落到 / 块处理,而该块只允许 GET,导致返回 405。这时即使加了 always,CORS 头也加不到错误页上——因为 405 响应由 Nginx 内置错误页机制生成,add_header 对其无效。
稳妥做法是显式捕获并重写:
error_page 405 =200 $request_uri;
这句放在 server 或 http 块里,能让 405 被转成 200 后再走正常响应流程,add_header ... always 就能生效了。


















