无法从浏览器向Express服务器发送JSON,CORS预检请求失败
解决跨域请求中Content-Type为application/json时的CORS错误
嘿,这个问题我太熟了——你踩中了跨域里**预检请求(Preflight Request)**的坑!
问题根源
当你把请求的Content-Type设为application/json时,这属于「非简单请求」,浏览器会在真正发送POST请求前,自动发起一个OPTIONS预检请求,用来询问后端:“我能不能发送这个跨域请求?”
而你的后端目前只在POST接口里设置了CORS头,完全没处理这个OPTIONS预检请求。浏览器收到OPTIONS的响应后,发现里面没有Access-Control-Allow-Origin等必要头,直接就把后续的POST请求拦下来了。
反观你用application/x-www-form-urlencoded或者不设置Content-Type的情况,这些属于「简单请求」,浏览器不会触发预检流程,直接走POST请求,此时你在POST接口里加的CORS头就能生效,所以请求能正常执行。
解决方案
方案1:使用Express的cors中间件(最省心推荐)
这是Express处理跨域的标准方案,它会自动帮你处理所有预检请求,不用手动编写CORS头逻辑。
- 先安装依赖:
npm install cors
- 修改后端代码:
const express = require('express'); const app = express(); const cors = require('cors'); // 引入cors中间件 const bodyParser = require('body-parser'); // 全局启用cors,自动处理所有跨域相关逻辑 app.use(cors()); app.use(bodyParser.urlencoded({extended: true})) app.use(bodyParser.json()); app.post('/test', (req, res) => { // 无需再手动设置CORS头,cors中间件已处理 console.log(req.body) res.json({success: true}); }); // 别忘了添加端口监听(你之前的代码里漏了这部分) app.listen(7300, () => { console.log('后端服务运行在localhost:7300'); });
方案2:手动处理OPTIONS预检请求
如果你不想依赖第三方中间件,可以手动为所有路由处理OPTIONS请求:
const express = require('express'); const app = express(); const bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({extended: true})) app.use(bodyParser.json()); // 处理所有OPTIONS预检请求,返回必要的CORS头 app.options('*', (req, res) => { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Headers', 'Content-Type'); res.sendStatus(200); // 返回200确认允许跨域 }); app.post('/test', (req, res) => { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Headers', 'Content-Type'); console.log(req.body) res.json({success: true}); }); app.listen(7300, () => { console.log('后端服务运行在localhost:7300'); });
修改完成后,当浏览器发送OPTIONS预检请求时,后端会返回正确的CORS响应头,浏览器就会允许后续的POST请求发送JSON数据了。
内容的提问来源于stack exchange,提问作者SkyFlame
相关产品推荐
相关产品推荐

