2013-01-07 10 views
6

私はクライアントからのメトリックを書く必要がある単純なノードアプリケーションを持っています。 クライアントはPythonのzlibモジュールでzipされたjson形式のメトリックを送信します。私はエクスプレスbodyParseが行われる前にリクエスト投稿を解凍するミドルウェアを追加しようとしています。ノード+エクスプレスでPOSTボディを解凍

私のミドルウェアは、単にデフォルトで特急が提供するものです。

app.configure(function(){ 
    app.set('port', process.env.PORT || 3000); 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.favicon()); 
    app.use(express.logger('dev')); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser('your secret here')); 
    app.use(express.session()); 
    app.use(app.router); 
    app.use(require('less-middleware')({ src: __dirname + '/public' })); 
    app.use(express.static(path.join(__dirname, 'public'))); 
}); 

私はデータを取得し、それを解凍シンプルなミドルウェアを追加しようとしました:

app.use(function(req, res, next) { 
    var data = ''; 
    req.addListener("data", function(chunk) { 
     data += chunk; 
    }); 

    req.addListener("end", function() { 
     zlib.inflate(data, function(err, buffer) { 
      if (!err) { 
       req.body = buffer; 
       next(); 
      } else { 
       next(err); 
      } 
     }); 
    }); 
}); 

問題zlib.inflateを使用しています。私はこのエラーを受け取ります:

Error: incorrect header check 

データが圧縮されていますPythonのzlibモジュール:

zlib.compress(jsonString) 

しかし、unzip、inflate、gunzipはどちらも動作していないようです。自分で解決策を見つけた

+0

はあなたがzlib.unzipから「ERR」を取得し、結果としてはありませんよろしいですnext()は呼び出されませんか?そのような場合は、データを配列に切り替えてみてください。この回答を調べるhttp://stackoverflow.com/a/12776856/30763さらに、bodyParserの前にミドルウェアが使用されていることを確認してください。 – Aaron

+0

その答えは、クライアントではなくノードによって行われた要求を解凍するためのものではありませんか?いずれの場合でも – alex88

+1

@ alex88の場合、エラーがある場合は 'next(err)'を呼び出す必要があります。また、 'bodyParser'ミドルウェアを忘れ、' req.body = JSON.parse(buffer) 'を直接行うことをお勧めします。 –

答えて

12

、問題は、コードのこの作品とあった:

req.addListener("data", function(chunk) { 
    data += chunk; 
}); 

要求データを連結することは正しくないので、私はこれに私のミドルウェアを切り替えたようだ:

app.use(function(req, res, next) { 
    var data = []; 
    req.addListener("data", function(chunk) { 
     data.push(new Buffer(chunk)); 
    }); 
    req.addListener("end", function() { 
     buffer = Buffer.concat(data); 
     zlib.inflate(buffer, function(err, result) { 
      if (!err) { 
       req.body = result.toString(); 
       next(); 
      } else { 
       next(err); 
      } 
     }); 
    }); 
}); 

バッファを連結すると完全に機能し、リクエストのボディを解凍できるようになりました。

+0

最初の試みが生のバイナリデータを文字列に変換していたためです。 UTF-8は圧縮されたデータストリームのような任意のバイトを保持するものではないため、データが破損しています。デフォルトでは、['data'](http://nodejs.org/api/http.html#http_event_data)イベントはあなたに[' Buffer'](http://nodejs.org/api/buffer.html# buffer_buffer)は、ノードが生データを処理する方法です。 – josh3736

+0

@ josh3736文字列に変換するとデータが失われていましたか?チャンクは既にバッファーであり、新しいバッファーを作成するのではなく、簡単にそれをプッシュできますか? – alex88

+0

[はい。 'data'イベントのドキュメントから:](http://nodejs.org/api/http.html#http_event_data) "*' request.setEncoding()でエンコーディングが設定されている場合、 'chunk'は文字列です。 'それ以外の場合は' Buffer' * * " – josh3736

1

私は、これは非常に遅れ応答である知っているが、モジュールbody-parserで、それがされます:

Returns middleware that only parses json. This parser accepts any Unicode encoding of the body and supports automatic inflation of gzip and deflate encodings.

var bodyParser = require('body-parser'); 
app.use(bodyParser.json());  // to support JSON-encoded bodies