เนื้อความอยู่ในการตอบสนอง http.get ของ nodejs?


187

ฉันอ่านเอกสารที่http://nodejs.org/docs/v0.4.0/api/http.html#http.requestแต่ด้วยเหตุผลบางอย่างฉันไม่สามารถหาแอตทริบิวต์ของร่างกาย / ข้อมูลได้จริง บนวัตถุตอบกลับที่เสร็จสิ้นแล้ว

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

> res.finished
true

> res._hasBody
true

เสร็จแล้ว (http.get ทำเพื่อคุณ) ดังนั้นควรมีเนื้อหาบางประเภท แต่ไม่มีเนื้อหาไม่มีข้อมูลและฉันไม่สามารถอ่านได้ ร่างกายซ่อนตัวอยู่ที่ไหน


7
เนื่องจากไม่มีคำตอบใดที่พูดถึงว่าคุณจะรู้ได้อย่างไรเมื่อมีdataเหตุการณ์เกิดขึ้น .. ให้คุณresฟัง"end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

คำตอบ:


172

http.request docs มีตัวอย่างวิธีรับเนื้อหาของการตอบสนองผ่านการจัดการdataเหตุการณ์:

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ทำสิ่งเดียวกันกับ http.request ยกเว้นว่าจะเรียกreq.end()โดยอัตโนมัติ

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
ด้วยเหตุผลบางอย่างฉันต้องเพิ่มres.setEncoding('utf8');ตัวอย่าง http.get มิฉะนั้นฉันไม่ได้รับ HTML ในchunkตัวแปร
SSH นี้

1
@SSH นี่เป็นเพราะพวกเขาเป็นวัตถุบัฟเฟอร์ที่มีข้อมูลดิบ หากคุณต้องการสตริงจากพวกเขาคุณสามารถใช้ chunk.toString () เลือกที่จะผ่านไปที่สตริงและเข้ารหัส ที่กล่าวว่า setEncoding น่าจะมีประสิทธิภาพมากกว่า
skeggse

14
เหตุการณ์ "data" อาจเรียกได้หลายครั้งและคุณจะได้รับเนื้อหาทีละชิ้น ตัวอย่างไม่แสดงวิธีการติดกาวเข้าด้วยกัน
Andrej

4
@tfmontague ตกลงกัน! น่าประหลาดใจ ... ผู้อัปยศจำนวนมากสำหรับคำตอบที่มีข้อบกพร่องที่รากฐานของมัน
ซันนี่

@tfmontague: คำขอPOST requests typically use a response body, not GET.โพสต์มีเนื้อหาและคำขอ GET ไม่ได้ แต่การตอบกลับ GET สามารถมีเนื้อหาได้
Cyrbil

135

ฉันยังต้องการเพิ่มว่าเหตุการณ์ที่http.ClientResponseส่งคืนโดยhttp.get()มีendเหตุการณ์ดังนั้นนี่เป็นอีกวิธีหนึ่งที่ฉันได้รับการตอบสนองของร่างกาย:

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
ขอบคุณสำหรับสิ่งนั้น! เหตุการณ์ 'สิ้นสุด' มีความสำคัญสำหรับฉันเนื่องจากฉันต้องประมวลผลเนื้อหาการตอบสนองโดยรวมมากกว่าเป็นชิ้น ๆ
Daniel Gruszczyk

http.ClientResponseไม่ได้ส่งคืนโดยhttp.get() http.ClientRequestคือตามทั้งเอกสารปัจจุบันและเอกสารที่เชื่อมโยงกับโปสเตอร์ต้นฉบับ
วินซ์

54

แก้ไข: ตอบกลับด้วยตนเอง 6 ปีต่อมา

รอคอยคำหลักคือวิธีที่ดีที่สุดที่จะได้รับการตอบสนองจากการร้องขอ HTTP หลีกเลี่ยงการเรียกกลับและ.then()

คุณจะต้องใช้ไคลเอ็นต์ HTTP ที่ส่งคืนสัญญา http.get()ยังคงส่งคืนวัตถุคำขอเพื่อที่จะไม่ทำงาน คุณสามารถใช้fetchแต่superagentเป็นไคลเอนต์ HTTP ที่เป็นผู้ใหญ่ซึ่งมีค่าเริ่มต้นที่สมเหตุสมผลมากกว่ารวมถึงการเข้ารหัสสตริงข้อความค้นหาที่ง่ายขึ้นใช้ประเภท mime อย่างถูกต้อง JSON โดยค่าเริ่มต้นและคุณสมบัติไคลเอนต์ HTTP ทั่วไปอื่น ๆ awaitจะรอจนกว่าสัญญาจะมีค่า - ในกรณีนี้คือการตอบกลับ HTTP!

const superagent = require('superagent');

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

ใช้การรอคอยการควบคุมเพียงส่งผ่านไปยังบรรทัดถัดไปเมื่อสัญญาที่ส่งคืนโดยsuperagent.get()มีค่า


3
สิ่งนี้ไม่ตอบคำถามเดิมของคุณ ในรหัสตัวอย่างของคุณresถูกตั้งค่าให้ค่าตอบแทนของไม่ได้superagent.get() ส่งคืน a ที่ไม่มีคุณสมบัติ ไม่ใช่วัตถุตอบสนอง แต่เป็นวัตถุคำขอ http.get()http.get()http.IncomingMessagetext
วินซ์

จุดดีวินซ์ฉันจะแก้ไขคำตอบเพื่อทำให้มันสะอาดขึ้นฉันใช้ไคลเอนต์ HTTP ที่สนับสนุนสัญญา
mikemaccana

12

dataเหตุการณ์ถูกยิงหลายครั้งด้วย 'ชิ้น' ของร่างกายเช่นที่พวกเขาจะถูกดาวน์โหลดและendเหตุการณ์เมื่อชิ้นทั้งหมดได้รับการดาวน์โหลด

ด้วยโหนดสนับสนุนสัญญาตอนนี้ฉันสร้างเสื้อคลุมเรียบง่ายเพื่อส่งคืนชิ้นที่ต่อกันผ่านสัญญา:

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

คุณสามารถโทรจากฟังก์ชั่น async ด้วย:

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

11

หากคุณต้องการใช้. รับคุณสามารถทำสิ่งนี้ได้

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

});

2
ตัวอย่างอื่น ๆ ให้สิ่งที่ดูเหมือนว่าค่าเลขฐานสิบหกเมื่อฉันไม่ได้รวมข้อความที่มีการตอบสนองอัน การตั้งค่าการเข้ารหัสแสดงเอกสาร JSON ที่ฉันต้องการ ขอบคุณ!
Collin McGuire

@CollinMcGuire นั่นเป็นเพราะพวกเขาเป็นวัตถุบัฟเฟอร์ที่มีข้อมูลดิบ หากคุณต้องการสตริงจากพวกเขาคุณสามารถใช้chunk.toString()เลือกที่จะผ่านtoStringและเข้ารหัส ที่กล่าวว่าsetEncodingน่าจะมีประสิทธิภาพมากกว่า
skeggse

6

คุณต้องเพิ่ม listener ให้กับคำร้องขอเนื่องจาก node.js ทำงานแบบอะซิงโครนัสเช่นนั้น:

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

2

โมดูลเข็มยังดีนี่คือตัวอย่างที่ใช้needleโมดูล

var needle = require('needle');

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

0

ส่วนหนึ่งของกาแฟที่นี่:

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

และเรียบเรียง

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

http.get()คุณไม่สามารถได้รับร่างกายของการตอบสนองจากค่าตอบแทนของ

http.get()ไม่ส่งคืนวัตถุตอบกลับ มันจะส่งกลับวัตถุคำขอ ( http.clientRequest) http.get()ดังนั้นไม่มีทางที่จะได้รับร่างกายของการตอบสนองจากมูลค่าการกลับมาของใด ๆ

ฉันรู้ว่ามันเป็นคำถามเก่า แต่การอ่านเอกสารที่คุณเชื่อมโยงเพื่อแสดงให้เห็นว่าเป็นกรณีนี้แม้ว่าคุณจะโพสต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.