fetch触发OPTIONS预检当使用PUT/DELETE等非常规方法、含自定义请求头或非标准Content-Type时;前端可降级为简单请求规避,但需后端配合,且credentials需显式设为include并配对应响应头。
JavaScript 无法绕过浏览器的同源策略直接请求不同源的后端 API,CORS 不是前端能“解决”的问题,而是必须由后端配置响应头;但前端可以主动规避预检(preflight)或适配其行为。
当 fetch 发出的请求满足以下任一条件

OPTIONS 请求(即预检):
GET、HEAD、POST 之外的 HTTP 方法(如 PUT、DELETE)Authorization、X-Request-ID)Content-Type 不是以下三种之一:text/plain、multipart/form-data、application/x-www-form-urlencoded
预检失败(如后端未返回 Access-Control-Allow-Origin 等头)会导致整个请求被浏览器拦截,控制台报错 Failed to fetch 或 No 'Access-Control-Allow-Origin' header。
如果后端暂时无法改 CORS 配置,可尝试让请求“降级”为简单请求:
POST 代替 PUT/DELETE,并在 body 中传 {_method: "PUT"}(需后端配合解析)Authorization 头,改用 query 参数或 cookie(前提是后端支持且 cookie 已开启 withCredentials)Content-Type: application/json,改用 JSON.stringify() + 默认 text/plain(但后端可能无法解析,慎用)Content-Type: application/json 加入 Access-Control-Allow-Headers
当需要携带 Cookie 或认证信息时,credentials 选项不能省略或设为 "omit":
fetch('https://api.example.com/data', {
method: 'GET',
credentials: 'include' // 必须显式写,不能依赖默认值
})
同时后端响应头必须包含:
Access-Control-Allow-Origin: https://your-frontend-domain.com(不能为 *)Access-Control-Allow-Credentials: true漏掉任意一项,浏览器都会拒绝响应。注意:本地开发时 http://localhost:3000 和 http://127.0.0.1:3000 被视为不同源,也需分别配置。
遇到 CORS 报错,别急着改前端代码:
OPTIONS 请求 → 看 Response Headers 是否含 Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers
OPTIONS 响应状态码是否为 200(不是 404 或 405)OPTIONS 请求做了特殊拦截(如某些框架默认不处理,或中间件跳过了 preflight)很多“前端调不通”的问题,根源是后端没真正响应 OPTIONS,或者响应头拼写错误(比如写成 Access-Control-Allow-Orgin)。预检这一步,前端只能观察和适配,没法替后端兜底。