Nodejs 消耗来自外部 API 的压缩响应

Nodejs consume deflate response from external API

这应该是一个简单的问题,但为了我的生活,我无法让它工作,我正在使用这样的网络服务:

var XMLHttpRequest = require('XMLHttpRequest').XMLHttpRequest;
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://rest.gestionix.com/api/v2/products? 
branch_id=7471&filter=0119080PMDSV&results_per_page=5&page=1&fields=id');
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.onreadystatechange = function(event) {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            console.log(xhr.responseText);
        }
    }
    console.log(xhr.getAllResponseHeaders());
};
xhr.setRequestHeader('Accept','application/json');
xhr.setRequestHeader('Accept-Encoding','decode');
xhr.setRequestHeader('Content-Encoding','decode');
xhr.setRequestHeader('Encoding','decode');
xhr.setRequestHeader('apikey', '---'); <<< of course I'm using an apikey
xhr.send();

本apireturns本header:

cache-control: max-age=60
content-length: 22766
content-type: application/json
content-encoding: deflate
server: Microsoft-IIS/10.0
x-aspnet-version: 4.0.30319
x-powered-by: ASP.NET
date: Mon, 02 Jul 2018 16:31:32 GMT
connection: close

然而,内容只是一堆奇怪的字符:

��a��^G4Wk��wC������p��şG��?FZ}��Ϧ��Bo��W��i��gu��$H��^; ,Wf��촞��}��: ������P������e����yE��%6٬e1D��ml�7UO��DzK������m��}t��"���� �dS7�Q�>5�y֫� I��;E��PH��}��/��X����&����W{��)X��SP��v��[�� ����k��Wو����P{��W ��>Z����ə��R��׺4T��]X��m<��Ns'՟��������f��0X:V��W��C������ P��#d������T��gb��yI n��c-��+EP��#=|��V��f��9��Ղ��h��:����r����yF��б����Se��!σr��L/E����d7��7��\��+ɠ��N��3�� a��{��-��)��~����.���� ��\s��^5����q .t�� ����������&��Ǧ��oP����- ��;( ��4����o6��

我尝试过不同的编码,但结果总是一样的,我一直在寻找有关如何解压缩它的文档,但我没有找到任何有效的方法,如果有人有 link 可以指出我在正确的方向我真的很感激。

服务器可能会忽略您对非未压缩数据的请求并向您发送压缩数据。它使用 content-encoding header 中所述的放气算法。你可以自己放气。 nodejs 有本地库 zlib 可以压缩数据。

var zlib = require("zlib")

// in response callback
zlib.deflate(xhr.response, function (error, result) {
    console.log(result.toString());
});

在我的例子中,我无法读取数据 XMLHttpRequest,因为该库无法处理二进制数据,而是将所有数据作为字符串处理。这是个问题,因为转换某些二进制字符(如 0)会破坏数据。我必须改用 request 库。我用来测试的代码是

var zlib = require("zlib")
var request = require("request")

request('http://something...', { encoding: null }, function (error, response, body) {
    zlib.deflate(xhr.response, function (error, result) {
        console.log(result.toString());
    });
});

好吧,我不想为了以防其他人需要它而让这个无人回答。 首先你需要这个样板代码

/** 锅炉板代码 * 处理响应。 * @param {Object} headers * 响应 header name-value 对的散列。 * @param {字符串} body * 未压缩的响应 body。 */ 函数 processResponse(headers, body) {

  **do something with the response**

    } else {
        console.log("Response is empty.");
    }
}

/**
 * Manage an error response.
 *
 * @param {Error} error
 *   An error instance.
 */
function handleError(error) {
    // Error handling code goes here.
    console.log("Error Found: " + error);

}

/**
 * Obtain the encoding for the content given the headers.
 *
 * @param {Object} headers
 *   A hash of response header name-value pairs.
 * @return {String}
 *   The encoding if specified, or 'utf-8'.
 */
console.log('------------ Getting Charset  ------------');
function obtainCharset(headers) {
    // Find the charset, if specified.
    var charset;
    var contentType = headers['content-type'] || '';
    var matches = contentType.match(/charset=([^;,\r\n]+)/i);
    if (matches && matches[1]) {
        charset = matches[1];
    }
    console.log('------------ Charset is ' + charset + ' (utf-8 if null)  ------------');
    return charset || 'utf-8';
}

此函数将负责处理,它们位于顶部。

然后你需要 运行 你的请求,在我的例子中,我使用的是普通的 var request = require('request-promise');

var req = 请求({ url:你的url在这里*, headers:**你的header这里 },函数等待(错误,响应){ 如果(错误){ return handleError(错误); }否则如果(response.statusCode>=400){ return handleError(新错误(util.format( 'Response with status code %s.'、response.statusCode ))); } console.log('------------解压响应------------'); zlib.inflateRaw(Buffer.concat(缓冲区), 函数 (gunzipError, body缓冲区) { 如果(gunzipError){ return handleError(gunzipError); } var charset = obtainCharset(response.headers); processResponse(response.headers, bodyBuffer.toString(字符集)); }); }); req.on('data', 函数 (buf) { 缓冲区[buffers.length] = buf; });