首页 文章

Koa路由器在击中路线之前得到解析的params

提问于
浏览
2

我正在使用koa2和koa-router以及sequelize . 我希望能够根据他们在数据库中的角色来控制用户访问,到目前为止它一直在工作 . 我做了自己的RBAC实现,但是我遇到了一些麻烦 .

如果用户没有访问权限,我需要在任何 endpoints 被命中之前退出执行,考虑到 endpoints 可以执行任何操作(如插入新项目等) . 这很有道理,我意识到我可能会使用Sequelize进行交易,但我发现这会增加更多的开销,截止日期即将结束 .

到目前为止,我的实现看起来有点像:

// initialize.js

initalizeRoutes()
initializeServerMiddleware()

服务器中间件在路由后注册 .

// function initializeRoutes
app.router = require('koa-router')

app.router.use('*', access_control(app))

require('./routes_init')

routes_init只运行一个递归解析文件夹并导入所有中间件定义的函数 .

// function initializeServerMiddleware
// blah blah bunch of middleware
app.server.use(app.router.routes()).use(app.router.allowedMethods())

这只是普通的koa-router .

但是,问题出现在access_control中 .

我有一个文件(access_control_definitions.js),我在其中指定命名路由,它们各自的sequelize模型名称,以及路径存在哪些规则 . (例如,如果所有者能够访问他们自己的资源,则是什么角色...)我计算请求者是否通过路由参数拥有资源(例如,资源ID是 ctx.params.id ) . 然而,在这个实现中,params认为我必须在koa-router之前手动解析params . 是否有人能够找到一种更好的方法来解决 ctx.params 没有填充实际的命名参数?

编辑:I also created a GitHub issue for this,考虑到我似乎有一些有趣的业务正在进行中 .

1 回答

  • 4

    所以如果你看 router.js

    layerChain = matchedLayers.reduce(function(memo, layer) {
      memo.push(function(ctx, next) {
        ctx.captures = layer.captures(path, ctx.captures);
        ctx.params = layer.params(path, ctx.captures, ctx.params);
        ctx.routerName = layer.name;
        return next();
      });
      return memo.concat(layer.stack);
    }, []);
    
    return compose(layerChain)(ctx, next);
    

    它的作用是,对于你拥有的每个路径函数,它都会添加自己的捕获层来生成参数

    LayerMap

    现在这确实有意义,因为您可以为具有不同参数的相同URL提供两个中间件

    router.use('/abc/:did', (ctx, next) => {
        // ctx.router available
        console.log('my request came here too', ctx.params.did)
        if (next)
            next();
    });
    
    router.get('/abc/:id', (ctx, next) => {
        console.log('my request came here', ctx.params.id)
    });
    

    现在对于第一个处理程序,参数 id 没有意义,对于第二个参数 did 不知道它是一个错误

    既然你已经找到了解决方法

    const fromRouteId = pathToRegexp(ctx._matchedRoute).exec(ctx.captures[0])
    

    你应该使用相同的 . 或者更好的一个

    var lastMatch = ctx.matched[ctx.matched.length-1];
    params = lastMatch.params(ctx.originalUrl, lastMatch.captures(ctx.originalUrl), {})
    

相关问题