【问题标题】:Incorrect Header Check when using zlib in node.js在 node.js 中使用 zlib 时不正确的标头检查
【发布时间】:2013-10-26 15:51:56
【问题描述】:

我正在尝试发送一个简单的 HTTP POST 请求,检索响应正文。以下是我的代码。我得到了

错误:标头检查不正确

在“zlib.gunzip”方法中。我是 node.js 的新手,感谢任何帮助。

;

    fireRequest: function() {

    var rBody = '';
    var resBody = '';
    var contentLength;

    var options = {
        'encoding' : 'utf-8'
    };

    rBody = fSystem.readFileSync('resources/im.json', options);

    console.log('Loaded data from im.json ' + rBody);

    contentLength = Buffer.byteLength(rBody, 'utf-8');

    console.log('Byte length of the request body ' + contentLength);

    var httpOptions = {
        hostname : 'abc.com',
        path : '/path',
        method : 'POST',
        headers : {
            'Authorization' : 'Basic VHJhZasfasNWEWFScsdfsNCdXllcjE6dHJhZGVjYXJk',
            'Content-Type' : 'application/json; charset=UTF=8',
            // 'Accept' : '*/*',
            'Accept-Encoding' : 'gzip,deflate,sdch',
            'Content-Length' : contentLength
        }
    };

    var postRequest = http.request(httpOptions, function(response) {

        var chunks = '';
        console.log('Response received');
        console.log('STATUS: ' + response.statusCode);
        console.log('HEADERS: ' + JSON.stringify(response.headers));
        // response.setEncoding('utf8');
        response.setEncoding(null);
        response.on('data', function(res) {
            chunks += res;
        });

        response.on('end', function() {
            var encoding = response.headers['content-encoding'];
            if (encoding == 'gzip') {

                zlib.gunzip(chunks, function(err, decoded) {

                    if (err)
                        throw err;

                    console.log('Decoded data: ' + decoded);
                });
            }
        });

    });

    postRequest.on('error', function(e) {
        console.log('Error occured' + e);
    });

    postRequest.write(rBody);
    postRequest.end();

}

【问题讨论】:

  • 你能发布你的堆栈跟踪吗?
  • 一个小提示:输入代码时,使用空格而不是制表符。格式化更容易。
  • 我使用的是 zlib.unzip 而不是 zlib.gunzip

标签: node.js zlib


【解决方案1】:

response.on('data', ...) 可以接受 Buffer,而不仅仅是纯字符串。连接时,您将错误地转换为字符串,然后无法进行压缩。你有两个选择:

1) 收集数组中的所有缓冲区,并在end 事件中使用Buffer.concat() 将它们连接起来。然后在结果上调用 gunzip。

2) 使用.pipe() 并将响应通过管道传输到 gunzip 对象,如果您希望将结果存储在内存中,则将其输出传输到文件流或字符串/缓冲区字符串。

此处讨论了选项 (1) 和 (2):http://nickfishman.com/post/49533681471/nodejs-http-requests-with-gzip-deflate-compression

【讨论】:

    【解决方案2】:

    在我们的例子中,我们在标题中添加了'accept-encoding': 'gzip,deflate',代码开始工作(解决方案归功于 Arul Mani):

    var httpOptions = {
        hostname : 'abc.com',
        path : '/path',
        method : 'POST',
        headers : {
            ...
            'accept-encoding': 'gzip,deflate'
        }
    };
    

    【讨论】:

    • 我同意。通过在请求中添加这些自定义标头,允许浏览器自动解压缩 gzip 文件,无需使用 zlib 的 gunzipcreateGunzip 方法进行后提取解压缩
    【解决方案3】:

    我在尝试使用 fs.readdirSync 循环时遇到此错误,但有一个 .Dstore 文件,因此对其应用了解压缩功能。

    注意只传递.zip/gz

    import gunzip from 'gunzip-file';
    
    const unzipAll = async () => {
      try {
        const compFiles = fs.readdirSync('tmp')
        await Promise.all(compFiles.map( async file => {
          if(file.endsWith(".gz")){
            gunzip(`tmp/${file}`, `tmp/${file.slice(0, -3)}`)
          }
        }));
      }
      catch(err) {
        console.log(err)
      }
    }
    

    【讨论】:

      【解决方案4】:

      除了@Nitzan Shaked 的回答,这可能与 Node.js 版本有关。

      我所经历的是https.request(OP 使用http.request,但它的行为可能相同)已经在后台解压缩了数据,因此一旦将块累积到缓冲区中,剩下的就是就是调用buffer.toString()(以utf8为例)。我自己在这个other answer经历过,好像和Node.js版本有关。

      我将用一个live demo类似工作代码 来结束这个答案,这对于未来的读者可能会派上用场(它查询 StackExchange API,获取 gzip 压缩块,然后解压缩它):

      • 它包含一个适用于 14.16.0(当前 StackBlitz 版本)的代码 - 正如我所描述的,它已经在后台解压缩了数据 - 但不适用于 Node.js 15.13.0,
      • 它包含一个注释掉的代码,适用于 Node.js 15.13.0,后者不适用于 14.16.0。

      【讨论】:

        猜你喜欢
        • 2015-09-21
        • 2015-05-29
        • 2015-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-13
        相关资源
        最近更新 更多