【发布时间】:2012-01-28 14:42:38
【问题描述】:
在 node.js 中实现 HTTP 服务时,有很多如下示例代码用于获取整个请求实体(客户端上传的数据,例如带有 JSON 数据的 POST):
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
});
});
假设输入是 UTF8 编码的,使用 req.setEncoding('utf8') 会自动将输入字节解码为字符串。但我觉得它可以打破。如果我们收到一个以多字节 UTF8 字符中间结尾的数据块怎么办?我们可以模拟这个:
> 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?'
所以我们得到一个错误字符,而不是等待下一个字节正确解码最后一个字符。
因此,除非请求对象处理好这一点,确保只有完全解码的字符被推送到块中,否则这个无处不在的代码示例会被破坏。
替代方法是使用缓冲区,处理缓冲区大小限制的问题:
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
});
});
我是对的,还是 http 请求类已经处理好了?
【问题讨论】:
-
感谢您提出这个问题。我以为我是这个星球上唯一认为这可能是一个问题的人要疯了;-)
标签: node.js