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

时间:2013-04-12 13:48:30

标签: 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) { ... });

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

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

也许我错过了express / connect文档中的内容?

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

1 个答案:

答案 0 :(得分:6)

一旦声明了路由,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) { ... });

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