为什么浏览器发了 OPTIONS 请求却没发真正的 POST 请求?

___树泽 阅读 25

我在用 React 调后端接口时,发现控制台里只看到一个 OPTIONS 请求,但我的 POST 请求根本没发出去,这是为啥?后端同事说跨域配置没问题,但我本地开发时就是请求失败。

我试过加 headers,也试过换不同的 Content-Type,但都没用。下面是我发起请求的代码:

fetch('https://api.example.com/upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'test' })
})
.then(res => res.json())
.then(data => console.log(data));
我来解答 赞 8 收藏
二维码
手机扫码查看
1 条解答
志鸣~
志鸣~ Lv1
你这情况太常见了,前端这块 OPTIONS 请求其实是浏览器的预检请求(preflight),当你的 POST 请求满足某些条件时,浏览器会先发个 OPTIONS 去问后端:“这请求你接不接?”
但关键点来了——如果后端没正确响应预检请求,真正的 POST 就根本不会发出去,浏览器直接就拦住了。

你代码本身没问题,问题大概率出在后端没正确处理 OPTIONS 请求,或者响应头没配对。
你后端同事说“跨域配置没问题”,那八成是只加了 Access-Control-Allow-Origin,但没处理预检的其他必填头。

正确处理预检请求,后端需要对 OPTIONS 请求返回这些响应头:

- Access-Control-Allow-Origin: https://your-frontend-domain(或者 *,但不推荐生产用)
- Access-Control-Allow-Methods: POST, GET, OPTIONS(必须包含 OPTIONS)
- Access-Control-Allow-Headers: Content-Type, Authorization(你用了 Content-Type,所以这里必须显式声明)
- Access-Control-Max-Age: 86400(可选,缓存预检结果,减少重复请求)

另外,Content-Type 为 application/json 的 POST 请求本身就属于“非简单请求”,一定会触发预检,这点你得记牢。

本地开发建议用代理绕开跨域,比如在 package.json 里配:

"proxy": "https://api.example.com"


然后前端请求改成 fetch('/upload', {...}),这样就走本地 dev server 代理了,浏览器不会触发 OPTIONS,开发体验能舒服很多。

如果一定要直连后端,那就让后端把 OPTIONS 请求的响应头检查清楚,注意响应状态码要是 200 或 204,千万别返回 404 或 500,不然浏览器直接认定“这接口不支持跨域”,你的 POST 就石沉大海了。

你先让后端查查 OPTIONS 请求的响应头和状态码,基本都能定位到问题。
点赞
2026-02-26 06:00