【问题标题】:Decode GZIP response on Node.JS Man In the Middle Proxy在中间代理中的 Node.JS Man 上解码 GZIP 响应
【发布时间】: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 应该很清楚。

标签: node.js zlib


【解决方案1】:

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

如果content-encodinggzip,你可以尝试将content-length 标头的值更改为未压缩正文的长度,而不仅仅是解压缩正文。

希望这会有所帮助。

【讨论】:

  • 切入正题。调整content-length 成功了!所以说我需要等待 6 个小时才能给你赏金,所以我稍后会回来做。感谢您的解决方案,我真的很惊讶 SO 上的相关答案都没有提到这个细节。
  • 很高兴您解决了问题。 NP 赏金...我可以等 ;)
猜你喜欢
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
相关资源
最近更新 更多