控制快递/连接中间件的顺序

Ale*_*hov 5 node.js express connect.js

我正在尝试添加应该阻止访问部分网站的身份验证中间件:

app = express()
    .get('/api/test', function (req, res) { ... })
    .use('/api', function (req, res, next) {
        if (req.param('key')) {
            next();
        } else {
            res.json(401, {
                message : 'Authentication failed'
            });
            res.end();
        }
    })
    .get('/api/data', function (req, res) { ... });
Run Code Online (Sandbox Code Playgroud)

我期望调用/ api/data将首先由密钥检查器处理,然后(如果成功)由/ api/data处理程序处理.而是首先由'/ api/data'处理请求.

似乎检查器适用于/ api/something_that_does_not_exist,但不适用于/ api/something_that_exist.

也许我错过了快递/连接文档中的内容?

更新我已经跟踪了这一事实,即第一个get/post调用初始化路由器中间件,因此首先执行它.

rob*_*lep 8

声明路由后,Express会router在设置应用程序时将中间件插入中间件堆栈.

在您的情况下,因为您.get('/api/test', ...)在插入密钥检查中间件之前插入,路由器中间件将被插入并优先使用(也适用于/api/data您稍后声明的路由),并且永远不会调用您的密钥检查器.

这有两个解决方案:

// separate middleware, used for all routes that need checking
var keyChecker = function(req, res, next) {
  ...
};
app.get('/api/test', function(req, res) { ... });
app.get('/api/data', keyChecker, function(req, res) { ... });

// or, as an alternative, create a 'catch-all' route between the routes that don't
// need to be checked, and the ones that should; this will also match non-existing
// routes (like '/api/foobar'), which might or might not be an issue;
app.get('/api/test', function(req, res) { ... });
app.all('/api/*', function(req, res, next) { // 'all' means 'all methods'
  // keychecker code
});
app.get('/api/data', function(req, res) { ... });
Run Code Online (Sandbox Code Playgroud)

第三种解决方案可能是/api/test在密钥检查中明确检查中间件本身(req.path === '/api/test'),next()如果匹配则调用.