Dov'è body in una risposta http.get di nodejs?


187

Sto leggendo i documenti su http://nodejs.org/docs/v0.4.0/api/http.html#http.request , ma per qualche motivo, non riesco a trovare effettivamente l'attributo body / data sull'oggetto risposta restituito e finito.

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

> res.finished
true

> res._hasBody
true

È finito (http.get lo fa per te), quindi dovrebbe avere qualche tipo di contenuto. Ma non c'è nessun corpo, nessun dato, e non riesco a leggere da esso. Dove si nasconde il corpo?


7
Poiché nessuna delle risposte menziona il modo in cui saprai quando gli dataeventi sono stati completati ... resascolta "end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

Risposte:


172

La documentazione http.request contiene esempi su come ricevere il corpo della risposta attraverso la gestione datadell'evento:

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 fa la stessa cosa di http.request tranne che chiama 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
Per qualche motivo, ho dovuto aggiungere res.setEncoding('utf8');l'esempio http.get. Altrimenti non ho ricevuto HTML nella chunkvariabile.
SSH Questo

1
@SSH Questo perché erano oggetti Buffer contenenti dati non elaborati. Se volevi stringhe da loro, puoi anche usare chunk.toString (), opzionalmente passando a String e codifica. Detto questo, setEncoding è probabilmente più efficiente.
skeggse il

14
L'evento "data" potrebbe essere chiamato più volte e otterrai il contenuto pezzo per pezzo. L'esempio non mostra come incollarli insieme.
Andrej,

4
@tfmontague. Concordato! Sorprendente ... tanti voti positivi per una risposta che è difettosa alla sua base.
Sunny

@tfmontague: la richiestaPOST requests typically use a response body, not GET. post ha un corpo e la richiesta GET no, ma una risposta GET può avere un corpo.
Cyrbil,

135

Voglio anche aggiungere che il http.ClientResponsereso di http.get()ha un endevento, quindi ecco un altro modo in cui ricevo la risposta del 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
Grazie per quello! L'evento di "fine" è stato cruciale per me in quanto ho dovuto elaborare il corpo di risposta nel suo insieme, piuttosto che a pezzi.
Daniel Gruszczyk,

http.ClientResponsenon viene restituito da http.get() http.ClientRequestè, in base alla documentazione corrente e alla documentazione collegata al poster originale.
Vince il

54

Modifica: rispondendo a se stessi 6 anni dopo

La parola chiave wait è il modo migliore per ottenere una risposta da una richiesta HTTP, evitando callback e.then()

Dovrai anche utilizzare un client HTTP che restituisca Promesse. http.get()restituisce comunque un oggetto Request, quindi non funzionerà. È possibile utilizzare fetch, ma superagentè un client HTTP maturo che presenta impostazioni predefinite più ragionevoli tra cui la codifica più semplice della stringa di query, l'utilizzo corretto dei tipi mime, JSON per impostazione predefinita e altre funzionalità client HTTP comuni. awaitaspetterò fino a quando la Promessa avrà un valore - in questo caso, una risposta HTTP!

const superagent = require('superagent');

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

Usando wait, il controllo passa semplicemente alla riga successiva quando la promessa restituita superagent.get()ha un valore.


3
Questo non risponde alla tua domanda originale. Nel tuo codice di esempio, resè impostato sul valore restituito di superagent.get(), non http.get(). http.get()restituisce un http.IncomingMessageche non ha una textproprietà. Non è l'oggetto response, è l'oggetto richiesta.
Vince il

Buon punto Vince modificherò la risposta per renderlo più pulito sto usando un client HTTP che supporta Promises.
mikemaccana,

12

L' dataevento viene generato più volte con "blocchi" del corpo mentre vengono scaricati e unend evento quando tutti i blocchi sono stati scaricati.

Con Node che supporta Promises ora, ho creato un semplice wrapper per restituire i blocchi concatenati tramite 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);
  });
};

Puoi chiamarlo da una funzione asincrona con:

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

11

Se vuoi usare .get puoi farlo in questo modo

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

});

2
Gli altri esempi mi hanno dato quelli che sembravano valori esadecimali quando non includevo il testo con la risposta di blocco. L'impostazione della codifica mostrava il documento JSON che stavo cercando. Grazie!
Collin McGuire l'

@CollinMcGuire è perché erano oggetti Buffer contenenti dati non elaborati. Se volevi stringhe da loro, puoi anche usare chunk.toString(), opzionalmente, passare toStringe codificare. Detto questo, setEncodingè probabilmente più efficiente.
skeggse il

6

È necessario aggiungere un listener alla richiesta perché node.js funziona in modo asincrono in questo modo:

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

2

Anche il modulo ago è buono, ecco un esempio che utilizza il needlemodulo

var needle = require('needle');

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

0

Una porzione di caffè qui:

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

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

Non è possibile ottenere il corpo della risposta dal valore restituito di http.get().

http.get()non restituisce un oggetto risposta. Restituisce l'oggetto richiesta ( http.clientRequest). Quindi, non esiste alcun modo per ottenere il corpo della risposta dal valore di ritorno dihttp.get() .

So che è una vecchia domanda, ma la lettura della documentazione che hai collegato mostra che questo era il caso anche quando l'hai pubblicato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.