Express配置CORS后fetch发POST跨域请求返回400错误排查
Express CORS配置失效+POST请求400报错解决方案
问题根因
报错由三个独立的配置错误共同导致,对中间件顺序的判断只对了一半:
- 客户端请求未做序列化:
fetch的body字段直接传入原生JS对象时,浏览器不会自动转成JSON格式,服务端bodyParser.json()收到非标准JSON格式的请求体时,会直接返回400 Bad Request cors包配置参数完全错误:npm官方cors中间件不识别Access-Control-Allow-Origin、Allow-Methods这类HTTP响应头名作为配置键,合法配置键为origin、methods、allowedHeaders,原有配置完全没有生效- 预检请求未放行:带
Content-Type: application/json的POST请求属于非简单请求,浏览器会先发送OPTIONS方法的预检请求,原有配置的允许方法列表里既没有OPTIONS,还写了不存在的FETCH方法,导致预检直接被拦截
修复方案
客户端代码修正
给请求体增加JSON序列化逻辑,修正后代码:
async modifyTrip() { const submitData = { data: "test", mezzo: "test", coordinate: ["test"], tappe: ["test"], }; const modifyform = document.getElementById("add-form"); modifyform.onsubmit = async (e) => { e.preventDefault(); await fetch("http://localhost:3000/trips", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, // 必须序列化JS对象为JSON字符串 body: JSON.stringify(submitData), }); }; }
服务端配置修正
CORS中间件必须放在所有业务中间件、路由之前挂载,同时修正cors包的配置参数,修正后代码:
const express = require('express'); const cors = require('cors'); const bodyParser = require('body-parser'); const app = express(); // 最先挂载CORS中间件,使用cors包标准配置 app.use( cors({ origin: "*", methods: ["GET", "POST", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Accept"] }) ); // 再挂载body解析中间件 app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // 最后挂载业务路由 app.use("/user", userRoutes); app.use("/trips", tripsRoutes); app.listen(3000);
验证说明:修复后打开浏览器开发者工具网络面板,先确认OPTIONS预检请求返回204状态码,后续POST请求即可正常处理,不会再出现跨域拦截或400报错。
内容的提问来源于stack exchange,提问作者pierbin24
相关产品推荐
相关产品推荐

