【问题标题】:Easy HTTP requests with gzip/deflate compression使用 gzip/deflate 压缩的简单 HTTP 请求
【发布时间】:2012-01-16 13:34:37
【问题描述】:

我正在尝试找出轻松发送 HTTP/HTTPS 请求以及处理 gzip/deflate 压缩响应和 cookie 的最佳方式。

我发现最好的是https://github.com/mikeal/request,它可以处理所有除了压缩。有没有什么模块或方法可以满足我的要求?

如果不是,我可以以某种方式将 request 和 zlib 结合起来吗?我尝试将zlib和http.ServerRequest结合起来,结果惨遭失败。

【问题讨论】:

标签: http node.js https gzip deflate


【解决方案1】:

对于最近遇到此问题的任何人,请求库现在支持开箱即用的 gzip 解压缩。使用如下:

request(
    { method: 'GET'
    , uri: 'http://www.google.com'
    , gzip: true
    }
  , function (error, response, body) {
      // body is the decompressed response body
      console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity'))
      console.log('the decoded data is: ' + body)
    }
  )

来自 github 自述文件https://github.com/request/request

gzip - 如果为 true,则添加 Accept-Encoding 标头以请求压缩 来自服务器的内容编码(如果不存在)和解码 响应中支持的内容编码。注:自动解码 对通过返回的body数据进行响应内容的 请求(都通过请求流和传递给回调 函数),但不在响应流上执行(可从 响应事件)这是未修改的 http.IncomingMessage 可能包含压缩数据的对象。请参见下面的示例。

【讨论】:

  • 这对于 2.53.0 版本不正确,请参阅我的回答。
  • 适用于我的 2.56.0
  • 我已经添加了来自 github 页面的解释。该示例直接取自文档,应该可以正常工作。确保您在回调(正文)中使用第三个参数,因为响应的其余部分可能已被压缩
  • @RyanKnell 你能这样修改吗? gist.github.com/niftylettuce/dffb449ab754e3de111788411c29f686 - 请注意,我添加了 encoding: null 以便我们可以在本地写入文件
  • 这在当前版本中不起作用,根据*.com/questions/50795520/…
【解决方案2】:

注意:从 2019 年开始,request 内置了 gzip 解压。您仍然可以使用以下方法手动解压请求。

您可以简单地将requestzlib 与流结合起来。

这是一个示例,假设您有一台服务器在端口 8000 上进行监听:

var request = require('request'), zlib = require('zlib');

var headers = {
    'Accept-Encoding': 'gzip'
};

request({url:'http://localhost:8000/', 'headers': headers})
    .pipe(zlib.createGunzip()) // unzip
    .pipe(process.stdout); // do whatever you want with the stream

【讨论】:

  • 有没有办法区分压缩、压缩或以其他方式压缩或未压缩的响应。因为网络服务器可能不会返回压缩响应并且不尊重标头。
  • @CMCDragonkai 我已经编辑了答案以使解码成为条件。
  • @RubenVerborgh 你指的是什么答案?
  • @CMCDragonkai jcreignou 的上述回答。好像我的编辑还没有完成。
  • zlib 库能否同时解码 gzipped 和 deflated 响应?
【解决方案3】:

这是一个压缩响应的工作示例

function gunzipJSON(response){

    var gunzip = zlib.createGunzip();
    var json = "";

    gunzip.on('data', function(data){
        json += data.toString();
    });

    gunzip.on('end', function(){
        parseJSON(json);
    });

    response.pipe(gunzip);
}

完整代码:https://gist.github.com/0xPr0xy/5002984

【讨论】:

    【解决方案4】:

    http://nodejs.org/docs/v0.6.0/api/zlib.html#examples查看示例

    zlib 现在内置于 node.js 中。

    【讨论】:

    • 嗯,这些例子不足以让我弄清楚如何在 Stack Exchange v2 API 上将 node.js 与 require 和 zlib 一起使用。
    【解决方案5】:

    查看 source code 内部 - 您必须在请求库本身上设置 gzip 参数才能使 gzip 工作。不确定这是否是故意的,但这是当前的实现。不需要额外的标题。

    var request = require('request');
    request.gzip = true;
    request({url: 'https://...'},  // use encoding:null for buffer instead of UTF8
        function(error, response, body) { ... }
    );
    

    【讨论】:

    • 这很奇怪 - 在 IDEA 中,选项的 gzip:true 并没有应用于 self,但是在不调试的情况下运行时,{gzip:true} 也可以。可能需要进一步调查。
    • 如何在express中使用它并检查是否应用了gzip或压缩!
    【解决方案6】:

    这里的所有答案都不起作用,我得到的是原始字节,gzip 标志也不起作用。事实证明,您需要将编码设置为 null 以防止请求将响应转换为 utf-8 编码,而是保留二进制响应。

    const request = require("request-promise-native");
    const zlib = require("zlib");
    
    const url = getURL("index.txt");
    const dataByteBuffer = await request(url, { encoding: null });
    const dataString = zlib.gunzipSync(response);
    

    【讨论】:

      最近更新 更多