Node.js Express中如何处理客户端发送的空请求体?
Express POST接口处理请求体为null的解决方案
在Express框架中,POST接口/api/health-check收到请求体为null的POST请求时,触发SyntaxError,提示"null" is not valid JSON,错误栈如下:
SyntaxError: Unexpected token 'n', "null" is not valid JSON at JSON.parse (<anonymous>) at createStrictSyntaxError (/Users/aungmyooo/Development/INTERVIEW-TEST/teamups-tech-x/server/node_modules/body-parser/lib/types/json.js:169:10) at parse (/Users/aungmyooo/Development/INTERVIEW-TEST/teamups-tech-x/server/node_modules/body-parser/lib/types/json.js:86:15) at /Users/aungmyooo/Development/INTERVIEW-TEST/teamups-tech-x/server/node_modules/body-parser/lib/read.js:128:18 at AsyncResource.runInAsyncScope (node:async_hooks:206:9) at invokeCallback (/Users/aungmyooo/Development/INTERVIEW-TEST/teamups-tech-x/server/node_modules/raw-body/index.js:238:16) at done (/Users/aungmyooo/Development/INTERVIEW-TEST/teamups-tech-x/server/node_modules/raw-body/index.js:227:7) at IncomingMessage.onEnd (/Users/aungmyooo/Development/INTERVIEW-TEST/teamups-tech-x/server/node_modules/raw-body/index.js:287:7) at IncomingMessage.emit (node:events:518:28) at IncomingMessage.emit (node:domain:488:12)
问题原因
问题出在body-parser的默认配置上:它开启了严格模式(strict: true),该模式下不允许单独的null、undefined或原始类型(如字符串、数字)作为JSON的顶级值,尽管这些在JSON标准中是合法的。当请求体是字符串"null"时,严格模式会直接抛出语法错误。
解决方案
方案1:修改body-parser配置允许解析null
修改bodyParser.json()的调用,添加strict: false选项,让它可以解析顶级的null、字符串等原始值:
// 替换原来的app.use(bodyParser.json()); app.use(bodyParser.json({ strict: false }));
修改后,请求体为null时,req.body会被解析为null,此时路由中的!req.body判断会生效,返回预期的400响应。
方案2:全局错误处理中捕获JSON解析错误
如果不想修改全局的body-parser配置,可以在全局错误中间件中专门捕获这个语法错误,返回更合理的400响应(而非默认的500):
app.use((err: Error, req: Request, res: Response, next: NextFunction) => { console.error(err.stack); // 判断是否为JSON解析错误 if (err instanceof SyntaxError && (err as any).status === 400 && 'body' in err) { return res.status(400).json({ error: "请求体格式无效,无法解析为JSON" }); } res.status(500).json({ error: "服务器内部错误" }); });
方案3:针对health-check路由跳过body解析
如果/api/health-check接口不需要请求体,可以单独为该路由跳过body解析,避免触发解析错误:
// 先定义不需要body解析的health-check路由 app.post("/api/health-check", express.raw({ type: '*/*' }), (req: Request, res: Response) => { const bodyStr = req.body?.toString().trim(); if (!req.body || bodyStr === 'null') { res.status(400).json({ error: "Request payload is null or empty" }); return; } res.json({ message: "pong" }); }); // 再挂载其他需要body解析的中间件和路由 app.use(bodyParser.json()); app.use("/api", coustomerLoyaltyRouter);
注意:这种方式需要把该路由放在bodyParser.json()中间件之前,避免被全局解析逻辑影响。
内容的提问来源于stack exchange,提问作者Alex Aung
相关产品推荐
相关产品推荐

