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

Express中间件中req.body为{}但控制器可正常获取如何解决

问题原因

你遇到的问题核心是CORS预检OPTIONS请求没有被提前处理,加上异步中间件没有做异常捕获,具体逻辑如下:

  1. 跨域POST请求触发时,浏览器会自动先发送OPTIONS类型的预检请求,用来验证服务端的跨域配置是否合法,这个请求本身没有请求体,所以req.body为空
  2. 你当前的CORS中间件没有对OPTIONS请求做特殊处理,会直接把请求传递到后续的productRouter.use("/pay")中间件
  3. 中间件里直接执行req.body.basketItems.items.map,因为req.body是空对象,这一步会直接抛出空指针异常,请求被中断,不会走到后续逻辑
  4. 你看到的paymentController能拿到req.body,大概率是你用Postman等接口测试工具发请求(这类工具不会发送OPTIONS预检),或者你没有注意到控制台里的报错日志。

修复方案

1. 修复CORS中间件,提前处理OPTIONS请求

修改你server.js里的CORS中间件,遇到OPTIONS请求直接返回204状态,不需要走到业务逻辑:

// Add headers before the routes are defined
app.use(function (req, res, next) {
  // Website you wish to allow to connect
  res.setHeader("Access-Control-Allow-Origin", "*");

  // Request methods you wish to allow
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, OPTIONS, PUT, PATCH, DELETE"
  );

  res.header("Access-Control-Allow-Headers", "Content-Type");
  // Set to true if you need the website to include cookies in the requests sent
  // to the API (e.g. in case you use sessions)
  res.setHeader("Access-Control-Allow-Credentials", true);

  // 新增:处理OPTIONS预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(204);
  }

  // Pass to next layer of middleware
  next();
});

2. 给异步中间件加异常捕获和参数校验

避免因为请求参数不合法直接抛出异常阻断请求:

productRouter.use("/pay", async (req, res, next) => {
  try {
    console.log("当前请求方法:", req.method);
    console.log("req.body:", req.body);
    // 增加参数校验
    if (!req.body?.basketItems?.items) {
      return res.status(400).send({ message: "请求参数缺失basketItems" });
    }
    // 原有计算逻辑不变
    const productIdsAndAmounts = req.body.basketItems.items.map((item) => {
      return { id: item.id, amount: item.amount };
    });
    // ... 剩余原有逻辑 ...
    req.totalPrice = totalTotalPrice;
    next();
  } catch (err) {
    console.error("支付中间件执行错误:", err);
    res.status(500).send({ message: "服务端错误" });
  }
});

3. 核对导入名称(可选)

你贴的代码里paymentController.js导出的函数名为paymentController,但productRouter里导入的是payment,如果实际代码也是这么写的会导致导入失败,你可以自行核对修正。

修复完成后,OPTIONS请求会被CORS中间件直接拦截返回,不会进入业务中间件,POST请求进入中间件时就能正常拿到express.json()解析后的req.body,计算完成后的req.totalPrice也可以正常在payment控制器里访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:27:02