2012-01-28 14 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 
    }); 
}); 

req.setEncoding('utf8')を使用すると、入力が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 
    }); 
}); 

は、右Iアム、またはこれはすでにhttpリクエストクラスで世話をしていますか?

+0

ありがとうございます。私は惑星上で唯一の人であると怒っていると思っていましたが、これは問題だと思っていました;-) – dty

答えて

7

これは自動的に行われます。 setEncodingを呼び出すとロードされるnodeに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( 'UTF8')を追加します。 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' 
関連する問題