如何在Express JSON初始化器前执行请求日志任务?
问题原因及解决方案
你当前的代码无法捕获无效JSON请求日志的核心问题有两个:
- 你写的是错误处理中间件(带
err参数的四参数中间件),但错误处理中间件必须放在所有可能抛出错误的中间件之后才能生效,你把它放在了express.json前面,根本触发不到。 express.json遇到无效JSON时会自动抛出entity.parse.failed类型的错误,但如果没有对应的错误处理逻辑,Express会用默认处理器直接返回响应,不会走你的日志代码。
方案一:调整中间件顺序+捕获JSON解析错误
先放普通的请求预处理日志中间件(如果需要记录请求到达的基础信息),再加载JSON解析器,最后放错误处理中间件捕获解析错误:
// 预处理日志:记录所有收到的请求(在JSON解析前执行) app.use((req, res, next) => { logger.info({ event: 'request_received', method: req.method, path: req.path }); next(); }); // 加载JSON解析中间件 app.use(express.json({ limit: '50mb' })); // 错误处理中间件:放在所有业务中间件之后 app.use((err, req, res, next) => { // 判断是否为JSON解析错误 if (err.type === 'entity.parse.failed') { logger.error({ event: 'invalid_json_request', msg: '收到无效JSON payload', method: req.method, path: req.path, error_detail: err.message }); console.log('捕获到无效JSON请求:', err.message); } else { // 处理其他类型错误 logger.error({ event: 'request_error', msg: err.message, error_stack: err.stack }); } // 给客户端返回标准化错误响应 res.status(err.status || 400).json({ code: 'BAD_REQUEST', message: err.message || '无效请求' }); });
方案二:通过verify选项提前捕获解析错误
给express.json配置verify函数,在解析阶段直接捕获无效JSON并记录日志:
app.use(express.json({ limit: '50mb', verify: (req, res, buf, encoding) => { try { // 手动尝试解析JSON,提前验证 JSON.parse(buf.toString(encoding)); logger.info({ event: 'valid_json_received', method: req.method, path: req.path }); } catch (err) { // 解析失败时立即记录日志 logger.error({ event: 'invalid_json_request', msg: '无效JSON格式', method: req.method, path: req.path, error_detail: err.message }); console.log('无效JSON请求详情:', err.message); // 抛出错误,交给后续错误处理中间件处理响应 throw err; } } })); // 错误处理中间件:统一返回错误响应 app.use((err, req, res, next) => { res.status(400).json({ code: 'INVALID_JSON', message: '请求JSON格式无效' }); });
关键注意点
- 错误处理中间件必须放在所有可能抛出错误的中间件之后,才能捕获到上游的错误。
- 可以通过
err.type === 'entity.parse.failed'精准判断是否是Express JSON解析器抛出的错误。
内容的提问来源于stack exchange,提问作者Shivam Balikondwar
相关产品推荐
相关产品推荐

