Node.js中如何记录响应体?Morgan中间件获取res.body遇阻
解决Morgan无法获取响应体的方案
Morgan 默认不会自动把响应内容挂载到 res.body 上,所以直接读取 res.body 会得到 undefined。要获取响应体,得先通过中间件劫持 Express 的响应发送方法,把响应内容暂存到 res.body 中。
步骤1:添加响应体拦截中间件
在 Morgan 中间件之前,添加自定义中间件劫持 res.json 和 res.send 方法,提前保存响应内容:
app.use((req, res, next) => { // 保存原始的json方法 const originalJson = res.json; res.json = function(data) { // 将响应内容存入res.body res.body = data; // 调用原始方法发送响应 return originalJson.call(this, data); }; // 保存原始的send方法 const originalSend = res.send; res.send = function(data) { // 处理不同类型的响应数据 if (typeof data === 'object' && data !== null) { res.body = data; } else { try { // 尝试解析为JSON格式,失败则存原始值 res.body = JSON.parse(data); } catch (e) { res.body = data; } } return originalSend.call(this, data); }; next(); });
步骤2:修改Morgan响应体Token
现在 res.body 已被赋值,自定义Token可以正常读取:
morgan.token('sbody', (res) => { // 兜底处理res.body不存在的情况 return JSON.stringify(res.body || {}); });
完整示例代码
将中间件与Morgan配置结合使用:
const express = require('express'); const morgan = require('morgan'); const app = express(); // 先解析请求体(必须在Morgan之前) app.use(express.json()); app.use(express.urlencoded({ extended: true })); // 响应体拦截中间件 app.use((req, res, next) => { const originalJson = res.json; res.json = function(data) { res.body = data; return originalJson.call(this, data); }; const originalSend = res.send; res.send = function(data) { if (typeof data === 'object' && data !== null) { res.body = data; } else { try { res.body = JSON.parse(data); } catch (e) { res.body = data; } } return originalSend.call(this, data); }; next(); }); // 自定义Morgan Tokens morgan.token('qbody', (req) => { return JSON.stringify(req.body || {}); }); morgan.token('sbody', (res) => { return JSON.stringify(res.body || {}); }); // 使用自定义格式的Morgan日志 app.use(morgan(':method :url :status :response-time ms - Request Body: :qbody - Response Body: :sbody')); // 测试路由 app.post('/test', (req, res) => { res.json({ message: 'success', received: req.body }); }); app.listen(3000, () => { console.log('Server running on port 3000'); });
注意事项
- 响应体拦截中间件必须放在Morgan中间件之前,确保先完成方法劫持。
- 必须先通过
express.json()或express.urlencoded()解析请求体,否则req.body也会是undefined。 - 如果应用使用了
res.sendFile这类发送文件流的方法,无需劫持(这类内容不适合存入res.body),按需扩展劫持逻辑即可。
内容的提问来源于stack exchange,提问作者Venkat Cpr
相关产品推荐
相关产品推荐

