Koa-router 在到达路由之前获取已解析的参数
Koa-router getting parsed params before hitting route
我在上面使用 koa2 和 koa-router 以及 sequelize。我希望能够根据用户在数据库中的角色来控制用户访问权限,到目前为止,它一直在工作。我做了自己的 RBAC 实现,但遇到了一些问题。
考虑到端点可以执行任何操作(如插入新项目等),如果用户无权访问,我需要在命中任何端点之前退出执行。这很有意义,我意识到我可能会使用 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),我在其中指定命名路由、它们各自的续集模型名称以及路由存在的规则。 (例如,什么角色,如果所有者能够访问他们自己的资源......)我通过路由参数计算请求者是否拥有资源(例如资源 ID 是 ctx.params.id
)。然而,在这个实现中,params 似乎没有被解析。我认为我必须在 koa-router 执行之前手动解析参数是不对的。是否有人能够基于此确定更好的方法来解决 ctx.params
未填充实际命名参数的问题?
编辑:I also created a GitHub issue for this,考虑到在我看来似乎发生了一些有趣的事情。
所以如果你看 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);
它所做的是,对于您拥有的每个路由函数,它都会添加自己的捕获层来生成参数
现在这确实有意义,因为您可以为相同的 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), {})
我在上面使用 koa2 和 koa-router 以及 sequelize。我希望能够根据用户在数据库中的角色来控制用户访问权限,到目前为止,它一直在工作。我做了自己的 RBAC 实现,但遇到了一些问题。
考虑到端点可以执行任何操作(如插入新项目等),如果用户无权访问,我需要在命中任何端点之前退出执行。这很有意义,我意识到我可能会使用 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),我在其中指定命名路由、它们各自的续集模型名称以及路由存在的规则。 (例如,什么角色,如果所有者能够访问他们自己的资源......)我通过路由参数计算请求者是否拥有资源(例如资源 ID 是 ctx.params.id
)。然而,在这个实现中,params 似乎没有被解析。我认为我必须在 koa-router 执行之前手动解析参数是不对的。是否有人能够基于此确定更好的方法来解决 ctx.params
未填充实际命名参数的问题?
编辑:I also created a GitHub issue for this,考虑到在我看来似乎发生了一些有趣的事情。
所以如果你看 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);
它所做的是,对于您拥有的每个路由函数,它都会添加自己的捕获层来生成参数
现在这确实有意义,因为您可以为相同的 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), {})