Mojolicious路由中under方法无法捕获后续路由参数的解决方案咨询
解决Mojolicious Under路由无法捕获子路由参数的问题
我完全懂你的困扰——不想给每个路由都重复写under,却碰到了参数捕获不一致的问题。先给你拆解清楚为什么两种情况会有差异,再给你一个通用的解决方案。
问题根源
你遇到的差异本质是Mojolicious路由的层级匹配特性:
- 第一种路由写法:
under('/api')->get('/users/:user_id'),under只负责匹配/api前缀,:user_id是子路由的占位符。当Permission#allow执行时,当前路由层级的mojo.captures只包含under本身的参数(这里没有参数),子路由的参数还没合并到当前stash中。 - 第二种路由写法:
under('/api/other/users/:user_id'),:user_id是under路由自带的占位符,匹配时直接捕获到参数,所以allow能正常拿到。
通用解决方案:获取全路由栈的参数
你完全不需要为20个路由单独定义under,只需要在Permission#allow里通过$c->match->stack获取所有路由层级的捕获参数即可。这个栈包含了从根路由到当前子路由的所有匹配层级,每个层级都存着对应的captures。
修改你的Permission控制器:
package Test::Controller::Permission; use Mojo::Base 'Mojolicious::Controller', -signatures; sub allow ($c) { # 合并所有路由层级的捕获参数 my %all_captures; foreach my $layer (@{$c->match->stack}) { %all_captures = (%all_captures, %{$layer->{captures} // {}}); } # 现在可以拿到所有参数,包括子路由里的user_id print $c->dumper(\%all_captures); # 直接用$all_captures{user_id}就能获取目标参数 # 如果想让后续控制器也能通过$c->param直接拿到参数,合并到stash里即可 $c->stash(%all_captures); return 1; } 1;
这样不管user_id是在under路由还是子路由里定义的,allow都能捕获到参数,你只需要定义一次under('/api')就能覆盖所有子路由的权限检查。
补充说明
- 第一种情况里
$c->param('user_id')失效,是因为param默认只会从当前层级stash的mojo.captures、查询参数、POST参数里查找,子路由的参数此时还没在当前层级的stash中。但通过match->stack就能拿到所有已匹配的参数,比解析URL路径可靠得多。
内容的提问来源于stack exchange,提问作者Peter Staab
相关产品推荐
相关产品推荐

