2012-01-28 32 views
6

Khi thực hiện dịch vụ HTTP trong Node.js, có rất nhiều mẫu mã như dưới đây sử dụng để có được những thực thể yêu cầu toàn bộ (dữ liệu được tải lên bởi khách hàng, ví dụ như một POST với dữ liệu JSON):Các sự cố khi phân tích cú pháp các ký tự UTF8 trong nội dung yêu cầu?

var http = require('http'); 

var server = http.createServer(function(req, res) { 
    var data = ''; 
    req.setEncoding('utf8'); 

    req.on('data', function(chunk) { 
     data += chunk; 
    }); 

    req.on('end', function() { 
     // parse data 
    }); 
}); 

Sử dụng req.setEncoding('utf8') sẽ tự động giải mã byte đầu vào thành chuỗi, giả sử đầu vào được mã hóa UTF8. Nhưng tôi có cảm giác rằng nó có thể phá vỡ. Điều gì sẽ xảy ra nếu chúng tôi nhận được một đoạn dữ liệu kết thúc ở giữa ký tự UTF8 nhiều byte? Chúng tôi có thể mô phỏng này:

> new Buffer("café") 
<Buffer 63 61 66 c3 a9> 
> new Buffer("café").slice(0,4) 
<Buffer 63 61 66 c3> 
> new Buffer("café").slice(0,4).toString('utf8') 
'caf?' 

Vì vậy, chúng tôi nhận được một nhân vật sai lầm thay vì chờ đợi cho các byte tiếp theo để giải mã đúng ký tự cuối cùng.

Do đó, trừ khi đối tượng yêu cầu quan tâm đến điều này, hãy đảm bảo rằng chỉ các ký tự được giải mã hoàn toàn mới được đẩy thành khối, mẫu mã phổ biến này bị hỏng.

Việc thay thế sẽ được sử dụng bộ đệm, xử lý các vấn đề về giới hạn kích thước bộ đệm:

var http = require('http'); 
var MAX_REQUEST_BODY_SIZE = 16 * 1024 * 1024; 

var server = http.createServer(function(req, res) { 
    // A better way to do this could be to start with a small buffer 
    // and grow it geometrically until the limit is reached. 
    var requestBody = new Buffer(MAX_REQUEST_BODY_SIZE); 
    var requestBodyLength = 0; 

    req.on('data', function(chunk) { 
     if(requestBodyLength + chunk.length >= MAX_REQUEST_BODY_SIZE) { 
      res.statusCode = 413; // Request Entity Too Large 
      return; 
     } 
     chunk.copy(requestBody, requestBodyLength, 0, chunk.length); 
     requestBodyLength += chunk.length; 
    }); 

    req.on('end', function() { 
     if(res.statusCode == 413) { 
      // handle 413 error 
      return; 
     } 

     requestBody = requestBody.toString('utf8', 0, requestBodyLength); 
     // process requestBody as string 
    }); 
}); 

Tôi có phải không, hay là này đã đưa về chăm sóc bởi lớp yêu cầu http?

+0

Cảm ơn bạn đã hỏi điều này. Tôi nghĩ rằng tôi sẽ phát điên là người duy nhất trên hành tinh nghĩ rằng đây có thể là một vấn đề ;-) – dty

Trả lời

7

Điều này được thực hiện tự động. Có một mô-đun string_decoder trong nút được tải khi bạn gọi setEncoding. Bộ giải mã sẽ kiểm tra vài byte cuối cùng nhận được và lưu trữ chúng giữa các lần phát ra 'dữ liệu' nếu chúng không phải là ký tự đầy đủ, vì vậy dữ liệu sẽ luôn nhận được một chuỗi chính xác. Nếu bạn không làm setEncoding, và không sử dụng string_decoder chính mình, sau đó bộ đệm phát ra có thể có vấn đề bạn đề cập, mặc dù.

Các tài liệu không có nhiều sự giúp đỡ, mặc dù http://nodejs.org/docs/latest/api/string_decoder.html, nhưng bạn có thể thấy các module đây, https://github.com/joyent/node/blob/master/lib/string_decoder.js

Việc thực hiện 'setEncoding' và logic cho phát cũng làm cho nó rõ ràng hơn.

1

Chỉ cần thêm response.setEncoding ('utf8'); để request.on ('trả lời') chức năng gọi lại. Trong trường hợp của tôi là đủ.

0
// Post : 'tèéïst3 ùél' 
// Node return : 't%C3%A8%C3%A9%C3%AFst3+%C3%B9%C3%A9l' 
decodeURI('t%C3%A8%C3%A9%C3%AFst3+%C3%B9%C3%A9l'); 
// Return 'tèéïst3+ùél' 
Các vấn đề liên quan