需精确配置Nginx的Access-Control-Allow-Headers、Access-Control-Expose-Headers及OPTIONS预检响应,显式声明自定义头并避免继承问题,生产环境禁用通配符Origin。

要让 Nginx 支持特定业务需求的非标准 CORS 头部(比如 X-Request-ID、X-App-Version、X-User-Role 等),关键不是开启默认 CORS,而是精确控制 Access-Control-Allow-Headers 和其他相关响应头,同时确保预检请求(OPTIONS)被正确处理。
明确需要暴露的自定义请求头
浏览器在发送携带自定义请求头(如 X-App-Version: 2.1.0)的跨域请求前,会先发一个 OPTIONS 预检请求。服务器必须在响应中通过 Access-Control-Allow-Headers 明确列出这些头,否则浏览器将拒绝主请求。
- 在
location块或server块中,用add_header设置允许的请求头列表 - 注意:该字段值是逗号分隔的字符串,**不带空格**(部分浏览器严格校验)
- 示例:
add_header Access-Control-Allow-Headers "X-App-Version,X-User-Role,X-Request-ID";
暴露自定义响应头给前端 JavaScript 访问
若前端 JS 需要读取后端返回的非标准响应头(如 response.headers.get('X-Request-ID')),必须在 Access-Control-Expose-Headers 中显式声明,否则这些头对 JS 不可见。
- 该头部只影响浏览器是否允许 JS 读取,不影响服务端实际发送
- 同样使用逗号分隔,无空格;可与
Access-Control-Allow-Headers内容不同 - 示例:
add_header Access-Control-Expose-Headers "X-Request-ID,X-RateLimit-Remaining";
正确处理预检请求(OPTIONS)
Nginx 默认不会为 OPTIONS 请求执行 proxy_pass 或后端逻辑,因此需显式拦截并返回 204 响应,避免请求落到后端(可能返回 405 或 500)。
- 在对应
location块内添加if ($request_method = 'OPTIONS') { ... }或更推荐的location匹配 - 推荐写法:
location = /api/ {<br> if ($request_method = 'OPTIONS') {<br> add_header Access-Control-Allow-Origin "*";<br> add_header Access-Control-Allow-Methods "GET,POST,PUT,DELETE,PATCH,OPTIONS";<br> add_header Access-Control-Allow-Headers "X-App-Version,X-User-Role";<br> add_header Access-Control-Expose-Headers "X-Request-ID";<br> add_header Access-Control-Max-Age 86400;<br> add_header Content-Length 0;<br> add_header Content-Type text/plain;<br> return 204;<br> }<br>}
避免常见陷阱
配置生效的前提是逻辑顺序和作用域正确:
-
add_header指令在子块(如if或嵌套location)中定义时,**不会继承父块的 header**,需全部重新声明 - 若使用
proxy_pass,确保后端不覆盖或清空你设置的 CORS 头(可在 Nginx 层统一加,后端不加 CORS 相关头) - 生产环境慎用
Access-Control-Allow-Origin: "*",若需携带凭证(cookies),必须指定具体域名且不能为通配符 - 调试时可用
curl -I -X OPTIONS -H "Origin: https://example.com" https://your-api.com/path验证预检响应头










