解码 Node.JS 中间人代理上的 GZIP 响应

Decode GZIP response on Node.JS Man In the Middle Proxy

我正在使用打字稿在 Node 上开发 MITM 代理。我正在尝试解码使用 gzip 编码的响应。我不想只删除 accept-encoding header 正如我在 SO 上的一些答案中看到的那样。我想使用 zlib 解码响应 body,但由于某种原因,当我尝试加载使用 gzip 的页面(例如 github.com)时,页面未加载(图片、颜色、文本等)。我的解压缩不起作用,我不知道为什么。我用来解压缩响应 body 的代码如下:

注意: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:这是一个 open-source 项目,因此可以在此处找到整个文件:https://github.com/olmps/web-sniffer/blob/master/src/server.ts

我在此处将删除不必要内容的逻辑简化为 post。

例如,当加载使用 gzip 压缩其内容的 github.com 时,代理打开时我得到以下结果:

您也可以尝试处理 content-length header。

如果content-encodinggzip你可以尝试用未压缩的长度body改变content-lengthheader的值,不仅解压缩 body.

希望对您有所帮助。