Де знаходиться тіло у відповіді http.get на nodejs?


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

Відповіді:


172

Документи http.request містять приклад, як отримати тіло відповіді через 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. Інакше я не отримав HTML у chunkзмінній.
SSH Це

1
@SSHTЦе тому, що вони були об'єктами буфера, що містять необроблені дані. Якщо вам потрібні рядки з них, ви також можете використовувати chunk.toString (), необов'язково передаючи toString та кодування. Однак, SetEncoding, ймовірно, є більш ефективним.
skeggse

14
Подія "дані" може бути викликана кілька разів, і ви отримаєте вміст детально. Приклад не показує, як склеїти їх між собою.
Андрій

4
@tfmontague. Домовились! Дивно ... стільки нагород за відповідь, яка є недоліком у самій її основі.
Сонячно

@tfmontague: POST requests typically use a response body, not GET.Повідомлення запиту є тіло і GET запит не робить, а GET відповідь може мати тіло.
Кірбіл

135

Я також хочу додати, що http.ClientResponseповернений користувач 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
Дякую за це! "Кінцева" подія була для мене вирішальною, оскільки мені довелося обробляти орган реагування в цілому, а не на шматки.
Даніель Грущик

http.ClientResponseне повертається http.get() http.ClientRequestяк згідно з поточною документацією, так і з документацією, пов'язаною з оригінальним плакатом.
Вінс

54

Редагувати: відповісти на себе через 6 років

Await ключовим словом є найкращим способом , щоб отримати відповідь від запиту HTTP, уникаючи зворотні виклики і.then()

Вам також потрібно буде використовувати клієнт HTTP, який повертає Обіцянки. http.get()як і раніше повертає об’єкт Запит, так що він не працює. Ви можете використовувати fetch, але superagentце зрілий клієнт HTTP, який має більш розумні налаштування за замовчуванням, включаючи просте кодування рядків запитів, правильне використання типів mime, JSON за замовчуванням та інші поширені функції клієнта HTTP. awaitбуде чекати, поки Обіця не отримає значення - у цьому випадку відповідь HTTP!

const superagent = require('superagent');

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

Використовуючи функцію wait, контроль просто переходить на наступний рядок, як тільки повернення обіцянки superagent.get()має значення.


3
Це не відповідає на ваше первісне запитання. У вашому прикладі коду resвстановлено значення повернення superagent.get(), а не http.get(). http.get()повертає http.IncomingMessageте, що не має textвластивості. Це не об’єкт відповіді, це об’єкт запиту.
Вінс

Добрий момент, Вінс Я відредагую відповідь, щоб зробити її більш чистою, я використовую HTTP-клієнт, який підтримує Обіцянки.
mikemaccana

12

dataПодія викликається кілька разів з «шматками» тел , як вони завантажуються і в endразі , коли всі шматки були завантажені.

Завдяки тому, що Вузол підтримує Обіцяння , я створив просту обгортку, щоб повернути об'єднані шматки через Обіцяння:

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. Дякую!
Колін Макгуайер

@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().

Я знаю, що це давнє запитання, але читання документації, з якою ви пов’язували, показує, що це було так, навіть коли ви його розміщували.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.