Di mana tubuh dalam respons node.js http.get?


187

Saya membaca dokumen di http://nodejs.org/docs/v0.4.0/api/http.html#http.request , tetapi untuk beberapa alasan, saya sepertinya tidak dapat menemukan atribut body / data pada objek respons yang dikembalikan dan selesai.

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

> res.finished
true

> res._hasBody
true

Sudah selesai (http.get lakukan itu untuk Anda), jadi itu harus memiliki beberapa jenis konten. Tetapi tidak ada tubuh, tidak ada data, dan saya tidak bisa membacanya. Di mana tubuh bersembunyi?


7
Karena tidak ada jawaban yang menyebutkan bagaimana Anda akan tahu kapan dataacara selesai .. minta Anda resmendengarkan "end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

Jawaban:


172

http.request docs berisi contoh cara menerima isi respons melalui penanganan dataacara:

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 melakukan hal yang sama dengan http.request kecuali ia memanggil req.end()secara otomatis.

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
Untuk beberapa alasan, saya harus menambahkan res.setEncoding('utf8');contoh http.get. Kalau tidak, saya tidak mendapatkan HTML dalam chunkvariabel.
SSH

1
@ SSHHal ini karena mereka adalah objek Buffer yang berisi data mentah. Jika Anda menginginkan string dari mereka, Anda juga bisa menggunakan chunk.toString (), secara opsional meneruskan keString dan pengkodean. Yang mengatakan, setEncoding kemungkinan lebih efisien.
skeggse

14
Acara "data" mungkin dipanggil beberapa kali dan Anda akan mendapatkan kontennya sepotong demi sepotong. Contoh tidak menunjukkan cara menempelkannya.
Andrej

4
@ tfmontague. Sepakat! Mengejutkan ... begitu banyak upvotes untuk jawaban yang cacat pada dasarnya.
Sunny

@ tfmontague: PermintaanPOST requests typically use a response body, not GET. posting memiliki tubuh dan permintaan GET tidak, tetapi respons GET dapat memiliki badan.
Cyrbil

135

Saya juga ingin menambahkan bahwa yang http.ClientResponsedikembalikan oleh http.get()memiliki endacara, jadi di sini adalah cara lain yang saya terima tanggapan tubuh:

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
Terima kasih untuk itu! Peristiwa 'akhir' sangat penting bagi saya karena saya harus memproses badan respons secara keseluruhan, bukan dalam potongan.
Daniel Gruszczyk

http.ClientResponsetidak dikembalikan oleh http.get() http.ClientRequest, menurut dokumentasi saat ini dan dokumentasi yang ditautkan oleh pengirim aslinya.
Vince

54

Sunting: membalas ke diri sendiri 6 tahun kemudian

Kata kunci yang menunggu adalah cara terbaik untuk mendapatkan respons dari permintaan HTTP, menghindari panggilan balik dan.then()

Anda juga harus menggunakan klien HTTP yang mengembalikan Janji. http.get()masih mengembalikan objek Permintaan, sehingga itu tidak akan berfungsi. Anda dapat menggunakan fetch, tetapi superagentmerupakan klien HTTP dewasa yang memiliki fitur default yang lebih masuk akal termasuk pengkodean string kueri yang lebih sederhana, menggunakan jenis mime, JSON secara default, dan fitur klien HTTP umum lainnya. awaitakan menunggu hingga Janji memiliki nilai - dalam hal ini, respons HTTP!

const superagent = require('superagent');

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

Menggunakan menunggu, kontrol hanya berpindah ke baris berikutnya setelah janji dikembalikan oleh superagent.get()memiliki nilai.


3
Ini tidak menjawab pertanyaan awal Anda. Dalam kode contoh Anda, resdiatur ke nilai balik superagent.get(), bukan http.get(). http.get()mengembalikan a http.IncomingMessageyang tidak memiliki textproperti. Itu bukan objek respons, itu objek permintaan.
Vince

Poin yang bagus Vince saya akan mengedit jawaban untuk membuatnya lebih bersih Saya menggunakan klien HTTP yang mendukung Janji.
mikemaccana

12

The dataevent ditembakkan beberapa kali dengan 'potongan' dari tubuh sebagai mereka di-download dan endacara ketika semua potongan telah di-download.

Dengan Node yang mendukung Janji sekarang, saya membuat pembungkus sederhana untuk mengembalikan potongan gabungan melalui Janji:

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

Anda dapat memanggilnya dari fungsi async dengan:

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

11

Jika Anda ingin menggunakan .get Anda dapat melakukannya seperti ini

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

});

2
Contoh-contoh lain memberi saya apa yang tampak seperti nilai hex ketika saya tidak memasukkan teks dengan respons chunk. Pengaturan penyandian ditampilkan pada dokumen JSON yang saya cari. Terima kasih!
Collin McGuire

@CollinMcGuire itu karena mereka adalah objek Buffer yang berisi data mentah. Jika Anda menginginkan string dari mereka, Anda juga dapat menggunakan chunk.toString(), secara opsional meneruskan toStringdan menyandikan. Yang mengatakan, setEncodingkemungkinan lebih efisien.
skeggse

6

Anda perlu menambahkan pendengar ke permintaan karena node.js berfungsi asinkron seperti itu:

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

2

Modul jarum juga bagus, berikut adalah contoh yang menggunakan needlemodul

var needle = require('needle');

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

0

Sebagian Kopi di sini:

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

Dan disusun

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

Anda tidak dapat memperoleh isi respons dari nilai pengembalian sebesar http.get().

http.get()tidak mengembalikan objek respons. Ini mengembalikan objek permintaan ( http.clientRequest). Jadi, tidak ada cara untuk mendapatkan isi tanggapan dari nilai pengembalian http.get().

Saya tahu ini adalah pertanyaan lama, tetapi membaca dokumentasi yang Anda tautkan menunjukkan bahwa ini adalah masalahnya bahkan ketika Anda mempostingnya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.