Nginx 应拦截 OPTIONS 预检请求并直接返回 204,避免透传后端;需配置 limit_except、Access-Control 响应头、upstream keepalive 及合理 Access-Control-Max-Age 值(3600–86400),并通过 curl、stub_status 和浏览器 DevTools 验证优化效果。

在 Nginx 中处理 CORS 预检(OPTIONS)请求时,若未合理配置,容易导致大量重复 TCP 连接、无效响应和性能损耗。关键在于:让预检请求快速返回、不穿透到后端,并复用已有连接。
避免 OPTIONS 请求转发到后端
默认情况下,Nginx 可能将 OPTIONS 请求透传给上游服务,而多数后端对预检仅做简单响应(如返回 204),既无业务逻辑又增加延迟。应直接在 Nginx 层拦截并响应。
- 使用 location = / 或更精确的 location ~ ^/api/ 匹配路径,配合 limit_except 或 if ($request_method = 'OPTIONS')
- 推荐写法:不要用 if + return 204(存在隐式限制),改用 limit_except 块内显式允许方法,并设 add_header Access-Control-Allow-Methods 等头
- 示例:
location /api/ { limit_except GET HEAD POST PUT DELETE OPTIONS { deny all; } if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; add_header Access-Control-Max-Age 1728000; add_header Content-Type 'text/plain; charset=utf-8'; add_header Content-Length 0; return 204; } proxy_pass http://backend; }
启用 keepalive 复用 upstream 连接
即使预检被拦截,常规请求仍需与后端保持高效连接。Nginx 默认 upstream 连接是短连接,每次请求新建 TCP 连接会显著拖慢吞吐。
- 在 upstream 块中添加 keepalive 32;(数字表示保活连接池大小)
- 在 location 或 server 块中设置 proxy_http_version 1.1; 和 proxy_set_header Connection '';,确保 HTTP/1.1 持久连接生效
- 可选增强:加 proxy_socket_keepalive on; 启用 socket 层 keepalive,防中间设备断连
控制预检缓存时长(Access-Control-Max-Age)
浏览器根据该响应头决定多久内不再发送预检请求。设得太短(如默认 5 秒)会导致高频 OPTIONS;太长(如数天)则无法及时响应接口权限变更。
- 建议值:3600~86400(1 小时至 1 天),兼顾稳定性与灵活性
- 注意:该头只在 OPTIONS 响应中有效,且必须与 Access-Control-Allow-Origin 同时存在才被浏览器识别
- 若使用通配符 * 作为 Origin,则不能携带 Access-Control-Allow-Credentials: true,否则浏览器拒绝缓存
验证与观测要点
优化是否生效,不能只看配置,要结合真实请求链路确认。
- 用 curl -v -X OPTIONS 检查响应是否由 Nginx 直接返回(查看 Server 头、响应时间、无后端日志)
- 通过 nginx stub_status 或 ss -tnp | grep :80 观察 ESTABLISHED 连接数变化趋势
- 在 Chrome DevTools → Network → Filter 选 XHR,观察跨域请求是否跳过 OPTIONS(说明已缓存)
- 后端 access log 中 OPTIONS 行应大幅减少甚至消失



















