Nginx 应直接拦截 OPTIONS 请求并返回 204,不转发至后端;需用 if 判断请求方法、显式添加完整 CORS 头(动态设置 Origin)、启用 24 小时缓存,并隔离预检与主请求处理逻辑。

直接在 Nginx 代理层拦截并响应 OPTIONS 预检请求,是降低后端压力、提升接口可用性的关键动作。它避免了每次跨域请求都穿透到后端服务,尤其在高并发或后端较重(如 Java/Spring Boot)场景下效果显著。核心在于:不转发、不代理、不调用后端,由 Nginx 自行构造合规响应。
精准识别并拦截所有 OPTIONS 请求
Nginx 必须在请求进入 upstream 之前就完成判断和终止,不能依赖后端返回 204 或 200。推荐使用 location = / + limit_except 组合,或更稳妥的 if + return 方式:
- 用 if ($request_method = 'OPTIONS') { ... } 判断,注意该指令只能放在 server 或 location 块内
- 搭配 add_header 显式写入全部必需 CORS 头,不可依赖 proxy_pass 后的后端注入
- 返回状态码必须为 204 No Content(语义最准确),禁止用 200+空体,部分浏览器对 200 OPTIONS 响应行为不一致
动态生成跨域头,支持多源且兼容凭证
前端若携带 cookie(credentials: 'include'),Access-Control-Allow-Origin 就不能为 *。Nginx 可通过变量安全回传合法来源:
- 检查 $http_origin 是否匹配白名单正则(如
~* ^https?://(localhost|admin\.example\.com|app\.mycompany\.io)(:[0-9]+)?$) - 匹配成功则 add_header Access-Control-Allow-Origin $http_origin,否则不加该头(浏览器将拒绝)
- 统一设置 Access-Control-Allow-Credentials: true,Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS,Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Token
极致缓存预检响应,消除重复 OPTIONS
浏览器默认缓存预检结果(由 Access-Control-Max-Age 控制),但若 Nginx 不主动设置强缓存策略,CDN 或客户端可能忽略。需双层控制:
- 在 OPTIONS 响应中设 Access-Control-Max-Age: 86400(24 小时),覆盖绝大多数业务场景
- 额外添加标准 HTTP 缓存头:add_header Cache-Control "public, max-age=86400" 和 add_header Expires "$time_iso8601"(配合 expires 86400s 更可靠)
- 确保该 location 块中 proxy_cache_bypass 和 proxy_no_cache 均设为 off,防止被缓存策略误跳过
隔离预检与主请求处理逻辑
避免 OPTIONS 请求干扰正常代理链。常见错误是把 CORS 头加在 proxy_pass 的 location 中,导致 OPTIONS 仍被转发。正确结构应为:
- 单独定义一个 location /api/ 用于常规接口代理
- 在其上方或内部嵌套 location /api/ { if ($request_method = 'OPTIONS') { ... return 204; } }
- 或使用 map 指令预判方法类型,配合 try_files 短路,实现零延迟响应











