Где находится тело в ответе http.get узлаjs?

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 сделает это за вас), поэтому он должен иметь какой-то контент. Но там нет тела, нет данных, и я не могу читать с него. Где прячется тело?

mikemaccana
источник
7
Поскольку ни в одном из ответов не упоминается, как вы узнаете, когда dataсобытия будут выполнены ... resпрослушайте их "end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

Ответы:

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);
});
yojimbo87
источник
15
По какой-то причине мне пришлось добавить res.setEncoding('utf8');в пример http.get. В противном случае я не получил HTML в chunkпеременной.
SSH это
1
@SSH Это потому, что они были объектами Buffer, содержащими необработанные данные. Если вам нужны строки из них, вы также можете использовать chunk.toString (), опционально передавая toString и кодировку. Тем не менее, setEncoding, вероятно, более эффективен.
Skeggse
14
Событие «data» может быть вызвано несколько раз, и вы получите контент по частям. Пример не показывает, как их склеить.
Андрей
4
@tfmontague. Согласовано! Удивительно ... так много голосов за ответ, который ошибочен в самом его основании.
Солнечно
@tfmontague: у POST requests typically use a response body, not GET.пост- запроса есть тело, а у запроса GET нет, но у ответа GET может быть тело.
Cyrbil
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-клиент, который возвращает Promises. http.get()по-прежнему возвращает объект запроса, так что это не будет работать. Вы можете использовать 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)
})();

Используя await, управление просто переходит на следующую строку, когда возвращаемое обещание superagent.get()имеет значение.

mikemaccana
источник
3
Это не отвечает на ваш первоначальный вопрос. В вашем примере кода resустановлено возвращаемое значение superagent.get(), а не http.get(). http.get()возвращает http.IncomingMessage, у которого нет textсвойства. Это не объект ответа, это объект запроса.
Винс
Хороший вопрос, Винс, я отредактирую ответ, чтобы сделать его более понятным. Я использую HTTP-клиент, который поддерживает Promises.
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');
nkron
источник
11

Если вы хотите использовать .get, вы можете сделать это так

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

});
user969714
источник
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);
 });
});
Skomski
источник
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
    }));
  });
});
18augst
источник
0

Вы не можете получить тело ответа из возвращаемого значения http.get().

http.get()не возвращает объект ответа. Возвращает объект запроса ( http.clientRequest). Таким образом, нет никакого способа получить тело ответа из возвращаемого значения http.get().

Я знаю, что это старый вопрос, но чтение документации, на которую вы ссылались, показывает, что это имело место даже тогда, когда вы ее опубликовали.

Vince
источник