javascript 从 express/nodejs 中的路由特定中间件链中退出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17232239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
exit from chain of route specific middleware in express/ nodejs
提问by bguiz
I have a chain of "route specific middleware" for this route, like so:
我有一条这条路线的“路线特定中间件”链,如下所示:
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]
are the middleware specific to the route /some/path
.
[mw1, mw2]
是特定于路由的中间件/some/path
。
This is different from server-wide middleware like this:
这与像这样的服务器范围的中间件不同:
server.use(mw1);
server.use(mw2);
Where it applies to all routes defined.
它适用于所有定义的路由。
Now my issue is that I want to exit from the chain. I.e. if success
is false in mw1
, I do not wish for mw2
to be called. If success
is false in mw2
, I do not without for the route function to be called. Presently, both mw1
and mw2
appear to be getting called whether or not next()
is called - and I do not know why.
现在我的问题是我想退出链。即如果在 中success
为假mw1
,我不希望mw2
被调用。如果在 中success
为 false mw2
,则需要调用路由函数。目前,无论是否被调用,mw1
和mw2
似乎都被next()
调用了——我不知道为什么。
How can I go about doing this?
我该怎么做呢?
采纳答案by bguiz
A little more tinkering yielded the answer:
稍微修修补补得到了答案:
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
});
The trick was send a response: resp.send(406, 'Invalid because of this');
诀窍是发送响应: resp.send(406, 'Invalid because of this');
Just prior to destroying the connection: req.connection.destroy();
就在破坏连接之前: req.connection.destroy();
In fact not destroying the connection, I found to also work, in the general case.
事实上,在一般情况下,我发现并没有破坏连接,也可以工作。
(But was required in my specific case, and is out of the scope of this question.)
(但在我的特定情况下是必需的,并且超出了这个问题的范围。)
If the response has already been sent, then express does not automatically call next()
for you, as it appeared to do otherwise.
如果已经发送了响应,则 express 不会自动呼叫next()
您,因为它似乎没有这样做。
回答by laconbass
You can call next( 'route' )
, as said on the express api reference, application routing
section:
您可以调用next( 'route' )
,如express api 参考中所述,application routing
部分:
Multiple callbacks may be given, all are treated equally, and behave just like middleware, with the one exception that these callbacks may invoke
next('route')
to bypass the remaining route callback(s).
可以给出多个回调,所有回调都被平等对待,并且行为就像中间件一样,除了这些回调可以调用
next('route')
以绕过剩余的路由回调的一个例外。
Example
例子
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();
}
回答by Plato
I was under the impression that if you neither call next()
nor send a response in a route handling function, express just hangs. Also FWIW I haven't used an array, mine looks like server.post('/some/path', mw1, mw2, function(req, resp) {...
我的印象是,如果您next()
在路由处理函数中既不调用也不发送响应,则 express 就会挂起。另外 FWIW 我没有使用过数组,我的看起来像server.post('/some/path', mw1, mw2, function(req, resp) {...
Anyway. One alternative might be to restructure your code so you only have a single handling function. Do you have a good reason for mw1 and mw2 being middleware instead of regular async functions your handler calls?
反正。一种替代方法可能是重构您的代码,以便您只有一个处理函数。您是否有充分的理由将 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);