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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 14:06:07