Nginx 配置 CORS 预检需用 if 拦截 OPTIONS 请求并 return 204,add_header 必带 always 参数,且必须返回完整预检头(如 Access-Control-Allow-Origin、Methods、Headers 等),缺一不可。

直接在 Nginx 的 location 块中用 add_header 配置 OPTIONS 预检响应,关键不是“加头”,而是“加对时机+加对状态码+加 always 参数”。否则头可能不生效,浏览器仍报跨域失败。
必须用 if 拦截 OPTIONS 请求并 return 204 或 200
Nginx 默认不处理 OPTIONS 方法,也不会自动返回 CORS 头。仅靠全局或 location 级别的 add_header 不起作用——因为那些头只在正常代理成功后才附加,而 OPTIONS 请求往往根本没走到 proxy_pass 就被拒绝(返回 405)。
- 用
if ($request_method = 'OPTIONS') { ... return 204; }显式捕获并短路响应 - 返回 204(推荐)或 200,不能返回 206、3xx、4xx、5xx
- return 后必须带状态码,不能只写 return
add_header 必须带 always 参数,否则头不返回
默认情况下,add_header 只在 2xx 和 3xx 响应中生效。而 204 是“No Content”,属于 2xx,但 Nginx 旧版本或某些编译配置下仍可能不输出头。加 always 是保险做法。
- 正确写法:
add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com' always; - 错误写法:
add_header 'Access-Control-Allow-Origin' '*';(缺 always,且 * 与 credentials 冲突) - 若需支持凭证(如 Cookie、Authorization),origin 必须是具体域名,不能用 *
预检必需的响应头一个都不能少
浏览器检查 OPTIONS 响应时,会严格验证多个头是否同时存在且值合法。漏掉任意一个,都可能导致后续真实请求被拦截。
-
Access-Control-Allow-Origin:匹配前端 Origin,精确一致(含协议、端口) -
Access-Control-Allow-Methods:列出允许的方法,必须包含实际要发的(如 POST)和 OPTIONS 自身 -
Access-Control-Allow-Headers:列出前端发送的自定义头(如 Authorization、Content-Type) -
Access-Control-Allow-Credentials:如前端设了credentials: 'include',此项必须为 true,且 origin 不能为 * -
Access-Control-Max-Age:缓存预检结果,避免重复 OPTIONS(建议设 86400)
验证配置是否生效的实操方式
别只看浏览器控制台,要从 Nginx 日志和 curl 两层确认。
- 查 access_log:确保日志里有
OPTIONS /path 204行(说明请求进来了且被正确响应) - 用 curl 模拟预检:
curl -X OPTIONS -H "Origin: https://your-frontend.com" -H "Access-Control-Request-Method: POST" -I http://your-api.com/api/user - 检查响应头是否完整,状态码是否为 204,且没有 405/502/超时
- 注意:如果用了 CDN 或 WAF,先确认 OPTIONS 请求是否被它们提前拦截

















