Cơ thể trong một phản hồi http.get của nodejs ở đâu?


187

Tôi đang đọc tài liệu tại http://nodejs.org/docs/v0.4.0/api/http.html#http.request , nhưng vì một số lý do, tôi dường như không thể thực sự tìm thấy thuộc tính cơ thể / dữ liệu trên đối tượng trả lại, kết thúc.

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

> res.finished
true

> res._hasBody
true

Nó đã kết thúc (http.get làm điều đó cho bạn), vì vậy nó nên có một số loại nội dung. Nhưng không có cơ thể, không có dữ liệu và tôi không thể đọc được từ đó. Cơ thể trốn ở đâu?


7
Vì không có câu trả lời nào đề cập đến việc bạn sẽ biết khi nào các datasự kiện được thực hiện .. reshãy lắng nghe "end"( nodejs.org/docs/latest/api/http.html#event_end_ )
SooDesuNe

Câu trả lời:


172

Tài liệu http.request chứa ví dụ về cách nhận nội dung phản hồi thông qua xử lý datasự kiện:

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 thực hiện tương tự như http.request ngoại trừ việc nó req.end()tự động gọi .

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
Vì một số lý do, tôi đã phải thêm res.setEncoding('utf8');vào ví dụ http.get. Nếu không, tôi đã không nhận được HTML trong chunkbiến.
SSH này

1
@SSHT đó là vì chúng là các đối tượng đệm chứa dữ liệu thô. Nếu bạn muốn chuỗi từ chúng, bạn cũng có thể sử dụng chunk.toString (), tùy ý chuyển sangString và mã hóa. Điều đó nói rằng, setEncoding có khả năng hiệu quả hơn.
xiên

14
Sự kiện "dữ liệu" có thể được gọi nhiều lần và bạn sẽ nhận được từng phần nội dung. Ví dụ không chỉ ra cách dán chúng lại với nhau.
Andrej

4
@tfmontague. Đã đồng ý! Đáng ngạc nhiên ... rất nhiều người ủng hộ cho một câu trả lời thiếu sót ở chính nền tảng của nó.
Nắng

@tfmontague: Yêu cầuPOST requests typically use a response body, not GET. đăng có một cơ thể và yêu cầu GET thì không, nhưng phản hồi GET có thể có một cơ thể.
Cyrbil

135

Tôi cũng muốn thêm rằng sự http.ClientResponsetrở lại của http.get()có một endsự kiện, vì vậy đây là một cách khác mà tôi nhận được phản hồi của cơ thể:

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
Cảm ơn vì điều đó! Sự kiện 'kết thúc' rất quan trọng đối với tôi khi tôi phải xử lý toàn bộ cơ quan phản hồi, thay vì theo từng khối.
Daniel Gruszchot

http.ClientResponsekhông được trả lại bởi http.get() http.ClientRequest, theo cả tài liệu hiện tại và tài liệu được liên kết bởi người đăng ban đầu.
Vince

54

Chỉnh sửa: trả lời tự 6 năm sau

Các chờ đợi từ khóa là cách tốt nhất để có được một phản hồi từ một yêu cầu HTTP, tránh callbacks và.then()

Bạn cũng sẽ cần sử dụng ứng dụng khách HTTP trả về Lời hứa. http.get()vẫn trả về một đối tượng Yêu cầu, do đó sẽ không hoạt động. Bạn có thể sử dụng fetch, nhưng superagentlà một máy khách HTTP trưởng thành có các giá trị mặc định hợp lý hơn bao gồm mã hóa chuỗi truy vấn đơn giản hơn, sử dụng đúng loại mime, JSON theo mặc định và các tính năng máy khách HTTP phổ biến khác. awaitsẽ đợi cho đến khi Promise có giá trị - trong trường hợp này, phản hồi HTTP!

const superagent = require('superagent');

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

Sử dụng chờ đợi, kiểm soát chỉ cần chuyển sang dòng tiếp theo một khi lời hứa được trả về superagent.get()có giá trị.


3
Điều này không trả lời câu hỏi ban đầu của bạn. Trong mã ví dụ của bạn, resđược đặt thành giá trị trả về của superagent.get(), không http.get(). http.get()trả lại một http.IncomingMessagecái mà không có texttài sản. Nó không phải là đối tượng phản hồi, nó là đối tượng yêu cầu.
Vince

Điểm hay Vince tôi sẽ chỉnh sửa câu trả lời để làm cho nó sạch hơn Tôi đang sử dụng ứng dụng khách HTTP hỗ trợ Promise.
mikemaccana

12

Sự datakiện này được thực hiện nhiều lần với 'khối' cơ thể khi chúng được tải xuống và một endsự kiện khi tất cả các đoạn đã được tải xuống.

Với Node hỗ trợ Promises bây giờ, tôi đã tạo ra một wrapper đơn giản để trả lại khối nối thông qua một 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);
  });
};

Bạn có thể gọi nó từ một chức năng không đồng bộ với:

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

11

Nếu bạn muốn sử dụng. Quên bạn có thể làm như thế này

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

});

2
Các ví dụ khác đã cho tôi những gì trông giống như các giá trị hex khi tôi không bao gồm văn bản với phản hồi chunk. Đặt mã hóa hiển thị tài liệu JSON mà tôi đang tìm kiếm. Cảm ơn bạn!
Collin McGuire

@CollinMcGuire đó là vì chúng là các đối tượng Bộ đệm chứa dữ liệu thô. Nếu bạn muốn chuỗi từ chúng, bạn cũng có thể sử dụng chunk.toString(), tùy ý chuyển toStringvà mã hóa. Điều đó nói rằng, setEncodingcó khả năng hiệu quả hơn.
xiên

6

Bạn cần thêm một trình lắng nghe vào yêu cầu vì node.js hoạt động không đồng bộ như thế:

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

2

Mô-đun kim cũng tốt, đây là một ví dụ sử dụng needlemô-đun

var needle = require('needle');

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

0

Một phần của Cà phê ở đây:

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

Và biên soạn

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

Bạn không thể nhận được nội dung phản hồi từ giá trị trả về của http.get().

http.get()không trả về một đối tượng phản hồi. Nó trả về đối tượng yêu cầu ( http.clientRequest). Vì vậy, không có cách nào để có được phần thân của phản hồi từ giá trị trả về của http.get().

Tôi biết đó là một câu hỏi cũ, nhưng đọc tài liệu bạn liên kết để cho thấy rằng đây là trường hợp ngay cả khi bạn đăng nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.