JSFiddle中POST请求首次预检失败及预检顺序相关疑问
CORS预检请求相关问题解答
测试代码
前端Fetch代码
const data = { name: 'example', password: 'password'}; fetch('http://localhost:3001', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }) .then((response) => response.json()) .then((data) => { console.log('Success:', data); }) .catch((error) => { console.error('Error:', error); });
后端Express代码
const express = require('express') const app = express() app.get('/', (req, res) => { res.send('Hi') }) app.post('/', (req, res) => { console.log('received') res.send('Received') }) app.listen(3001, () => { console.log('Listening on port', 3001) })
问题解答
1. POST请求的首次预检(preflight)请求失败是否属于正常情况?
不正常。预检请求失败的核心原因是你的Express后端没有处理OPTIONS请求,也未返回任何CORS相关响应头,导致浏览器的同源策略校验不通过。对于包含Content-Type: application/json的POST请求,浏览器会判定为非简单请求,必须先发起OPTIONS预检请求,确认服务器允许跨域后才会发送实际POST请求。服务器没有配置CORS支持时,预检请求会直接失败。
2. 成功的预检请求不应在POST请求之前发起吗?服务器端POST处理代码未执行(无日志输出),说明浏览器取消了POST请求,浏览器如何在预检请求完成前就决定不发送POST请求?
正常逻辑下,预检请求(OPTIONS)必然在实际请求(POST)之前发起,你看到的“fetch请求之后发生预检”是浏览器DevTools的显示顺序误导,实际网络请求的优先级是预检先发送。服务器没收到POST请求,是因为预检请求失败后,浏览器直接拦截了后续的实际请求,根本不会将POST请求发送到服务器,自然不会触发后端的POST处理逻辑。
补充场景分析
- 改用本地HTML页面测试后预检不再失败:如果本地HTML页面和后端服务同属
localhost域名,属于同源请求,浏览器不会触发预检流程。此时你看到的OPTIONS请求可能是其他操作触发,或是DevTools的显示偏差。 - GET请求控制台报错但网络面板无报错:GET请求属于简单请求,浏览器不会发起预检,会直接发送请求。但如果服务器未返回CORS允许的响应头,浏览器会拦截响应内容,在控制台抛出跨域错误;但网络层面请求已经完成,所以网络面板不会显示请求失败。
内容的提问来源于stack exchange,提问作者Dropin' Science
相关产品推荐
相关产品推荐

