Node.js-Expressを使用して生のリクエスト本文を取得します


回答:


89

編集2:ボディパーサーモジュールのリリース1.15.2では、ボディをバッファーとして返すrawモードが導入されています。デフォルトでは、deflateとgzipの解凍も自動的に処理します。使用例:

var bodyParser = require('body-parser');
app.use(bodyParser.raw(options));

app.get(path, function(req, res) {
  // req.body is a Buffer object
});

デフォルトでは、optionsオブジェクトには次のデフォルトオプションがあります。

var options = {
  inflate: true,
  limit: '100kb',
  type: 'application/octet-stream'
};

生のパーサーで以外の他のMIMEタイプを解析するapplication/octet-stream場合は、ここで変更する必要があります。*/*またはなどのワイルドカードマッチングもサポートし*/applicationます。


注:次の回答は、ミドルウェアがまだフレームワークにバンドルされているExpress4より前のバージョンに対するものです。最新の同等物はbody-parserモジュールであり、個別にインストールする必要があります。

rawBodyExpressのプロパティはかつて利用可能でしたが、バージョン1.5.1以降削除されました。生のリクエストボディを取得するには、bodyParserを使用する前にミドルウェアを挿入する必要があります。ここでそれに関するGitHubのディスカッションを読むこともできます

app.use(function(req, res, next) {
  req.rawBody = '';
  req.setEncoding('utf8');

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  req.on('end', function() {
    next();
  });
});
app.use(express.bodyParser());

そのミドルウェアは実際のデータストリームから読み取り、それをrawBodyリクエストのプロパティに保存します。次に、次のように未加工のボディにアクセスできます。

app.post('/', function(req, res) {
  // do something with req.rawBody
  // use req.body for the parsed body
});

編集:このメソッドとbodyParserは共存を拒否しているようですこれは、一方が他方よりも先にリクエストストリームを消費し、どちらかが2番目に起動しendないためnext()、呼び出しが行われず、アプリケーションがハングするためです。

最も簡単な解決策は、ConnectのJSONパーサーの57行目にあるbodyParserのソースを変更することです。これは、変更されたバージョンがどのように見えるかです。

var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function() {
  req.rawBody = buf;
  var first = buf.trim()[0];
  ...
});

次の場所にファイルがあります。

/node_modules/express/node_modules/connect/lib/middleware/json.js


これはできないようです。これらのコードを追加した場合、\ node_modules \ express \ node_modules \ connect \ lib \ Middleware \ urlencoded.jsのイベントは発生しません。req.on( "data")、req.on( "end")は起動されません
haitao_wu 2013

コードを追加した後、このコードを使用して投稿を処理しますapp.post( "/ ajax"、function(req、res){res.send( 'hello world、post');}); リクエストのコンテンツタイプがapplication / x-www-form-urlencodedの場合、サーバーは「hello world、post」に応答しません
haitao_wu 2013

私の場合、ファイルの場所が正しくありません。express(> 4.0.0)のnode_modulesに接続モジュールがありません。新しい場所がまだ見つかりません
Sam Vloeberghs 2014

ConnectはExpress4の依存関係ではないため、BodyParserモジュールは含まれていません。それでも必要な場合は、ここで見つけることができます
ヘキサシアニド2014

1
@hexacyanide回答を更新して、最新のボディパーサーミドルウェアへの参照を含めてください。モジュールには、raw-body-parserミドルウェアが含まれるようになりました。これは、生の体を取得する方法を探しているグーグルに役立ちます。
eAbi 2015

47

bodyParserのverifyコールバックを使用して、bodyParserでうまく機能するソリューションを入手しました。このコードでは、これを使用してコンテンツのsha1を取得し、生のボディも取得しています。

app.use(bodyParser.json({
    verify: function(req, res, buf, encoding) {

        // sha1 content
        var hash = crypto.createHash('sha1');
        hash.update(buf);
        req.hasha = hash.digest('hex');
        console.log("hash", req.hasha);

        // get rawBody        
        req.rawBody = buf.toString();
        console.log("rawBody", req.rawBody);

    }
}));

私はNode.jsとexpress.js(文字通り昨日開始しました!)を初めて使用するので、このソリューションに関するコメントを聞きたいと思います。


3
私はこのソリューションが本当に好きです。必要なのreq.rawBody = buf.toString();はそれだけで、verify機能が美しく機能したので、関数を含めて残りを削除しました。bodyParserのソースコードを変更する必要はありません!
グレッグ

+1ですが、私の問題は、このリクエストが以前に送信されたかどうかを確認するために非同期関数が必要なことです:/
Renato Gama

3
非常に素晴らしい。提案してもいいですかreq.rawBody = buf.toString(encoding);
shaharsol 2016

2
これはapplication/jsonリクエストのみをキャプチャします
Pavel Evstigneev 2016

35

この解決策は私のために働いた:

var rawBodySaver = function (req, res, buf, encoding) {
  if (buf && buf.length) {
    req.rawBody = buf.toString(encoding || 'utf8');
  }
}

app.use(bodyParser.json({ verify: rawBodySaver }));
app.use(bodyParser.urlencoded({ verify: rawBodySaver, extended: true }));
app.use(bodyParser.raw({ verify: rawBodySaver, type: '*/*' }));

req.on('data', function(chunk) { });チャンクされたリクエスト本文で機能しないソリューションを使用する場合。


これにより、リクエストのさまざまな部分で受信データのすべての主要なシナリオが処理されました。
TWright 2016年

2
ShopifyアプリのWebhookのhmacを確認しようとしましたが、これでうまくいきました。私はこの例に大まかに従いました:gist.github.com/andjosh/5c4f0244914adfd312e4
チャドジョンソン

29

json、urlencodedなどもサポートしようとしている場合はbodyParserで正しく再生されないため、他の回答には注意してください。bodyParserで機能させるには、ハンドラーを条件付けして、Content-Typeヘッダーにのみ登録する必要があります。 bodyParser自体と同じように気にします。

リクエストの未加工の本文コンテンツを取得するには、次の操作Content-Type: "text/plain"req.rawBody実行できます。

app.use(function(req, res, next) {
  var contentType = req.headers['content-type'] || ''
    , mime = contentType.split(';')[0];

  if (mime != 'text/plain') {
    return next();
  }

  var data = '';
  req.setEncoding('utf8');
  req.on('data', function(chunk) {
    data += chunk;
  });
  req.on('end', function() {
    req.rawBody = data;
    next();
  });
});

3
+1。上記の解決策の1つを試しましたが、GETとjsonの投稿がすべて失敗していました。上記の解決策は技術的には正しい質問ですが、複数の形式のデータを使用してより多様なリクエストを処理する場合は、これが必要になります。

ここのデータは何ですか?UIから送信する変数ですか?
Saras Arya 2015年

app.use(bodyParser.urlencoded({limit: '80mb', extended: true})); app.use(bodyParser.json({limit: '80mb'})); app.use(bodyParser.raw({type: 'application/octet-stream'})) これも可能です。
SoumyaKanti20年

15

これは、上記のヘキサシアニドの答えのバリエーションです。このミドルウェアは「data」イベントも処理しますが、「next」を呼び出す前にデータが消費されるのを待ちません。このようにして、このミドルウェアとbodyParserの両方が共存し、ストリームを並行して消費する可能性があります。

app.use(function(req, res, next) {
  req.rawBody = '';
  req.setEncoding('utf8');

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  next();
});
app.use(express.bodyParser());


2
これは、早期に切断される長いボディでは機能しないようです。
Adam Lockhart 2014

完璧に働いて、私を救った。ありがとうございました。
hakazvaka 2016年

これは大きなファイルでも機能することを確認しています。1.5MBのテキストファイルを送ってみましたが、データ全体が正しく受信されました。ありがとう
ATOzTOA 2016

@ AdamLockhart-カットされたリクエストのサイズはどれくらいでしたか?
upTheCreek 2016年

@UpTheCreek、しばらく経ちました。わからない。私の最新のものはこのスニペットを使用していませんが、他の人が問題を報告しない場合、それは修正されたバグである可能性があります。
Adam Lockhart

-1

body-parserを使用します。ボディを次のように解析します。

app.use(bodyParser.text());

app.use(bodyParser.urlencoded());

app.use(bodyParser.raw());

app.use(bodyParser.json());

すなわち。生のテキストファイルを取得することになっている場合は、を実行し.text()ます。

それがbody-parserが現在サポートしているものです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.