1

要求されたパスに基づいて特定のミドルウェア関数のみを呼び出すことにより、Express/Connect ミドルウェア パイプラインを短縮しようとしています。

ただし、次の場合は失敗します。

_cookieParser(req, res, function(err) {
     if(err) return next(err);
     _session(req, res, function(err) {
         if(err) return next(err);
         _csrf(req, res, function(err) {
              if(err) return next(err);
              loadUserFromSession(req, res, function(err) {
                   if(err) return next(err);
                   if(req.method == "POST") {
                       _bodyParser(req, res, next);
                   } else {
                       next();
                   }
              });
          });
     });
});

しかし、これはうまくいきます:

_cookieParser(req, res, function(err) {
     if(err) return next(err);
     _session(req, res, function(err) {
         if(err) return next(err);
         _csrf(req, res, function(err) {
              if(err) return next(err);
              _bodyParser(req, res, function(err) {
                   if(err) return next(err);
                   loadUserFromSession(req, res, next);
              });
          });
     });
});

loadUserFromSession の場所:

function loadUserFromSession(req, res, next) {
    if(req.session && req.session.userId) {
        userFunctions.getUserById(req.session.userId, function(err, user) {
            if(err) return next(err);
            if(user) {
                req.user = user;
                return next();
            } else {
                req.session.destroy();
                return next(new Error('Unauthenticated'));
            }
        });
    } else {
        return next(new Error('Unauthenticated'));
    }        
};

loadUserFromSession() の後に bodyParser() を呼び出せないのはなぜですか?

編集

失敗/予期しない結果の詳細が不足していて申し訳ありません。

loadUserFromSession() の後に bodyParser() または json() (POST コンテンツが json であるため) を配置すると、呼び出しが json() 内に返されることはありません。res.on('data') または res.on('end') のいずれかのノード インスペクタにブレークポイントを配置すると、どちらもトリップされません。

json ミドルウェアのソースは次のとおりです。

exports = module.exports = function(options){
  var options = options || {}
    , strict = options.strict !== false;

  var limit = options.limit
    ? _limit(options.limit)
    : noop;

  return function json(req, res, next) {
    if (req._body) return next();
    req.body = req.body || {};

    if (!utils.hasBody(req)) return next();

    // check Content-Type
    if ('application/json' != utils.mime(req)) return next();

    // flag as parsed
    req._body = true;

    // parse
    limit(req, res, function(err){
      if (err) return next(err);
      var buf = '';
      req.setEncoding('utf8');
      req.on('data', function(chunk){ 
        buf += chunk                  <==BREAKPOINT NEVER GETS CALLED
      });
      req.on('end', function(){
        var first = buf.trim()[0];    <==BREAKPOINT NEVER GETS CALLED

        if (0 == buf.length) {
          return next(400, 'invalid json, empty body');
        }

        if (strict && '{' != first && '[' != first) return next(400, 'invalid json');
        try {
          req.body = JSON.parse(buf, options.reviver);
          next();
        } catch (err){
          err.body = buf;
          err.status = 400;
          next(err);
        }
      });
    });
  }
};
4

1 に答える 1

0

OK、特定の回答ではなく、このアドバイス/コード レビューを検討してください。

まず、私の推測では、以下が問題を解決し、混乱を解消することを理解していると思いますが、上記の 2 番目の例が、分離されたスニペットが与えられた最初の例と異なる動作をする理由を正確に言うことはできませんが、この情報に基づいていくつかの実験を行ってください。要求が与えられると、一連のイベント ( dataendなど) が 1 回だけ発生します。起動時にリスナーがアタッチされていない場合、そのリスナーは呼び出されません。起動後にリスナーが接続されると、呼び出されることはありません。bodyParserには、同じリクエスト本文を複数回再解析しようとすることを避けるためのコードがあります (必要なイベントが発生せず、リクエストに応答せずにコードがハングするため) 。

SO、あなたのアプリでは、app.use(express.bodyParser())上記のカスタムの前にミドルウェアが呼び出されて実行されていると思われます。したがって、ファイルアップロードのセキュリティに関する質問にも対処する私の提案は次のとおりです。

bodyParser例のようにグローバルにインストールしないでください: app.use(express.bodyParser()). このコードは初日のサンプル アプリには適していますが、運用サイトにはまったく不適切です。代わりに次のようにする必要があります。

app.post('/upload/some/file', express.bodyParser(), myUploadHandler);

そして、body パーサーを必要な場所だけに使用し、それ以外の場所には使用しないでください。奇妙でネストされたミドルウェアのスタックをさらに下に移動しないでください。接続に組み込まれたミドルウェア スタック設計を使用して、HARMONY で動作する必要な機能、セキュリティ、および効率性を得る明確な方法があります。一般に、さまざまなパスでさまざまなミドルウェア スタックを使用できること、およびエクスプレス/コネクトを構成して、パスごとに発生させたいことをうまく一致させることができることを理解してください。

于 2013-05-13T16:00:52.750 に答える