Mojolicious路由(十)

一、内省

命令Mojolicious:: command::routes可以在命令行中使用,列出所有可用的路由以及名称和底层的正则表达式。

$ ./myapp.pl routes -v
/foo/:name  ....  POST  fooname  ^/foo/([^/.]+)/?(?:\.([^/]+))?$
/bar        ..U.  *     bar      ^/bar
  +/baz     ...W  GET   baz      ^/baz/?(?:\.([^/]+))?$
/yada       ....  *     yada     ^/yada/?(?:\.([^/]+))?$

二、under

要与多个嵌套路由共享代码,可以使用Mojolicious:: routes::Route中的“under”,因为与普通的嵌套路由不同,用它生成的路由有自己的中间目的地,当它们匹配时,会导致额外的调度周期。

# /foo     -> undef
# /foo/bar -> {controller => 'foo', action => 'baz'}
#             {controller => 'foo', action => 'bar'}
my $foo = $r->under('/foo')->to('foo#baz');
$foo->get('/bar')->to('#bar');

这个目的地的实际操作代码需要返回一个真值,否则分派链将被破坏,这可能是一个非常强大的身份验证工具。

# /blackjack -> {cb => sub {...}}
#               {controller => 'hideout', action => 'blackjack'}
my $auth = $r->under('/' => sub ($c) {
 
  # Authenticated
  return 1 if $c->req->headers->header('X-Bender');
 
  # Not authenticated
  $c->render(text => "You're not Bender.", status => 401);
  return undef;
});
$auth->get('/blackjack')->to('hideout#blackjack');

中断的分派链可以通过在Mojolicious::Controller中调用“continue”来继续,例如,这允许非阻塞操作在到达下一个分派周期之前完成。

my $maybe = $r->under('/maybe' => sub ($c) {
 
  # Wait 3 seconds and then give visitors a 50% chance to continue
  Mojo::IOLoop->timer(3 => sub {
 
    # Loser
    return $c->render(text => 'No luck.') unless int rand 2;
 
    # Winner
    $c->continue;
  });
 
  return undef;
});
$maybe->get('/')->to('maybe#winner');

在路由匹配时,每个目的地都只是存储点的快照,并且只有format值被所有目的地共享。为了获得更大的功能,我们可以在Mojolicious::Controller中使用“match”来内省前面和后面的目的地。

# Action of the fourth dispatch cycle
my $action = $c->match->stack->[3]{action};

标签