📌 问题描述
在 Vite 开发环境中,我遇到了一个奇怪的现象:
- GET 请求可以成功返回数据
- POST 请求却返回
403 Forbidden: Invalid CORS request - 但如果我手动使用
fetch直接请求服务器 API,POST 请求可以成功
我的 Vite 代理配置如下:
ts
server: {
proxy: {
'/api': {
target: 'https://www.example.cn',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '/api/back')
}
}
}
在 axios 中的 POST 请求:
ts
request.post({ url: '/queryRealTimeData' })
最终 POST 请求失败,并在控制台看到:
403 Forbidden: Invalid CORS request
🔍 排查过程
1️⃣ 直接测试服务器 API
为了确认后端 API 是否工作正常,我手动使用 fetch 在本地 HTML 文件中调用 API:
js
const response = await fetch(
"https://www.example.cn/api/back/query",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({})
}
);
请求成功!这说明后端 API 本身没有问题。
2️⃣ 检查 Vite 代理的 POST 请求
我打开 Network 面板,查看 Vite 代理的 POST 请求,发现:
- 请求的
Origin是http://localhost:4000 - 服务器的
CORS规则仅允许http://127.0.0.1:5500 - 浏览器在
POST之前会先发送OPTIONS预检请求,而这个请求被拒绝了
为了确认 OPTIONS 是否真的被拒绝,我手动执行:
sh
curl -X OPTIONS -H "Origin: http://localhost:4000" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type" \
https://www.liontry.cn/api/back/moon/queryRealTimeData -v
返回:
403 Forbidden: Invalid CORS request
确认问题:后端的 CORS 规则不允许 localhost:4000,但允许 127.0.0.1:5500,所以 Vite 代理的请求失败!
3️⃣ 解决方案
✅ 方案 1:伪装 Origin
由于后端只允许 127.0.0.1:5500,但 Vite 运行在 localhost:4000,我修改 Vite 代理,在 headers 里手动伪装 Origin:
ts
server: {
proxy: {
'/api': {
target: 'https://www.example.cn',
changeOrigin: true,
secure: false,
headers: {
Origin: 'http://127.0.0.1:5500' // 伪装成被允许的 Origin
},
rewrite: (path) => path.replace(/^\/api/, '/api/back')
}
}
}
修改后,POST 请求成功!
✅ 方案 2:让后端允许 localhost:4000
如果后端可修改,最好的办法是让后端 CORS 规则允许 localhost:4000:
http
Access-Control-Allow-Origin: http://127.0.0.1:5500, http://localhost:4000
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type
📌 这样,无论是 fetch 还是 Vite 代理的 axios,都能正常请求!
🎯 总结
| 问题 | 原因 | 解决方案 |
|---|---|---|
| GET 请求成功,但 POST 失败 | POST 触发 OPTIONS 预检,后端 CORS 限制了 Origin |
让后端允许 localhost:4000,或在 Vite 代理中伪装 Origin |
fetch 请求成功,Vite 代理的 POST 失败 |
fetch 直接请求 127.0.0.1:5500,Vite 代理使用 localhost:4000 |
在 Vite 代理 headers 里伪装 Origin |
CORS 报错 Invalid CORS request |
后端不允许 localhost:4000 作为 Origin |
让后端添加 localhost:4000 到 Access-Control-Allow-Origin |
💡 最终,我通过在 Vite 代理中伪装 Origin 解决了 POST 请求的跨域问题! 🚀