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

Node.js Express中Morgan中间件无法获取req/res及应用配置问题

问题排查与解决方案

错误原因

Morgan 的 stream 选项不支持直接传入函数,它要求的值必须是一个具备 write() 方法的流对象(比如 fs.createWriteStream 的返回值)。你之前把返回流的函数直接赋值给 stream,Morgan 会将这个函数当作流对象尝试调用 write(),而函数本身没有该方法,因此触发 TypeError。

对比 skip 选项:skip 本身就是为接收函数设计的(Morgan 会在请求处理时自动调用该函数并传入 req、res 参数),所以你在 skip 里能正常获取流是因为函数被正确执行了,但 stream 不支持这种用法。

正确实现方式

需要将 Morgan 包装成自定义中间件,在中间件内部获取 app 配置的流,再初始化 Morgan 实例并执行。

步骤1:app.js 中配置日志流

如果已经提前创建好写入流,直接配置到 app 中:

const fs = require('fs');
const express = require('express');
const app = express();

// 创建日志写入流(追加模式)
const logStream = fs.createWriteStream('./access.log', { flags: 'a' });
// 将流配置到 app 中
app.set('logStream', logStream);

// 引入自定义日志中间件
const customLogger = require('./middleware/customLogger');
app.use(customLogger);

步骤2:编写自定义日志中间件(middleware/customLogger.js)

const morgan = require('morgan');

// 自定义日志格式
const customLogFormat = ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';

module.exports = (req, res, next) => {
  // 从 app 配置中获取日志流
  const logStream = req.app.get('logStream');

  // 初始化 Morgan 实例,传入自定义格式和流
  const logger = morgan(customLogFormat, {
    stream: logStream,
    // 如需跳过某些请求,可添加 skip 逻辑
    // skip: (req, res) => res.statusCode < 400
  });

  // 执行 Morgan 中间件
  logger(req, res, next);
};

可选:若配置的是日志文件名而非流

如果 app 中配置的是日志文件路径而非已创建的流,可在中间件中创建流并缓存,避免重复打开文件句柄:

const morgan = require('morgan');
const fs = require('fs');
const path = require('path');

// 缓存流对象,避免每次请求重复创建
let cachedLogStream = null;
const customLogFormat = ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';

module.exports = (req, res, next) => {
  if (!cachedLogStream) {
    const logFileName = req.app.get('logFileName');
    cachedLogStream = fs.createWriteStream(path.resolve(logFileName), { flags: 'a' });
  }

  const logger = morgan(customLogFormat, { stream: cachedLogStream });
  logger(req, res, next);
};

内容的提问来源于stack exchange,提问作者Alex Marienko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:42:42