web-dev-qa-db-ja.com

Nodejs:文字列をバッファに変換

文字列をソケットに書き込もうとしています(ソケットは「応答」と呼ばれます)。ここに私がソファーを持っているコードがあります(私はバイトキャッシュプロキシを実装しようとしています...):

_var http = require('http');
var sys=require('sys');

var localHash={};

http.createServer(function(request, response) {
    var proxy = http.createClient(80, request.headers['Host'])
    var proxy_request = proxy.request(request.method, request.url, request.headers);
    proxy_request.addListener('response', function (proxy_response) {
    proxy_response.addListener('data', function(x) {
        var responseData=x.toString();
        var f=50;
        var toTransmit="";
        var p=0;        

        var N=responseData.length;
        if(N>f){
            p=Math.floor(N/f);

            var hash="";
            var chunk="";
            for(var i=0;i<p;i++){
                chunk=responseData.substr(f*i,f);
                hash=DJBHash(chunk);
                if(localHash[hash]==undefined){
                    localHash[hash]=chunk;
                    toTransmit=toTransmit+chunk;
                }else{
                    sys.puts("***hit"+chunk);
                    toTransmit=toTransmit+chunk;//"***EOH"+hash;
                }
            }
            //remainder:
            chunk=responseData.substr(f*p);
            hash=DJBHash(chunk);
            if(localHash[hash]==undefined){
                localHash[hash]=chunk;
                toTransmit=toTransmit+chunk;
            }else{
                toTransmit=toTransmit+chunk;//"***EOH"+hash;
            }
        }else{
            toTransmit=responseData;
        }
        response.write(new Buffer(toTransmit));   /*error occurs here */
    });
    proxy_response.addListener('end', function() {
        response.end();
    });
    response.writeHead(proxy_response.statusCode, proxy_response.headers);
    });
    request.addListener('data', function(chunk) {
        sys.puts(chunk);
        proxy_request.write(chunk, 'binary');
    });
    request.addListener('end', function() {
        proxy_request.end();
    });
}).listen(8080);



function DJBHash(str) {
    var hash = 5381;
    for(var i = 0; i < str.length; i++) {
        hash = (((hash << 5) + hash) + str.charCodeAt(i)) & 0xffffffff;
    }
    if(hash<-1){
        hash=hash*-1;
    }
    return hash;
}
_

問題は、Firefoxで「コンテンツエンコーディングエラー」が発生し続けることです。これは、ギップされたコンテンツが適切に送信されていないかのようです。 「toTransmit」がconsole.log(x)およびconsole.log(toTransmit)を介して「x」と同じであることを確認しました。

response.write(new Buffer(toTransmit))を単にresponse.write(x)に置き換えると、プロキシは期待どおりに機能しますが、ペイロード分析を行ってから、「x」ではなく「toTransmit」を渡す必要があることに注意してください。

私はresponse.write(toTransmit)も試しました(つまり、バッファへの変換なしで)。同じコンテンツエンコーディングエラーが発生し続けます。

私は本当に行き詰まっています。別のスレッド(http://stackoverflow.com/questions/7090510/nodejs-content-encoding-error)のように文字列をバッファに変換することでこの問題を解決したと思いましたが、新しいスレッドを再開しました私が経験しているこの新しい問題について話し合う。

Operaのプロキシ経由でページを開くと、gobblydeegookが表示されます。これは、gzip圧縮されたデータが破損しているようです。

どんな洞察も大歓迎です。

よろしくお願いいたします。

13
Eamorr

あなたのコードを深く掘り下げることなく、あなたは変更したいと思うかもしれません

var responseData=x.toString();

var responseData=x.toString("binary");

そして最後に

response.write(new Buffer(toTransmit, "binary"));
20
Andris

これはどう?

var responseData = Buffer.from(x, 'utf8');

from: 文字列をバッファノードに変換

31
user1527225

ドキュメントから

純粋なJavascriptはUnicodeに対応していますが、バイナリデータには適していません。 TCPストリームまたはファイルシステムを処理する場合、オクテットストリームを処理する必要があります。Nodeには、オクテットストリームを操作、作成、および消費するためのいくつかの戦略があります。

生データは、Bufferクラスのインスタンスに格納されます。バッファは整数の配列に似ていますが、V8ヒープ外の未加工メモリ割り当てに対応しています。バッファのサイズを変更することはできません。

したがって、バイナリデータの処理に文字列を使用しないでください。

proxy_request.write(chunk, 'binary');proxy_request.write(chunk);に変更します。

var responseData=x.toString();を省略してください。これは悪い考えです。

文字列に対してsubstrを実行する代わりに、バッファに対してsliceを使用します。

文字列で+を実行する代わりに、 buffertools の「concat」メソッドを使用します。

5
thejh