5

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

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 调用初始化路由器中间件,因此它首先被执行。

4

1 回答 1

9

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

在您的情况下,因为您.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()如果匹配则调用。

于 2013-04-12T15:16:44.807 回答