NodeJS,如何调试 GET 请求上 TLSSocket.socketOnData 的解析错误?

Tim*_*imM 5 debugging https json get node.js

我对 NodeJS 还很陌生,一直在 AWS Lambda 上尝试编写一个简单的 Alexa 服务来告诉我家里的温度。我遇到了一个让我陷入困境的问题 - 当我尝试与 https 端点通信以查询家庭自动化恒温器的一些数据时 - 我的 Node 应用程序因错误而终止:

Error: Parse Error
    at TLSSocket.socketOnData (_http_client.js:362:20)
    at emitOne (events.js:96:13)
    at TLSSocket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at TLSSocket.Readable.push (_stream_readable.js:134:10)
    at TLSWrap.onread (net.js:551:20)
Run Code Online (Sandbox Code Playgroud)

这是一个相当简单的通过 https 的 GET 请求,端点的提供者使用 Python 没有任何问题。我尝试将代码移至笔记本电脑上的本地节点设置,但仍然遇到问题(所以不是 AWS)。由于它是 https 和我的控制之外的服务,我无法轻松地对流量进行 Wireshark 来发现响应是否以某种微妙的方式损坏 - 但是我尝试使用 Browsify 将代码转换为在 Web 浏览器中运行(我可以在其中使用wireshark),当然它然后就可以工作了,我看不出我得到的 json 响应有什么奇怪的。

我尝试使用响应模块而不是节点中的核心 https 库,但我仍然遇到相同的潜在错误。

我对我能做什么感到困惑 - 并且不知道如何调试它。我觉得这要么是格式问题,要么是时间问题——但我不知道如何解决这个问题。有人有想法吗?

我的代码如下所示:

var https = require('https');
var crypto = require('crypto');

function executeHttpRequest(path, data, method, username, password) {

    var encodedLogin = getLoginString(username,password);
    var stringData = JSON.stringify(data);

    var requestOptions = {
        host: 'hub-server.domain.co.uk',
        port: 443,
        path: path,
        method: 'GET',
        headers: {
            'Cache-Control': 'no-cache',
            'Accept': 'application/json, text/plain, */*',
            'Authorization': 'Basic ' + encodedLogin
        }};

    var request = https.request(requestOptions, function(response) {

        var body='';
        response.setEncoding('utf8');

        response.on('error', function(err){
            console.log(method + " error: \n", err.stack);
        }); 

        response.on('data', function (chunk) {
            console.log("read data: " + chunk);
            body += chunk 
        });

        response.on('end', function () {
            console.log("end data");
        });

    });

    request.on('error', function(err) {
        console.log('request error: \n' + err.stack);
    });

    console.log("sending request:" + JSON.stringify(requestOptions));
    console.log("with data: " + stringData)

    request.write(stringData);  
    request.end();
    console.log("closed request")
}
Run Code Online (Sandbox Code Playgroud)

当在节点中运行时,我得到以下输出

sending request:{"host":"hub-server.domain.co.uk","port":443,"path":"/zone/1","method":"GET","headers":{"Cache-Control":"no-cache","Accept":"application/json, text/plain, */*","Authorization":"Basic bWFjdGEyOmY0OWZiODJlYTcyNWYzNDgwMTViODVjZTNlZmIyYmY1MWE4ZmI3YWUxMzJmZTRkNDk4OGEc"}}
closed request
request error: 
Error: Parse Error
    at TLSSocket.socketOnData (_http_client.js:362:20)
    at emitOne (events.js:96:13)
    at TLSSocket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at TLSSocket.Readable.push (_stream_readable.js:134:10)
    at TLSWrap.onread (net.js:551:20)
Run Code Online (Sandbox Code Playgroud)

我使用类似的 PUT 命令得到了同样的错误。有趣的是,如果我在使用 PUT 时遗漏了一个参数,并且服务器回复 JSON 错误,则上面的代码可以工作并显示记录该错误的 JSON。同样,如果我使用无效的 URL 或错误的 AUTH,我会正确获得适当的状态代码。

如果我尝试点击https://www.google.com并进行搜索,我的代码似乎也可以工作。

显然有些事情发生了 - 但我如何纠正我的节点代码,或者向端点的作者提供建议?

Tim*_*imM 4

响应同时具有Content-LengthTransfer-encoding: chunked标头(这是一个错误)

使用调试器,我发现http解析器实际上显示了一个错误代码:HPE_UNEXPECTED_CONTENT_LENGTH - 在谷歌上搜索更多有关此内容的信息,我发现其他几个人也经历过这种情况(有趣,都与家庭自动化有关) - 这些线程的结论是由于安全问题,Node 的更高版本对 HTTP 规范变得更加严格。有了这个错误代码,搜索显示了两个与我类似的情况(例如http.get Parse Error,代码:'HPE_UNEXPECTED_CONTENT_LENGTH'),结论是有一个同时包含内容长度和传输编码的响应:分块标头一起存在(这是一个错误)。我的响应没有此错误,但是我想知道声明的内容长度是否错误,或者响应中的某处是否存在虚假的 cr/lf。我希望我能够在 IntelliJ 中调试这个假设

IntelliJ 调试节点应用程序