被预检请求卡了一下午,才真正读懂 CORS
前后端联调,控制台报 blocked by CORS policy。后端说"我加了跨域头",前端说"还是报错"。这种来回扯皮的场景,最后往往发现是预检请求没对上。
浏览器把跨域请求分成两类。简单请求直接发出,服务器响应里带 Access-Control-Allow-Origin 就放行;非简单请求要先发一个 OPTIONS 请求试探——带上 Access-Control-Request-Method 和 Access-Control-Request-Headers,问服务器"我接下来要这么干,你允许吗"。
什么算非简单请求?两个常见触发条件:请求方法不是 GET/POST/HEAD,或者 Content-Type 不是表单那三件套。所以 application/json 的 POST 一定会预检——这就是为什么接口明明配了跨域头、JSON 请求还是挂。

排查的时候有个好办法:网络面板里先看那条 OPTIONS 请求的状态。它 204 了,真正的请求才会发出去;它 405 了,说明后端根本没处理 OPTIONS。后端框架一般有现成的跨域中间件,自己手写响应头最容易漏掉 Access-Control-Allow-Headers——允许来源配了,允许的自定义头没配,照样挂。
还有一个高频坑:跨域时 cookie 默认不带。credentials: 'include' 是前端的事,后端也要把 Allow-Origin 写成具体域名(通配符 * 和凭证模式互斥)。两边少改一边,就是一次"明明都配了"的灵异事件。
理解了预检,CORS 就不是玄学:它是浏览器代替服务器做的一次白名单确认。报错信息虽然丑,但每一行都指向具体的缺失项。