从express / nodejs中的路由链特定中间件退出

时间:2013-06-21 09:48:59

标签: javascript node.js express connect middleware

我为这条路线设置了一系列“特定于路线的中间件”,如下所示:

    var express = require('express');
    var server = express();
    var mw1 = function(req, resp, next) {
        //do stuff
        if (success) {
            next();
        } else {
            req.connection.destroy(); //without calling next()
        }
    };
    var mw2 = function(req, resp, next) {
        //do stuff
        if (success) {
            next();
        } else {
            req.connection.destroy(); //without calling next()
        }
    };
    server.post('/some/path', [mw1, mw2], function(req, resp) {
        //write response
    });

[mw1, mw2]是特定于路由/some/path的中间件。

这与服务器范围的中间件不同,如下所示:

    server.use(mw1);
    server.use(mw2);

适用于所有定义的路线。

现在我的问题是我想退出链。即如果successmw1为假,我不希望调用mw2。如果successmw2为假,我不会因为调用路由函数而没有。目前,无论mw1是否被调用,mw2next()似乎都会被调用 - 我不知道为什么。

我该怎么做呢?

3 个答案:

答案 0 :(得分:17)

the express api reference, application routing section所述,您可以致电next( 'route' )

  

可以给出多个回调,所有回调都是平等的,并且表现得很好   就像中间件一样,这些回调可能有一个例外   调用next('route')以绕过剩余的路由回调。

实施例

var express = require('express')
  , app = express()
;

// keep an eye on the function names
app.post( '/some/path', middleware1, middleware2, function route1( req, res, next ) {
      // write response
});
app.all( '*', function route2( req, res, next ) {
    // do something like handle a 404 request
});
app.use(function errorHandler( err, req, res, next ) {
    // handle error
});

function middleware1( req, res, next ) {
    // ...
    if ( !success ) {
        // bypasses middleware2 and route1, route2 will be called
        return next( 'route' );
    }
    // calls middleware2
    next();
}
// intentionally similar to middleware1 to keep things clear
function middleware2( req, res, next ) {
    if ( !success ) {
      // bypasses route1 and route2
      // errorHandler will be called with the error
      return next( Error( 'middleware 2 failed' ) );
    }
    // calls route1
    next();
}

答案 1 :(得分:1)

我的印象是,如果你既没有呼叫next()也没有在路由处理功能中发送响应,那么表达只是挂起。还有FWIW我还没有使用过数组,我看起来像server.post('/some/path', mw1, mw2, function(req, resp) {...

反正。一种替代方法可能是重构代码,这样您只需要一个处理函数。你有充分的理由认为mw1和mw2是中间件而不是处理程序调用的常规异步函数吗?

var express = require('express');
var server = express();

var mw1 = function(req, res, callback) {
  // do stuff with req/res if necessary but don't send a response
  if (success) {
    callback(null);
  } else {
    callback('Error');
  }
};

var mw2 = function(req, res, callback) {
  //do other stuff but don't send a response
  if (success) {
    callback(null);
  } else {
    callback('Error');
  }
};

function mwBoth(req, res){
  mw1(req, res, function(err){
    if(err){ return res.send(500) };
    mw2(req, res, function(err){
      if(err){ return res.send(500) };
      // neither had an error
      res.redirect('/some/other/path');
    });
  });
};

server.post('/some/path', mwBoth);

答案 2 :(得分:1)

稍微修修一下得到了答案:

var express = require('express');
var server = express();
var mw1 = function(req, resp, next) {
  //do stuff
  if (success) {
    next();
  } else {
    resp.send(406, 'Invalid because of this');
    req.connection.destroy(); //without calling next()
  }
};
var mw2 = function(req, resp, next) {
  //do stuff
  if (success) {
    next();
  } else {
    resp.send(406, 'Invalid because of that');
    req.connection.destroy(); //without calling next()
  }
};
server.post('/some/path', [mw1, mw2], function(req, resp) {
  //write response
});

诀窍是发送回复:resp.send(406, 'Invalid because of this');

在销毁连接之前:req.connection.destroy();

事实上,在一般情况下,我发现也没有破坏连接。

(但在我的具体情况下是必需的,并且超出了这个问题的范围。)

如果已经发送了回复,则快递不会自动为您拨打next(),因为它似乎没有。