CORS 预检请求排查指南:OPTIONS、跨域头与网关配置一次讲清
“接口明明通,浏览器却报 CORS”是最常见的线上联调阻塞之一。多数问题不在业务逻辑,而在跨域头、代理层和预检缓存的细节。把排查顺序固定下来,可以大幅减少来回试错。
1. 先理解什么时候会触发预检
浏览器在下列情况会先发 `OPTIONS` 预检:
- 方法不是简单方法(例如 `PUT`、`DELETE`)。
- 请求头包含自定义头(例如 `Authorization`、`X-Trace-Id`)。
- `Content-Type` 不是简单类型(例如 `application/json`)。
预检失败时,真正业务请求根本不会发出去,所以后端日志里可能看不到对应 `POST` 或 `PUT`。
2. 按“浏览器报错语句”定位配置缺口
常见报错基本能直接映射到缺失项:
- `No 'Access-Control-Allow-Origin'`:服务端没回允许来源。
- `Method ... is not allowed`:`Access-Control-Allow-Methods` 缺少对应方法。
- `Request header field ... is not allowed`:`Access-Control-Allow-Headers` 未放行该头。
- `credentials mode is include` 报错:使用了 Cookie,但 Origin 配置为 `*`。
先让报错和响应头逐项对齐,比“改一行试一次”更快。
3. 网关与应用层必须同口径
很多团队只在应用层加 CORS 中间件,却忽略了 Nginx/API Gateway。真实链路通常是:浏览器 -> CDN -> 网关 -> 服务。只要中间有一层吞掉或改写头部,前端仍会失败。
建议固定责任边界:要么统一在网关处理 CORS,要么网关透传并由应用层统一处理,避免双重配置互相打架。
4. Cookie 场景的三个硬条件
跨域带 Cookie(`credentials: include`)时,必须同时满足:
- `Access-Control-Allow-Credentials: true`
- `Access-Control-Allow-Origin` 不能是 `*`,必须是具体域名
- Cookie 端设置 `SameSite=None; Secure`
这三项缺任何一项,都会出现“本地能用、线上不稳定”问题。
5. 用预检缓存降低 OPTIONS 放大
高频接口如果每次都预检,会产生额外延迟与网关开销。可配置 `Access-Control-Max-Age` 缓存预检结果,但要兼顾安全与变更频率,通常从 600 秒到 3600 秒逐步评估。
先保证正确,再做缓存优化。错误的 CORS 配置缓存会把问题放大到整个用户群。
推荐排查流程(10 分钟版本)
- 浏览器 Network 面板确认是否发了 OPTIONS。
- 对照预检响应头,定位缺失字段。
- 检查网关是否覆盖或删除了 CORS 头。
- 检查 Cookie 场景是否满足三条件。
- 确认修复后再加 `Access-Control-Max-Age`。
这个流程跑通后,80% 的跨域问题都能在联调阶段解决,不会拖到发布窗口。