Onde está o corpo em uma resposta http.get do nodejs?


187

Estou lendo os documentos em http://nodejs.org/docs/v0.4.0/api/http.html#http.request , mas por algum motivo, não consigo encontrar o atributo body / data no objeto de resposta retornado e finalizado.

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

> res.finished
true

> res._hasBody
true

Está concluído (http.get faz isso por você), portanto, ele deve ter algum tipo de conteúdo. Mas não há corpo, nem dados, e eu não consigo ler. Onde o corpo está escondido?


7
Como nenhuma das respostas mencionar como você saberá quando os dataeventos são feitas .. ter seu resouvir "end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

Respostas:


172

Os documentos http.request contêm exemplo de como receber o corpo da resposta por meio do dataevento de manipulação :

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 faz o mesmo que http.request, exceto que ele chama req.end()automaticamente.

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
Por alguma razão, eu tive que adicionar res.setEncoding('utf8');ao exemplo http.get. Caso contrário, não obtive HTML na chunkvariável.
SSH This

1
@SSHIsso é porque eram objetos de buffer que contêm dados brutos. Se você quisesse strings deles, também poderia usar chunk.toString (), opcionalmente passando toString e codificação. Dito isto, setEncoding é provavelmente mais eficiente.
Skeggse

14
O evento "data" pode ser chamado várias vezes e você obterá o conteúdo, peça por peça. O exemplo não mostra como colá-los juntos.
Andrej

4
@tfmontague. Acordado! Surpreendente ... tantos votos positivos por uma resposta que é falha no seu próprio fundamento.
Sunny

@tfmontague: a solicitação dePOST requests typically use a response body, not GET. postagem tem um corpo e a solicitação GET não, mas uma resposta GET pode ter um corpo.
Cyrbil # 5/15

135

Também quero acrescentar que o http.ClientResponseretornado por http.get()tem um endevento, então aqui está outra maneira de receber a resposta do corpo:

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
Obrigado por isso! O evento 'final' foi crucial para mim, pois tive que processar o corpo da resposta como um todo, e não em pedaços.
precisa

http.ClientResponsenão é retornado por http.get() http.ClientRequestis, de acordo com a documentação atual e a documentação vinculada pelo pôster original.
Vince

54

Edit: respondendo a si mesmo 6 anos depois

A palavra - chave wait é a melhor maneira de obter uma resposta de uma solicitação HTTP, evitando retornos de chamada e.then()

Você também precisará usar um cliente HTTP que retorne promessas. http.get()ainda retorna um objeto Request, para que não funcione. Você poderia usar fetch, mas superagenté um cliente HTTP maduro, que possui padrões mais razoáveis, incluindo codificação de cadeia de consulta mais simples, usando corretamente tipos MIME, JSON por padrão e outros recursos comuns do cliente HTTP. awaitesperará até que a Promessa tenha um valor - nesse caso, uma resposta HTTP!

const superagent = require('superagent');

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

Usando aguardar, o controle simplesmente passa para a próxima linha quando a promessa retornada por superagent.get()tiver um valor.


3
Isso não responde à sua pergunta original. No seu código de exemplo, resé definido como o valor de retorno de superagent.get(), não http.get(). http.get()retorna um http.IncomingMessageque não possui uma textpropriedade. Não é o objeto de resposta, é o objeto de solicitação.
Vince

Bom ponto Vince, eu vou editar a resposta para torná-la mais limpa. Estou usando um cliente HTTP que suporta Promises.
Mikemaccana #

12

O dataevento é disparado várias vezes com 'pedaços' do corpo à medida que são baixados e um endevento quando todos os pedaços foram baixados.

Com o Nó suportando Promises agora, criei um wrapper simples para retornar os pedaços concatenados por meio de um 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);
  });
};

Você pode chamá-lo de uma função assíncrona com:

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

11

Se você deseja usar .get, pode fazê-lo assim

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

});

2
Os outros exemplos me deram o que pareciam valores hexadecimais quando eu não incluí texto com a resposta em bloco. A definição da codificação exibiu o documento JSON que eu estava procurando. Obrigado!
precisa

@CollinMcGuire é porque eram objetos de buffer que contêm dados brutos. Se você quisesse strings deles, também poderia usar chunk.toString(), opcionalmente passando toStringe codificando. Dito isto, setEncodingé provavelmente mais eficiente.
Skeggse

6

Você precisa adicionar um ouvinte à solicitação porque o node.js funciona de forma assíncrona assim:

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

2

O módulo de agulha também é bom, aqui está um exemplo que usa o needlemódulo

var needle = require('needle');

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

0

Uma porção de café aqui:

# 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)

E compilado

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

Você não pode obter o corpo da resposta a partir do valor de retorno de http.get().

http.get()não retorna um objeto de resposta. Retorna o objeto de solicitação ( http.clientRequest). Portanto, não há como obter o corpo da resposta a partir do valor de retorno de http.get().

Sei que é uma pergunta antiga, mas ler a documentação à qual você vinculou mostra que esse era o caso mesmo quando você a postou.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.