Où est body dans une réponse nodejs http.get?

187

Je lis la documentation sur http://nodejs.org/docs/v0.4.0/api/http.html#http.request , mais pour une raison quelconque, je n'arrive pas à trouver l'attribut body / data sur l'objet de réponse renvoyé et terminé.

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

> res.finished
true

> res._hasBody
true

C'est fini (http.get le fait pour vous), donc il devrait avoir une sorte de contenu. Mais il n'y a pas de corps, pas de données et je ne peux pas en lire. Où se cache le corps?

Mikemaccana
la source
7
Étant donné qu'aucune des réponses ne mentionne comment vous saurez quand les dataévénements sont terminés .. resécoutez "end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

Réponses:

172

La documentation http.request contient un exemple de comment recevoir le corps de la réponse via l' dataévénement de gestion :

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 fait la même chose que http.request sauf qu'il appelle req.end()automatiquement.

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
la source
15
Pour une raison quelconque, j'ai dû ajouter res.setEncoding('utf8');à l'exemple http.get. Sinon, je n'ai pas eu HTML dans la chunkvariable.
SSH ce
1
@SSHC'est parce qu'il s'agissait d'objets Buffer contenant des données brutes. Si vous en vouliez des chaînes, vous pouvez également utiliser chunk.toString (), en passant éventuellement toString et encoding. Cela dit, setEncoding est probablement plus efficace.
skeggse
14
L'événement "data" peut être appelé plusieurs fois et vous obtiendrez le contenu morceau par morceau. L'exemple ne montre pas comment les coller ensemble.
Andrej
4
@tfmontague. D'accord! Surprenant ... autant de votes positifs pour une réponse qui est imparfaite à sa base même.
Ensoleillé du
@tfmontague: POST requests typically use a response body, not GET.La demande de publication a un corps et la demande GET n'en a pas, mais une réponse GET peut avoir un corps.
Cyrbil
135

Je veux également ajouter que le http.ClientResponserenvoyé par http.get()a un endévénement, voici donc une autre façon de recevoir la réponse du corps:

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);
}); 
bizi
la source
13
Merci pour ça! L'événement «de fin» était crucial pour moi car je devais traiter le corps de la réponse dans son ensemble, plutôt que par morceaux.
Daniel Gruszczyk
http.ClientResponsen'est pas retourné par http.get() http.ClientRequestest, selon à la fois la documentation actuelle et la documentation liée à l'affiche originale.
Vince
54

Edit: se répondre 6 ans plus tard

Le mot - clé await est le meilleur moyen d'obtenir une réponse à partir d'une requête HTTP, en évitant les rappels et.then()

Vous devrez également utiliser un client HTTP qui renvoie des promesses. http.get()retourne toujours un objet Request, donc cela ne fonctionnera pas. Vous pouvez utiliser fetch, mais superagentc'est un client HTTP mature qui présente des valeurs par défaut plus raisonnables, notamment un codage de chaîne de requête plus simple, utilisant correctement les types mime, JSON par défaut et d'autres fonctionnalités courantes du client HTTP. awaitattendra que la promesse ait une valeur - dans ce cas, une réponse HTTP!

const superagent = require('superagent');

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

En utilisant await, le contrôle passe simplement à la ligne suivante une fois que la promesse renvoyée par superagent.get()a une valeur.

Mikemaccana
la source
3
Cela ne répond pas à votre question initiale. Dans votre exemple de code, resest défini sur la valeur de retour de superagent.get(), non http.get(). http.get()renvoie un http.IncomingMessagequi n'a pas de textpropriété. Ce n'est pas l'objet de réponse, c'est l'objet de requête.
Vince
Bon point Vince Je vais éditer la réponse pour la rendre plus propre J'utilise un client HTTP qui prend en charge les promesses.
mikemaccana
12

L' dataévénement est déclenché plusieurs fois avec des «morceaux» du corps lorsqu'ils sont téléchargés et un endévénement lorsque tous les morceaux ont été téléchargés.

Avec Node prenant en charge les promesses maintenant, j'ai créé un wrapper simple pour renvoyer les morceaux concaténés via une promesse:

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);
  });
};

Vous pouvez l'appeler depuis une fonction asynchrone avec:

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

Si vous voulez utiliser .get, vous pouvez le faire comme ceci

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

});
user969714
la source
2
Les autres exemples m'ont donné ce qui ressemblait à des valeurs hexadécimales lorsque je n'incluais pas de texte avec la réponse de bloc. La configuration de l'encodage a affiché le document JSON que je recherchais. Je vous remercie!
Collin McGuire
@CollinMcGuire c'est parce qu'il s'agissait d'objets Buffer contenant des données brutes. Si vous en vouliez des chaînes, vous pouvez également les utiliser chunk.toString(), éventuellement en passant toStringet en encodant. Cela dit, setEncodingest probablement plus efficace.
skeggse
6

Vous devez ajouter un écouteur à la requête car node.js fonctionne de manière asynchrone comme ça:

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

Le module d'aiguille est également bon, voici un exemple qui utilise le needlemodule

var needle = require('needle');

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

Une portion de café ici:

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

Et compilé

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
    }));
  });
});
18août
la source
0

Vous ne pouvez pas obtenir le corps de la réponse à partir de la valeur de retour de http.get().

http.get()ne renvoie pas d'objet de réponse. Il renvoie l'objet de requête ( http.clientRequest). Il n'y a donc aucun moyen d'obtenir le corps de la réponse à partir de la valeur de retour de http.get().

Je sais que c'est une vieille question, mais la lecture de la documentation à laquelle vous avez lié montre que c'était le cas même lorsque vous l'avez postée.

Vince
la source