为什么有时候会发送两次请求(cors 预检)
2024年5月6日大约 3 分钟
为什么有时候会发送两次请求(cors 预检)
CORS
CORS(跨域资源共享) 是前后端开发中一个核心的概念。
cors 是一种浏览器的安全机制,允许服务器指定哪些源可以访问他的资源。
浏览器出于安全考虑,默认禁止从不同的源请求数据。
这项限制就是 同源策略
这里的“同源”指的是: 协议、域名、端口必须一致。
同源策略主要是防止以下的危险行为:
- 窃取敏感信息(如 Cookie / LocalStorage / 响应内容)
- JS 操作 iframe 跨源 DOM
- JS 读取跨域接口响
- xss 攻击
请求的两种类型
在 Http 请求中,请求会被分为两种类型
- 简单请求
简单请求需要同时满三个条件:
- 请求方法是以下三种方法之一:HEAD,GET,POST
- HTTP 的头信息不超出以下几种字段:
- Accept:指定返回类型,: text/plain(纯文本类型), text/html(html 类型)
- Accept-Language 指定返回语言
- Content-Language 指定内容语言
- Content-Type:只限于三个值
1. application/x-www-form-urlencoded:对发送内容进行编码
2. multipart/form-data:上传的表单内包含文件
3. text/plain:发送内容为纯文本格式 - 请求不携带 credentials(cookie / HTTP 认证头)
除非服务端明确允许携带 credentials
- 非简单请求
任何不满足简单请求的请求都是非简单请求,在进请求时浏览器会自动先发一个OPTIONS 请求进行**预检**,确认服务端是否允许跨源通信,只有在预检通过的时候才会进行真正的请求
预检通过后段会在响应头返回
| 字段 | 说明 |
|---|---|
| Access-Control-Allow-Origin | 指定允许的前端源,例如 https://example.com,不能省 |
| Access-Control-Allow-Methods | 指定允许哪些 HTTP 方法(如 GET, POST, PUT) |
| Access-Control-Allow-Headers | 指定前端请求中允许使用的自定义请求头(如 Authorization, Content-Type) |
| Access-Control-Allow-Credentials | 若为 true,表示允许携带 cookie、认证信息等 |
| Access-Control-Max-Age | 浏览器缓存这次预检许可的时间(秒),避免频繁发送 OPTIONS |
某些请求发送两次,实际上是触发了预检操作
背景
「为什么有时候会发送两次请求(cors 预检)」对应前端高频异步问题,现象常见但根因复杂,必须通过时序建模来定位。
核心原理
同步栈、微任务、宏任务的执行关系决定了大多数异步行为。
若不先厘清调度边界,容易把时序问题误判为网络或框架问题。
实现方式 / 示例
建议采用最小复现并输出时序日志,分别验证成功、失败、超时、取消四类分支。
常见问题
- 仅验证 happy path,忽略异常分支。
- 把代码顺序等同执行顺序。
- 缺少可复现样例,团队无法协同排查。
最佳实践
将异步问题沉淀为时序图与排障 Runbook,持续复用到后续模块。
总结
围绕「为什么有时候会发送两次请求(cors 预检)」的重点是把“偶发”问题转为“可复现、可解释、可治理”的工程问题。
