引言
在做跨域请求时,你是否遇到过这种怪事:在 Network 面板里,OPTIONS 预检请求返回了 200 OK,看起来一切正常;但紧随其后的 POST 请求却直接报了 CORS error,甚至点开详情还提示 "Provisional headers are shown" 。
这到底是浏览器的锅,还是后端的错?今晚我们就来扒开这层皮。

一、 罪魁祸首:被遗忘的"入场券"
在跨域场景下,浏览器会发起 OPTIONS 预检。如果你在请求中使用了非简单的 Header(如 JSON 的 Content-Type 或链路追踪的 traceparent),浏览器会发起"礼貌询问":
- 浏览器问:
Access-Control-Request-Headers: content-type, traceparent - 服务器答:
Access-Control-Allow-Headers: Content-Type, Access-Token, ...
坑点就在这里: 如果服务器的白名单里漏掉了哪怕一个 Header(比如本文案例中的 traceparent),浏览器就会认为这场"商业洽谈"失败了。
二、 为什么 OPTIONS 是绿的,POST 却是红的?
这是最让人困惑的地方。既然"洽谈"失败,为什么 OPTIONS 不直接报错?
- OPTIONS 是"获取规则": 服务器成功处理了你的咨询请求,并如实告知了它的配置。从 HTTP 协议看,咨询过程是完美的,所以返回
200 OK。 - POST 是"执行意图": 浏览器拿到服务器的规则后,发现和你手里的"会员卡"(
traceparent)不匹配。为了安全,浏览器单方面拦截了 POST 请求,不让它真正发往服务器。 - "红色"是浏览器的警告: 那个红色的 POST 记录其实是浏览器生成的"虚拟记录",目的是告诉你: "你原本想发这个,但我把它按下了。" > 核心结论:
OPTIONS的成功代表"问答过程成功",不代表"准入结果成功"。
三、 关于 Origin 的安全防线
在排查过程中,我们曾想过:能不能手动在 Headers 里改 Origin?
- 答案是:不行。 在浏览器环境下,
Origin是 Forbidden Header,由浏览器强制控制。 - 为什么? 如果开发者能改
Origin,那么钓鱼网站就能轻易伪装成银行官网,CORS 安全机制将形同虚设。 - 真相:
Origin的存在不由后端决定,但它的"生死存亡"由后端决定。后端通过校验这个自动带上的Origin来决定是否给浏览器发放"过路费"(即Access-Control-Allow-Origin响应头)。
四、 避坑指南:如何彻底解决?
1. 后端侧(根治方案)
不要只配置 Origin。如果前端有自定义 Header(如分布式追踪、身份令牌),必须在 Access-Control-Allow-Headers 中显式添加。
-
代码示例(Node.js):
JavaScript
arduinores.header("Access-Control-Allow-Headers", "Content-Type, traceparent, Your-Custom-Header");
2. 前端侧(调试技巧)
当你看到 "Provisional headers are shown" 且伴随 CORS error 时:
- 第一步: 检查
OPTIONS请求头里的Access-Control-Request-Headers。 - 第二步: 检查
OPTIONS响应头里的Access-Control-Allow-Headers。 - 第三步: 找茬,看谁多了,看谁少了。
结语
Web 开发中,CORS 不是敌人,而是保护数据的保镖。当你理解了浏览器、服务器和安全策略之间的那场"礼貌洽谈",这些诡异的红色报错就不再是迷雾。