【发布时间】:2020-06-21 22:59:02
【问题描述】:
我正在使用 typescript 在 Node 上开发 MITM 代理。我正在尝试解码使用 gzip 编码的响应。我不想删除 accept-encoding 标题,正如我在 SO 上的一些答案中看到的那样。我想使用zlib 来解码响应正文,但是由于某种原因,当我尝试加载使用 gzip 的页面(例如 github.com)时,该页面无法加载(图像、颜色、文本等)。 )。我的解压缩不起作用,我不知道为什么。我用来解压响应正文的代码如下:
注意:serverResponse 是我(作为代理)连接到的服务器(例如 github.com)的响应,proxyResponse 是我(代理)对启动客户端的响应请求
protected async receiveResponse(serverResponse: http.IncomingMessage, proxyResponse: http.ServerResponse) {
const contentEncoding = serverResponse.headers["content-encoding"]
let responseContent: http.IncomingMessage | zlib.Gunzip = serverResponse
if (contentEncoding && contentEncoding.toLowerCase().includes("gzip")) {
responseContent = zlib.createGunzip()
serverResponse.pipe(responseContent)
delete serverResponse.headers["content-encoding"]
}
let responseBody: Buffer
try {
responseBody = await this.collectMessageBody(responseContent)
} catch (error) {
console.log(error)
return
}
proxyResponse.writeHead(serverResponse.statusCode!, serverResponse.headers)
proxyResponse.write(responseBody)
proxyResponse.end()
}
private collectMessageBody(stream: http.IncomingMessage | zlib.Gunzip): Promise<Buffer> {
return new Promise<Buffer>((resolve, reject) => {
let bodyBuffers: Buffer[] = []
stream.on('data', chunk => bodyBuffers.push(chunk))
stream.on('end', () => resolve(Buffer.concat(bodyBuffers)))
stream.on('error', error => reject(error))
})
}
它遵循与 SO 上大多数答案相同的策略,但我不知道为什么我的不起作用。
OBS:这是一个开源项目,所以可以在这里找到整个文件:https://github.com/olmps/web-sniffer/blob/master/src/server.ts
我已经简化了逻辑,删除了在此处发布的不必要的内容。
例如,当加载使用gzip 压缩其内容的github.com 时,代理开启时我得到以下结果:
【问题讨论】:
-
看起来样式表等资产没有被加载。
-
是的!我不知道为什么。当我在将请求发送到 Github 之前删除标头
accept-encoding时,它工作正常,因为显然 Github 没有压缩响应。但是当我不删除这个标头并尝试在本地解压响应时,就是这样的结果。我认为这是我不知道的事情,或者是我没有看到的非常愚蠢的事情。 -
通过快速阅读代码,当您使用 gzip 发送接受编码时,为什么还要使用 zlib.creategunzip() 再次对其进行编码?要么按原样传递响应,要么在重新编码之前对其进行解码?当您不发送 accept-encoding 标头时,您会得到一个原始响应,您可以正确编码。
-
@suv “使用 zlib.creategunzip() 再次编码”是什么意思?我正在使用
Gunzip来解码来自 Github 服务器的响应,而不是对其进行编码 -
啊。这是一个误导性的函数名称。我刚刚阅读了文档,您是正确的。 creategunzip 解码 gzip 流。您是否尝试过控制台打印响应并查看那里发生了什么?我可以想到另一个原因,为什么会发生这种情况,console.log 应该很清楚。