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

REST API内部错误、无请求体POST时错误返回201状态码问题

问题现象

REST API开发中出现状态码返回异常:接口触发内部错误时仍固定返回201状态码。
稳定复现场景:发送未携带任何请求体数据的POST请求时,预期返回400参数错误状态码,实际接口返回201状态码及空对象。
Postman调试请求响应示例:
Postman请求响应截图
存在异常的接口实现代码:

router.post('/', (req: Request, res: Response) => {
const transaction = new Transactions({
    name: req.body?.name,
    amount: req.body?.amount,
    type: req.body?.type,
})
try{
    const newTransaction = transaction.save();
    return res.status(201).json(newTransaction);
}catch (err){
    return res.status(400).json({message: err.message});
}
})
问题根因

两个核心逻辑错误导致异常:

  • Mongoose的save()是异步方法,返回Promise对象,代码中没有加await等待操作执行完成,会直接拿到Pending状态的Promise。同步执行流不会等待数据库写入、字段校验逻辑跑完,也无法捕获异步操作抛出的异常:代码会直接走到res.status(201)的返回逻辑,等异步操作真正抛出错误时,HTTP响应已经发送完成,catch块完全不会触发。
  • 代码使用可选链req.body?.xxx读取请求参数,当请求完全不带请求体时,req.body为undefined,读取到的所有模型字段均为undefined;如果对应Mongoose Schema没有配置必填字段校验规则,实例化模型阶段不会同步抛出错误,最终接口会把Pending状态的Promise序列化为空对象,随201状态码返回给客户端。
修复方案

将路由处理函数改为异步写法,添加await等待save()执行完成,让try/catch可以正常捕获参数校验、数据库操作抛出的异常,同时可补充前置的请求体校验逻辑:

router.post('/', async (req: Request, res: Response) => {
  // 前置校验请求体合法性
  if (!req.body) {
    return res.status(400).json({message: "请求体不能为空"});
  }
  const transaction = new Transactions({
    name: req.body.name,
    amount: req.body.amount,
    type: req.body.type,
  })
  try{
    // 等待异步保存操作完成
    const newTransaction = await transaction.save();
    return res.status(201).json(newTransaction);
  }catch (err){
    return res.status(400).json({message: err.message});
  }
})

优化建议:在Mongoose的Schema定义中,给name/amount/type业务必填字段加上required: true约束,即使省略前置请求体校验,保存操作触发的校验错误也会被catch块捕获,正常返回400状态码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:15:36