nodejs http.get响应中的主体在哪里?


187

我正在http://nodejs.org/docs/v0.4.0/api/http.html#http.request上阅读文档,但是由于某些原因,我似乎无法真正找到body / data属性在返回的完成响应对象上。

> var res = http.get({host:'www.somesite.com', path:'/'})

> res.finished
true

> res._hasBody
true

完成(http.get为您完成),因此它应该具有某种内容。但是没有主体,没有数据,我无法读取。身体藏在哪里?


7
由于没有一个答案何况你怎么知道什么时候该data事件被做..有你res"end"nodejs.org/docs/latest/api/http.html#event_end_
SooDesuNe

Answers:


172

http.request docs包含示例如何通过处理data事件接收响应的主体:

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/upload',
  method: 'POST'
};

var req = http.request(options, function(res) {
  console.log('STATUS: ' + res.statusCode);
  console.log('HEADERS: ' + JSON.stringify(res.headers));
  res.setEncoding('utf8');
  res.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
  });
});

req.on('error', function(e) {
  console.log('problem with request: ' + e.message);
});

// write data to request body
req.write('data\n');
req.write('data\n');
req.end();

http.get与http.request一样,只是req.end()自动调用。

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/index.html'
};

http.get(options, function(res) {
  console.log("Got response: " + res.statusCode);

  res.on("data", function(chunk) {
    console.log("BODY: " + chunk);
  });
}).on('error', function(e) {
  console.log("Got error: " + e.message);
});

15
由于某些原因,我不得不添加res.setEncoding('utf8');到http.get示例中。否则我没有在chunk变量中得到HTML 。
SSH

1
@SSH这是因为它们是包含原始数据的Buffer对象。如果您希望从中获取字符串,则还可以使用chunk.toString(),可以选择传递toString和编码。也就是说,setEncoding可能更有效。
skeggse

14
可能会多次调用“数据”事件,您将逐步获得内容。示例未显示如何将它们粘合在一起。
Andrej

4
@tfmontague。同意!令人惊讶的是……如此之多的评论​​都为根本上存在缺陷的答案。
2015年

@tfmontague: POST requests typically use a response body, not GET.发布请求有一个正文,而GET 请求没有一个正文,但是GET 响应可以有一个正文。
Cyrbil

135

我还想补充一点,http.ClientResponsereturn by http.get()具有一个end事件,因此这是我收到正文响应的另一种方式:

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/index.html'
};

http.get(options, function(res) {
  var body = '';
  res.on('data', function(chunk) {
    body += chunk;
  });
  res.on('end', function() {
    console.log(body);
  });
}).on('error', function(e) {
  console.log("Got error: " + e.message);
}); 

13
感谢那!“结束”事件对我来说至关重要,因为我必须处理整个响应主体,而不是分块处理。
Daniel Gruszczyk 2015年

http.ClientResponsehttp.get() http.ClientRequest根据当前文档以及原始张贴者链接的文档,is不是由is 返回。
文斯

54

编辑:6年后回复自我

的await关键字是获得从HTTP请求的响应的最佳方式,避免回调和.then()

您还需要使用返回Promises的HTTP客户端。 http.get()仍会返回一个Request对象,因此将无法正常工作。您可以使用fetch,但它superagent是一个成熟的HTTP客户端,它具有更合理的默认值,包括更简单的查询字符串编码,正确使用mime类型,默认情况下为JSON和其他常见的HTTP客户端功能。await将等待,直到Promise具有值-在这种情况下,将是HTTP响应!

const superagent = require('superagent');

(async function(){
  const response = await superagent.get('https://www.google.com')
  console.log(response.text)
})();

使用wait,一旦返回的promise 具有值,控制就简单地转到下一行superagent.get()


3
这不能回答您的原始问题。在您的示例代码中,res将设置为而superagent.get()不是的返回值http.get()http.get()返回http.IncomingMessage没有text属性的。它不是响应对象,而是请求对象。
文斯

好点,Vince我将编辑答案以使其更整洁。我使用的是支持Promises的HTTP客户端。
mikemaccana

12

下载该data事件时,会用其身体的“块”触发多次end所有块都已下载时。

有了Node 现在支持Promises的支持,我创建了一个简单的包装器,以通过Promise返回连接的块:

const httpGet = url => {
  return new Promise((resolve, reject) => {
    http.get(url, res => {
      res.setEncoding('utf8');
      let body = ''; 
      res.on('data', chunk => body += chunk);
      res.on('end', () => resolve(body));
    }).on('error', reject);
  });
};

您可以使用以下方法从异步函数中调用它:

const body = await httpGet('http://www.somesite.com');

11

如果您想使用.get,可以这样

http.get(url, function(res){
    res.setEncoding('utf8');
    res.on('data', function(chunk){
        console.log(chunk);
    });

});

2
当我没有在块响应中包含文本时,其他示例给了我十六进制值。设置编码将显示我正在寻找的JSON文档。谢谢!
Collin McGuire

@CollinMcGuire是因为它们是包含原始数据的Buffer对象。如果您需要字符串,也可以使用chunk.toString(),可以选择传递toString和编码。也就是说,这setEncoding可能会更有效率。
skeggse

6

您需要向请求添加侦听器,因为node.js像这样异步工作:

request.on('response', function (response) {
  response.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
 });
});

2

针模块也不错,这是一个使用needle模块的例子

var needle = require('needle');

needle.get('http://www.google.com', function(error, response) {
  if (!error && response.statusCode == 200)
    console.log(response.body);
});

0

这里有一部分咖啡:

# My little helper
read_buffer = (buffer, callback) ->
  data = ''
  buffer.on 'readable', -> data += buffer.read().toString()
  buffer.on 'end', -> callback data

# So request looks like
http.get 'http://i.want.some/stuff', (res) ->
  read_buffer res, (response) ->
    # Do some things with your response
    # but don't do that exactly :D
    eval(CoffeeScript.compile response, bare: true)

并编译

var read_buffer;

read_buffer = function(buffer, callback) {
  var data;
  data = '';
  buffer.on('readable', function() {
    return data += buffer.read().toString();
  });
  return buffer.on('end', function() {
    return callback(data);
  });
};

http.get('http://i.want.some/stuff', function(res) {
  return read_buffer(res, function(response) {
    return eval(CoffeeScript.compile(response, {
      bare: true
    }));
  });
});

0

您无法从返回值中获取响应的正文http.get()

http.get()不返回响应对象。它返回请求对象(http.clientRequest)。因此,没有任何方法可以从的返回值获取响应的主体http.get()

我知道这是一个老问题,但是阅读链接到的文档后,即使您发布了它,情况也是如此。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.