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

如何在Fastify中记录响应体?响应对象未暴露响应体

如何在Fastify中记录响应体

确实,Fastify默认不会把响应体暴露给日志序列化器里的res对象——因为响应是流式传输的,为了性能考虑,框架不会自动缓存整个响应体。不过我们可以通过Fastify的钩子机制来实现这个需求,下面是两种可行的方案:

方案一:使用onSend钩子捕获响应体

onSend钩子会在响应即将发送给客户端前触发,此时我们可以获取到响应体的payload,并将其附加到Node.js原生的res对象上,这样日志序列化器就能访问到它了。

const fastify = require('fastify')({
  logger: {
    serializers: {
      res(res) {
        return {
          statusCode: res.statusCode,
          body: res.body // 现在可以拿到响应体了
        };
      }
    }
  }
});

// 添加onSend钩子来捕获并存储响应体
fastify.addHook('onSend', async (request, reply, payload) => {
  // payload可能是Buffer或字符串,转成字符串方便日志记录
  if (payload) {
    reply.res.body = typeof payload === 'string' ? payload : payload.toString();
  }
  // 必须返回payload,否则客户端会收不到响应
  return payload;
});

// 测试路由
fastify.get('/', async (request, reply) => {
  return { message: 'Hello Fastify!' };
});

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
});

注意事项

  • 这种方式会将整个响应体加载到内存中,如果你的服务处理大文件或大响应(比如超过100MB),可能会导致内存占用过高,建议只在开发环境使用,或者添加响应体大小过滤逻辑。
  • 如果响应是流式的(比如reply.send(fs.createReadStream('large-file.txt'))),payload会是null,这种场景下需要额外监听流的data事件来收集内容,但同样要注意内存开销问题。

方案二:在业务逻辑中主动记录响应体

如果你的响应都是通过reply.send()发送的JSON对象或简单字符串,可以在发送前直接将响应体传递给日志,这种方式更轻量化,不需要钩子:

const fastify = require('fastify')({ logger: true });

fastify.get('/', async (request, reply) => {
  const responseBody = { message: 'Hello Fastify!' };
  // 主动记录响应体
  request.log.info({ responseBody }, 'Sending response');
  return responseBody;
});

这种方式适合响应体较小且可控的场景,不会有额外的内存开销。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:14:53