【问题标题】:Problems with parsing UTF8 characters in request body?解析请求正文中的 UTF8 字符时出现问题?
【发布时间】: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


【解决方案1】:

这是自动处理的。节点中有一个 string_decoder 模块,当您调用 setEncoding 时会加载该模块。解码器将检查接收到的最后几个字节,如果它们不是完整的字符,则将它们存储在“数据”的发射之间,因此数据将始终获得正确的字符串。如果您不执行 setEncoding,并且自己不使用 string_decoder,那么发出的缓冲区可能会出现您提到的问题。

尽管文档没有多大帮助,http://nodejs.org/docs/latest/api/string_decoder.html,但您可以在此处查看模块,https://github.com/joyent/node/blob/master/lib/string_decoder.js

'setEncoding' 的实现和发出的逻辑也使其更加清晰。

【讨论】:

    【解决方案2】:

    只需添加 response.setEncoding('utf8');到 request.on('response') 回调函数。就我而言,这就足够了。

    【讨论】:

      【解决方案3】:
      // 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'
      

      【讨论】:

        猜你喜欢
        • 2019-01-14
        • 1970-01-01
        • 1970-01-01
        • 2022-09-30
        • 2018-01-15
        • 2020-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多