Vite 代理下的 POST 请求跨域问题排查与解决方案

📌 问题描述

在 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 请求的跨域问题! 🚀

相关推荐
程序员Sunday19 小时前
JavaScript 事件循环面试题,宏任务与微任务怎么执行|Sunday面试指南
开发语言·javascript·面试·校招·事件循环·程序员sunday
默_笙20 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
思无邪6621 小时前
用 AI 做 JS 逆向:从抓包到复现的完整方法论
开发语言·javascript·人工智能
福兮说1 天前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
可乐鸡翅yeah_1 天前
video.js 集成 hls.js 开发 M3U8 播放器,新手高频踩坑
开发语言·前端·javascript·后端·ecmascript·m3u8·音视频在线播放
用户117953654781 天前
TRAE vs Claude Code 性能对比:从代码生成、多文件重构到底层吞吐,谁更适合你的日常开发?
javascript
kill5221 天前
useRef
前端·javascript·react.js
米多科技1 天前
我做了一个 3D 虚拟世界基底,在上面再搭 3D 世界或元宇宙,事半功倍
javascript·人工智能·github
霍营_托尼1 天前
纯前端播 40GB 本地视频?我把浏览器改造成了「磁盘流式」播放器
前端·javascript·音视频开发
西柚小萌新1 天前
【LLM&&AI应用开发 八股文】--4.2.Agent智能体(中)
前端·javascript·react.js