如何在morgan()中间件中获取请求体并自定义日志输出格式
方案实现与推荐
方案1:原生morgan自定义token(推荐优先使用)
该方案完全可以满足需求,核心是调整中间件顺序+自定义token:
- 首先必须先注册JSON请求体解析中间件,再注册morgan,否则req.body会是undefined。现在express已经内置了json解析能力,无需单独安装body-parser依赖。
- 调用
morgan.token()方法自定义获取请求体的token,再自定义日志输出格式即可。
代码示例:
const express = require('express'); const morgan = require('morgan'); const app = express(); // 1. 先注册请求体解析中间件,必须放在morgan之前 app.use(express.json()); // 2. 自定义morgan token,用于获取POST请求的请求体 morgan.token('post-body', (req) => { // 仅POST请求返回请求体内容,其他请求返回空字符串避免冗余 return req.method === 'POST' ? JSON.stringify(req.body) : ''; }); // 3. 自定义日志格式,可按需调整字段顺序、样式,匹配要求的输出规范 const customLogFormat = ':method :url :status :res[content-length] - :response-time ms :post-body'; app.use(morgan(customLogFormat)); // 后续的业务代码和原有逻辑完全一致 const generateId = () => { const randNum = Math.floor(Math.random() * 5000) return randNum; } let notes = [] // 原有代码漏了notes变量的初始化,此处补充 const isExist = (arr, name) => { return arr.some(arrItem => arrItem.name === name) } app.post('/api/persons', (req, res) => { const body = req.body if (!body.name || !body.number) { return res.status(400).json({ error: "missing data" }) } else if (isExist(notes, body.name) === true) { return res.status(400).json({ error: "existed data" }) } const note = { id: generateId(), name: body.name, number: body.number } notes = notes.concat(note) res.json(note) }) const PORT = 3001; app.listen(PORT, () => { console.log(`Server is working on ${PORT}`) })
如果需要在JS代码中直接调用获取日志内容,不用默认输出到控制台,可以给morgan传入第二个参数,指定write回调接收日志内容:
app.use(morgan(customLogFormat, { write: (logStr) => { // 这里可以拿到拼接好的完整日志字符串,做自定义存储、上报等操作 console.log('自定义处理日志:', logStr) } }))
方案2:使用morgan-body(不推荐自定义场景使用)
morgan-body是基于原生morgan封装的上层工具,核心能力是默认封装了请求体、响应体的打印逻辑,但官方没有提供自定义token的相关配置,仅支持调整预设参数(如是否打印请求头、是否过滤敏感字段等),无法灵活调整日志的整体输出格式,无法满足自定义指定样式的需求。
方案选择建议
优先选择原生morgan自定义token的方案,原因如下:
- 依赖更轻量:无需额外安装morgan-body,仅用已有的morgan即可实现需求
- 灵活性更高:可以完全自主定义日志的字段、顺序、样式,100%匹配任务要求的输出规范
- 可控性更强:可以自主控制哪些请求需要打印请求体、哪些字段需要过滤,避免日志冗余
- 维护成本更低:原生morgan的文档更完善,自定义逻辑简单透明,后续调整成本远低于黑盒封装的morgan-body
另外你最初的代码无法获取请求体的核心原因是没有提前注册JSON请求体解析中间件,且morgan注册顺序早于请求体解析中间件,不是morgan本身不支持获取请求体。
内容的提问来源于stack exchange,提问作者rd9911
相关产品推荐
相关产品推荐

