如何在NodeJS中使用HTTP GET方法获取错误状态码?

53

好的,我一定是太笨了,因为我找不到在使用Node.JS http.gethttp.request 时如何获得错误状态码的任何信息。

我的代码:

var deferred = $q.defer();
var req = https.get(options, function(response) {
  var str = '';
  response.on('data', function(chunk) {
    str += chunk;
  });
  response.on('end', function() {
    console.log("[evfService] Got user info: " + str);
    deferred.resolve(str);
  });
});

req.on('error', function(e) {
  deferred.reject(e);
});
在 "req.on" 部分,我想要的是 HTTP 状态码(即 401、403 等),但我得到的是一个几乎没用的错误对象,它不能给我代码或任何响应对象的引用。
我尝试在函数(response)回调中拦截,但当出现404时,它从未被调用。
谢谢!

你尝试过 response.statusCode 吗? - radubogdan
3个回答

71
无论服务器响应状态码如何,您的回调都会被调用,因此在回调中,请检查response.statusCode。也就是说,在您正在处理的级别上,4xx状态代码不是错误;服务器已经响应,只是服务器响应说资源不可用(等等)。

这在文档中有所说明,但通常含糊不清。下面是他们给出的示例,并附有指向相关部分的注释:

var https = require('https');

https.get('https://encrypted.google.com/', function(res) {
  console.log("statusCode: ", res.statusCode); // <======= Here's the status code
  console.log("headers: ", res.headers);

  res.on('data', function(d) {
    process.stdout.write(d);
  });

}).on('error', function(e) {
  console.error(e);
});

如果你尝试使用未知资源,你会看到statusCode: 404

因此,对于你正在做的事情,你可能需要像这样的东西:

var deferred = $q.defer();

var req = https.get(options, function (response) {
    var str = "";

    if (response.statusCode < 200 || response.statusCode > 299) { // (I don"t know if the 3xx responses come here, if so you"ll want to handle them appropriately
        response.on("data", function() { } ); // ¹
        deferred.reject(/*...with appropriate information, including statusCode if you like...*/);
    }
    else {
        response.on("data", function (chunk) {
            str += chunk;
        });
        response.on("end", function () {
            console.log("[evfService] Got user info: " + str);
            deferred.resolve(str);
        });
    }
});

req.on("error", function (e) {
    deferred.reject(/*...with appropriate information, but status code is irrelevant [there isn"t one]...*/);
});

¹ 针对处理非"OK"状态码的分支,空的data事件处理程序存在于文档中的以下备注原因:

...如果添加了一个'response'事件处理程序,则必须消耗来自响应对象的数据,可以通过在每次出现'readable'事件时调用response.read()、添加'data'事件处理程序或调用.resume()方法来完成。在数据被消耗之前,'end'事件不会触发。此外,在读取数据之前,它将占用内存,最终可能导致"进程内存不足"错误。

由于我们正在向https.get传递一个函数,因此我们正在挂接'response'事件,这表明我们需要执行其中一项操作(在本例中,我添加了一个无作用的data事件处理程序)。感谢Nicolas2bert指出这一点!


你好,有没有关于如何在响应回调内执行重试 (如果状态码不等于200) 的想法? - user1893702
1
@sudosoul:我会把整个东西放在一个函数中,如果你想重试,那么该函数将从响应回调中调用自身。 - T.J. Crowder
1
在你的启动代码条件中,不要忘记使用res.resume()消耗响应数据以释放内存。来自:https://nodejs.org/api/http.html#http_class_http_clientrequest:“此外,在数据被读取之前,它将消耗内存,最终可能导致“内存不足”错误。” - Nicolas2bert
@Nicolas2bert - 哇,这是一个非常出人意料的要求。但我和你一样阅读了文档,所以...谢谢!我已经更新了答案。 - T.J. Crowder

15

node.js 不认为错误代码 400 的响应是错误。

在这个中尝试使用 response.statusCode

request.on('response', function (response) {}); 

8
这里是一个非常小的例子,展示如何获取错误代码。只需将https更改为http并制造一个错误即可:
var https = require('https')
var username = "monajalal3"
var request = https.get("https://teamtreehouse.com/" + username +".json", function (response) {
    console.log(response.statusCode);
});

request.on("error", function (error) {
    console.error(error.status);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接