2017-08-14 75 views
0

Mojolicious + Hypnotoad。代理重新路由到控制器

我希望我的控制器重新路由请求的剩余部分,以便我不必在主脚本级别声明所有路由。

因此,例如,'/ foo/bar/baz'应该路由到控制器'FOO',控制器'FOO'将决定自己内部的'bar/baz'的路由。

主要脚本:

package MyApp; 
use Mojo::Base 'Mojolicious'; 
use Mojolicious::Plugin::Config; 

sub startup { 
    my $self = shift; 

    $self->moniker('MyApp'); 
    $self->plugin('Config'); 

    my $r = $self->routes; 
    $r->any('/foo/*remainder')->to('FOO#rerouter')->name('TEST_NAME'); 
} 

我试过的一种方式,通过动态地添加路由,但在运行了很多次,显示不一致 - 可能是通过竞争条件或因素导致的:

package MyApp::Controller::FOO; 
use Mojo::Base 'Mojolicious::Controller'; 

sub rerouter { 
    my $self = shift; 

    my $r = Mojolicious::Routes->new; 
    $r->get('bar/:baz')->to('myInternalControllerAction'); 

    my $current_route = $self->current_route; # 'TEST_NAME' 

    $self->app->routes->find($current_route)->add_child($r); 
} 

sub myInternalControllerAction { #stuff } 

这似乎与其他答案一致:

“路由器是动态的,直到第一个请求RVED, 之后,路由器不能改变路线”

https://stackoverflow.com/a/22291864/2304437

即使是没有工作,虽然,执行通过动态添加重新输入一个不同的行动之前将退出控制器FOO路线(一个或多个)。

的另一种方式,我可以做到这一点仅仅是在控制器的“重新路由”创建调度表,因为我有机会获得请求的其余部分反正:

sub rerouter { 
    my $self = shift; 
    my $remainder = $self->stash->{remainder}; 
    # ... 
} 

但后来我失去Mojolicious调度员的好处 - 我将不得不自己解析剩余的请求URL /路径。感觉脏。 钩子在这里也不合适。

我该如何优雅地让控制器路由自己的子部分?

回答

0

我解决了这个如下:

use MyApp::Controller::FOO; 
my $r = $self->routes; 
my $r_root = $r->under('/' => sub { return 1; }); 

my $baz = $r_root->under('/baz' => sub { return 1; }); 
$baz->add_child($MyApp::Controller::FOO::routes); 

然后在模块中:

package MyApp::Controller::FOO; 
use Mojo::Base 'Mojolicious::Controller'; 

our $routes = Mojolicious::Routes->new; 
my $r = $routes->under('/')->to('FOO#bar'); 

sub bar { ... } 

也许不是优雅,因为它可能是,但它的作品对我非常好。