Wo befindet sich body in einer http.get-Antwort von nodejs?

187

Ich lese die Dokumente unter http://nodejs.org/docs/v0.4.0/api/http.html#http.request , aber aus irgendeinem Grund kann ich das Attribut body / data scheinbar nicht finden auf dem zurückgegebenen, fertigen Antwortobjekt.

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

> res.finished
true

> res._hasBody
true

Es ist fertig (http.get erledigt das für Sie), also sollte es irgendeine Art von Inhalt haben. Aber es gibt keinen Körper, keine Daten und ich kann nicht daraus lesen. Wo versteckt sich der Körper?

Mikemaccana
quelle
7
Da in keiner der Antworten angegeben ist, woher Sie wissen, wann die dataEreignisse abgeschlossen sind, sollten Sie resauf "end"( nodejs.org/docs/latest/api/http.html#event_end_ ) hören
SooDesuNe

Antworten:

172

http.request docs enthält ein Beispiel für den Empfang des Antwortkörpers durch die Behandlung von dataEreignissen:

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 macht dasselbe wie http.request, ruft jedoch req.end()automatisch auf.

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
quelle
15
Aus irgendeinem Grund musste ich res.setEncoding('utf8');das http.get-Beispiel ergänzen. Ansonsten habe ich kein HTML in der chunkVariablen bekommen.
SSH Diesen
1
@SSHTDas liegt daran, dass es sich um Pufferobjekte handelt, die Rohdaten enthalten. Wenn Sie Zeichenfolgen von ihnen möchten, können Sie auch chunk.toString () verwenden und optional an String und Codierung übergeben. Allerdings ist setEncoding wahrscheinlich effizienter.
skeggse
14
Das Ereignis "Daten" kann mehrmals aufgerufen werden und Sie erhalten den Inhalt Stück für Stück. Das Beispiel zeigt nicht, wie man sie zusammenklebt.
Andrej
4
@tfmontague. Einverstanden! Überraschend ... so viele positive Stimmen für eine Antwort, die von Grund auf fehlerhaft ist.
Sunny
@tfmontague: POST requests typically use a response body, not GET.Post- Anfrage hat einen Body und GET- Anfrage nicht, aber eine GET- Antwort kann einen Body haben.
Cyrbil
135

Ich möchte auch hinzufügen, dass der http.ClientResponsezurückgegebene von http.get()ein endEreignis hat. Hier ist eine andere Möglichkeit, wie ich die Körperantwort erhalte:

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
quelle
13
Dank dafür! Das "Endereignis" war für mich von entscheidender Bedeutung, da ich den Antwortkörper als Ganzes und nicht in Stücken verarbeiten musste.
Daniel Gruszczyk
http.ClientResponsewird nicht von http.get() http.ClientRequestis zurückgegeben, gemäß der aktuellen Dokumentation und der Dokumentation, auf die das Originalplakat verweist.
Vince
54

Bearbeiten: 6 Jahre später auf sich selbst antworten

Das Warten Schlüsselwort ist der beste Weg, um eine Antwort von einer HTTP-Anfrage zu erhalten und Rückrufe zu vermeiden.then()

Sie müssen auch einen HTTP-Client verwenden, der Versprechen zurückgibt. http.get()Gibt immer noch ein Request-Objekt zurück, sodass dies nicht funktioniert. Sie könnten verwenden fetch, sondern superagentist ein ausgereiftes HTTP - Client, der mehr sinnvolle Voreinstellungen einschließlich einfacher Query - String - Codierung bietet, richtig Mime - Typen, JSON standardmäßig verwendet wird , und anderen gängigen HTTP - Client - Funktionen. awaitwartet, bis das Versprechen einen Wert hat - in diesem Fall eine HTTP-Antwort!

const superagent = require('superagent');

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

Mit await geht die Steuerung einfach in die nächste Zeile über, sobald das von zurückgegebene Versprechen superagent.get()einen Wert hat.

Mikemaccana
quelle
3
Dies beantwortet Ihre ursprüngliche Frage nicht. Wird in Ihrem Beispielcode resauf den Rückgabewert von gesetzt superagent.get(), nicht http.get(). http.get()Gibt eine zurück http.IncomingMessage, die keine textEigenschaft hat. Es ist nicht das Antwortobjekt, es ist das Anforderungsobjekt.
Vince
Guter Punkt Vince Ich werde die Antwort bearbeiten, um sie sauberer zu machen. Ich verwende einen HTTP-Client, der Promises unterstützt.
Mikemaccana
12

Das dataEreignis wird mehrmals mit "Chunks" des Körpers beim Herunterladen und einem endEreignis ausgelöst, wenn alle Chunks heruntergeladen wurden.

Da Node jetzt Promises unterstützt , habe ich einen einfachen Wrapper erstellt, um die verketteten Blöcke über ein Promise zurückzugeben:

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

Sie können es von einer asynchronen Funktion aus aufrufen mit:

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

Wenn Sie .get verwenden möchten, können Sie dies folgendermaßen tun

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

});
user969714
quelle
2
Die anderen Beispiele gaben mir etwas, das wie Hex-Werte aussah, als ich der Chunk-Antwort keinen Text hinzufügte. Durch Festlegen der Codierung wird das gesuchte JSON-Dokument angezeigt. Danke dir!
Collin McGuire
@CollinMcGuire, weil es sich um Pufferobjekte handelt, die Rohdaten enthalten. Wenn Sie Zeichenfolgen von ihnen möchten, können Sie diese auch verwenden chunk.toString(), optional übergeben toStringund codieren. Das heißt, setEncodingist wahrscheinlich effizienter.
skeggse
6

Sie müssen der Anforderung einen Listener hinzufügen, da node.js wie folgt asynchron arbeitet:

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

Nadelmodul ist auch gut, hier ist ein Beispiel, das needleModul verwendet

var needle = require('needle');

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

Eine Portion Kaffee hier:

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

Und zusammengestellt

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
quelle
0

Sie können den Hauptteil der Antwort nicht aus dem Rückgabewert von abrufen http.get().

http.get()gibt kein Antwortobjekt zurück. Es gibt das Anforderungsobjekt ( http.clientRequest) zurück. Es gibt also keine Möglichkeit, den Hauptteil der Antwort aus dem Rückgabewert von zu ermitteln http.get().

Ich weiß, dass es eine alte Frage ist, aber das Lesen der Dokumentation, mit der Sie verlinkt haben, zeigt, dass dies auch dann der Fall war, als Sie es veröffentlicht haben.

Vince
quelle