2012-01-28 26 views
6

當實現在node.js的HTTP服務,有很多的示例代碼象下面用來獲得整個請求實體(由客戶端上載的數據,例如與JSON數據的POST):解析請求正文中的UTF8字符的問題?

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的請求類照顧?

+0

謝謝你的提問。我以爲我瘋了是這個星球上唯一認爲這可能是個問題的人;-) – dty 2013-07-04 15:01:21

回答

7

這是自動處理的。在調用setEncoding時加載的節點中有一個string_decoder模塊。解碼器將檢查接收到的最後幾個字節,並將它們存儲在「數據」發出之間,如果它們不是全字符的話,那麼數據總是會得到正確的字符串。如果你沒有執行setEncoding,並且你自己不使用string_decoder,那麼發出的緩衝區可能會遇到你提到的問題。

的文檔是沒有太大的幫助,雖然,http://nodejs.org/docs/latest/api/string_decoder.html,但你可以看到這裏的模塊,https://github.com/joyent/node/blob/master/lib/string_decoder.js

「setEncoding」和用於發射邏輯的實現也使得它更清晰。

1

只需添加response.setEncoding( 'utf-8'); request.on('response')回調函數。在我的情況下,這是足夠的。

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'