You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS+Express接收React POST请求req.body为空问题排查

问题根因
  • Access-Control-Allow-*系列是服务端返回给浏览器的CORS响应头,绝对不能在前端请求头里手动添加,手动加这类头反而会触发异常CORS校验逻辑。
  • 带Content-Type: application/json的POST请求属于CORS非简单请求,浏览器会自动先发OPTIONS方法的预检请求,之前的配置要么没有正确响应预检,要么中间件顺序错误导致预检被拦截,才会触发跨域报错。
  • 前端发请求时没有指定正确的Content-Type: application/json头,Express内置的express.json()中间件只有识别到请求头标记为JSON格式时,才会解析请求体挂载到req.body上,这是req.body为空的直接原因。
  • 额外参数错误:之前前端直接JSON.stringify(tipologia)序列化字符串值,就算解析成功req.body也只会拿到part-time这个字符串,拿不到tipologia属性。
  • CORS规则限制:开启credentials: true(允许携带会话cookie)时,origin不能设为通配符*,必须指定明确的前端源地址。
修复步骤

1. 修改前端请求代码

删除请求头中错误的CORS相关字段,添加正确的Content-Type头,修正请求体传参格式:

function CreateStudyPlan(tipologia){
  return new Promise((resolve, reject) => {
    fetch((URL+'/PianoStudio'), {
      method: 'POST',
      credentials: 'include',
      headers: {
        "Content-Type": "application/json"
      },
      // 包装为对象传递,后端才能通过req.body.tipologia拿到值
      body: JSON.stringify({ tipologia }),
    }).then((response) => {
      if (response.ok) {
        resolve(null);
      } else {
        response.json()
          .then((message) => { reject(message); })
          .catch(() => { reject({ error: "Cannot parse server response." }) });
      }
    }).catch(() => { reject({ error: "Cannot communicate with the server." }) });
  });
}

2. 调整后端中间件顺序与CORS配置

CORS中间件必须放在所有其他中间件(日志、JSON解析、路由、鉴权)的最前面,否则OPTIONS预检请求会被提前拦截,触发跨域报错:

// 最先注册CORS中间件
const corsOptions = {
  origin: 'http://localhost:3000',
  credentials: true,
  allowedHeaders: ['Content-Type', 'Authorization'], // 明确允许Content-Type等常用请求头
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] // 允许预检请求的OPTIONS方法
};
app.use(cors(corsOptions));

// CORS配置完成后再注册其他中间件
app.use(morgan('dev'));
app.use(express.json());

// 后续鉴权、路由代码无需修改
const isLoggedIn = (req, res, next) => {
  if(req.isAuthenticated())
    return next();
  
  return res.status(401).json({ error: 'not authenticated'});
}

app.post('/PianoStudio', isLoggedIn, async (req, res) => {
  try {
    await dao.createPianoStudio(req.body, req.user.id);   
    res.status(201).json(req.body);
  } catch(err) {
    console.log(err);
    res.status(503).json({error: `Database error during the creation of piano di studi for user ${req.user.id}.`});
  }
});
验证要点
  • 修改完成后重启后端服务,清空浏览器缓存再发请求
  • 先检查OPTIONS预检请求返回状态码为200/204,无跨域报错
  • 正式POST请求的Payload格式为{"tipologia":"part-time"},请求头携带正确的Content-Type: application/json
  • 服务端打印req.body即可正常拿到结构化参数,不会为空。

内容的提问来源于stack exchange,提问作者redbite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 00:21:40