简单请求不会触发预检,但满足任一条件(非常用方法、自定义头、非标准content-type、credentials+*跨域)即变复杂请求并触发options预检;需后端正确配置cors响应头或调整前端请求方式。

简单请求不会触发预检(OPTIONS),但稍作改动就可能被浏览器自动识别为复杂请求,从而卡在预检失败上。关键不在于“升级”本身,而在于哪些操作会悄悄越过简单请求的边界。
哪些操作会让简单请求变复杂
只要满足以下任一条件,浏览器就会把它当复杂请求处理,强制发一次 OPTIONS 预检:
- 请求方法不是 GET、HEAD 或 POST
- 设置了自定义请求头,比如 X-Auth-Token、Authorization、X-Request-ID
-
Content-Type 值不是以下三者之一:
text/plain、multipart/form-data、application/x-www-form-urlencoded - 使用了 fetch 并设置了 credentials: 'include',且服务端 Access-Control-Allow-Origin 设为 *(这会直接报错)
常见“踩坑”场景举例
你以为是简单请求,其实早已越界:
- 用 POST 发 JSON 数据:
Content-Type: application/json→ 触发预检 - 加了 token:
headers: { Authorization: 'Bearer xxx' }→ 触发预检 - 用 PUT 或 DELETE 方法 → 触发预检
- 前端设了
withCredentials = true,但后端响应头仍写Access-Control-Allow-Origin: *→ 预检通过但主请求被拒
如何避免或应对预检失败
目标不是消灭预检,而是让预检顺利通过:
- 后端必须对 OPTIONS 请求返回完整 CORS 头:
Access-Control-Allow-Origin、
Access-Control-Allow-Methods、
Access-Control-Allow-Headers(值要和前端实际发的一致)、
Access-Control-Allow-Credentials(如需带 cookie) - 如果只是想发 JSON,又不想改后端,可临时改用 POST + 表单格式:
body: new URLSearchParams({ key: 'value' }),保持Content-Type为默认表单类型 - 开发阶段可用 代理(如 vite 的 server.proxy 或 webpack devServer.proxy)绕过浏览器限制,不走真实跨域
检查预检是否生效的小技巧
打开浏览器开发者工具 → Network 标签页 → 找到请求前出现的 OPTIONS 条目 → 点开看它的响应头是否包含上述 CORS 字段。没有?那就是后端漏配了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











