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

如何在Fastify HTTP Proxy的OnResponse钩子中获取响应体?

解决Fastify HTTP Proxy中onResponse钩子获取响应体的问题

问题原因

res参数是Node.js原生的http.IncomingMessage流对象,它的响应体不会直接暴露为可直接读取的属性,必须手动读取流中的数据才能获取内容。

解决方案

方法1:用原生流API读取响应体

直接监听流的data和end事件收集响应体,处理完成后再将数据转发给客户端:

const fastifyProxyLib = require("@fastify/http-proxy");
const { PassThrough } = require('stream');

register(fastifyProxyLib, {
  ...proxyConfig,
  upstream,
  preHandler: async ({ url, body }) => {
    // 自定义请求处理逻辑
  },
  replyOptions: {
    onResponse: (request, reply, res) => {
      const responseChunks = [];
      // 收集响应体片段
      res.on('data', chunk => responseChunks.push(chunk));
      
      // 响应体收集完成
      res.on('end', () => {
        const bodyBuffer = Buffer.concat(responseChunks);
        // 转换为字符串查看内容(二进制数据可跳过此步)
        const bodyContent = bodyBuffer.toString('utf8');
        console.log('目标服务器响应体:', bodyContent);
        
        // 创建新流转发数据给客户端(原流已被消费,无法直接复用)
        const forwardStream = new PassThrough();
        forwardStream.end(bodyBuffer);
        // 保留原响应的状态码和头部信息
        reply.code(res.statusCode).headers(res.headers).send(forwardStream);
      });
      
      // 处理流读取错误
      res.on('error', err => {
        console.error('读取响应体失败:', err);
        reply.code(500).send('Proxy error');
      });
    },
  }, 
});

方法2:用concat-stream简化流处理

通过第三方库concat-stream简化流收集逻辑,先安装依赖:

npm install concat-stream

再修改代码:

const fastifyProxyLib = require("@fastify/http-proxy");
const concat = require('concat-stream');
const { PassThrough } = require('stream');

register(fastifyProxyLib, {
  ...proxyConfig,
  upstream,
  preHandler: async ({ url, body }) => {
    // 自定义请求处理逻辑
  },
  replyOptions: {
    onResponse: (request, reply, res) => {
      res.pipe(concat(bodyBuffer => {
        // 查看响应体内容
        const bodyContent = bodyBuffer.toString('utf8');
        console.log('目标服务器响应体:', bodyContent);
        
        // 转发数据给客户端
        const forwardStream = new PassThrough();
        forwardStream.end(bodyBuffer);
        reply.code(res.statusCode).headers(res.headers).send(forwardStream);
      }));
      
      res.on('error', err => {
        console.error('读取响应体失败:', err);
        reply.code(500).send('Proxy error');
      });
    },
  }, 
});

注意事项

  • 不能直接调用reply.send(res):原流被读取消费后无法再次发送给客户端,必须重新创建流或直接发送缓冲区数据。
  • 保留原响应的状态码和头部:避免客户端收到不符合预期的响应。
  • 二进制响应处理:如果响应是图片、文件等二进制数据,不要转换为字符串,直接处理Buffer即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:39:48