在express / nodejs中退出特定链路的中间件
我有一个这条路线的“路线特定中间件”链,就像这样:
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);
它适用于所有定义的路线。
现在我的问题是,我想退出链条。 也就是说,如果mw1
success
是错误的,我不希望mw1
被调用。 如果mw2
success
是错误的,我并不是没有路由function被调用。 目前, mw1
和mw1
似乎被调用是否调用next()
– 我不知道为什么。
我怎么能这样做?
您可以调用next( 'route' )
,如express API参考中所述, application routing
部分 :
可能会给出多个callback,所有处理都是平等的,并且像中间件一样行为,除了这些callback可能会调用
next('route')
来绕过剩余的路由callback。
例
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(); }
我的印象是,如果你既没有在路由处理函数中调用next()
也没有发送响应,那么expression就是挂起。 也FWIW我没有使用一个数组,我看起来像server.post('/some/path', mw1, mw2, function(req, resp) {...
无论如何。 一种替代scheme可能是重构你的代码,所以你只有一个处理函数。 mw1和mw2是否是中间件,而不是你的处理程序调用的常规asynchronous函数?
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);
多一点修补得出答案:
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();
其实并没有破坏这个联系,我发现在一般情况下也是有效的。
(但在我的具体情况下是必需的,超出了这个问题的范围。)
如果响应已经被发送,那么Express不会自动为你调用next()
,因为看起来不是这样。