如何在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
相关产品推荐
相关产品推荐

