Skip to content

Commit

Permalink
fixed a few more inconsistencies in Mojolicious::Routes::Match
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed May 11, 2013
1 parent 917a4d4 commit 037f2eb
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 277 deletions.
2 changes: 1 addition & 1 deletion Changes
@@ -1,5 +1,5 @@

4.0 2013-05-11
4.0 2013-05-12
- Code name "Top Hat", this is a major release.
- Added simple JSON serialization support to Mojo::Transaction::WebSocket.
- Added json event to Mojo::Transaction::WebSocket.
Expand Down
1 change: 0 additions & 1 deletion lib/Mojo/Util.pm
Expand Up @@ -45,7 +45,6 @@ our @EXPORT_OK = (
);

sub b64_decode { decode_base64($_[0]) }

sub b64_encode { encode_base64($_[0], $_[1]) }

sub camelize {
Expand Down
5 changes: 2 additions & 3 deletions lib/Mojolicious/Controller.pm
Expand Up @@ -15,9 +15,8 @@ use Scalar::Util ();
use Time::HiRes ();

has app => sub { Mojolicious->new };
has match => sub {
Mojolicious::Routes::Match->new(GET => '/')->root(shift->app->routes);
};
has match =>
sub { Mojolicious::Routes::Match->new(root => shift->app->routes) };
has tx => sub { Mojo::Transaction::HTTP->new };

# Reserved stash values
Expand Down
24 changes: 13 additions & 11 deletions lib/Mojolicious/Routes.pm
Expand Up @@ -27,31 +27,33 @@ sub auto_render {
sub dispatch {
my ($self, $c) = @_;

# Prepare path
# Path (partial path gets priority)
my $req = $c->req;
my $path = $c->stash->{path};
if (defined $path) { $path = "/$path" if $path !~ m!^/! }
else { $path = $req->url->path->to_route }

# Prepare match
my $method = $req->method;
my $websocket = $c->tx->is_websocket ? 1 : 0;
my $m = Mojolicious::Routes::Match->new($method => $path, $websocket);
$c->match($m->root($self));
# Method (HEAD will be treated as GET)
my $method = uc $req->method;
$method = 'GET' if $method eq 'HEAD';

# Check cache
my $cache = $self->cache;
my $cache = $self->cache;
my $websocket = $c->tx->is_websocket ? 1 : 0;
my $match = Mojolicious::Routes::Match->new(root => $self);
$c->match($match);
if ($cache && (my $cached = $cache->get("$method:$path:$websocket"))) {
$m->endpoint($cached->{endpoint})->stack($cached->{stack});
$match->endpoint($cached->{endpoint})->stack($cached->{stack});
}

# Check routes
else {
$m->match($c);
my $options = {method => $method, path => $path, websocket => $websocket};
$match->match($c => $options);

# Cache routes without conditions
if ($cache && (my $endpoint = $m->endpoint)) {
my $result = {endpoint => $endpoint, stack => $m->stack};
if ($cache && (my $endpoint = $match->endpoint)) {
my $result = {endpoint => $endpoint, stack => $match->stack};
$cache->set("$method:$path:$websocket" => $result)
unless $endpoint->has_conditions;
}
Expand Down
81 changes: 33 additions & 48 deletions lib/Mojolicious/Routes/Match.pm
Expand Up @@ -4,14 +4,7 @@ use Mojo::Base -base;
has [qw(endpoint root)];
has stack => sub { [] };

sub new {
my $self = shift->SUPER::new;
$self->{method} = uc shift;
$self->{$_} = shift for qw(path websocket);
return $self;
}

sub match { $_[0]->_match($_[0]->root, $_[1]) }
sub match { $_[0]->_match($_[0]->root, $_[1], $_[2]) }

sub path_for {
my $self = shift;
Expand Down Expand Up @@ -70,20 +63,19 @@ sub path_for {
}

sub _match {
my ($self, $r, $c) = @_;
my ($self, $r, $c, $options) = @_;

# Pattern
my $path = $self->{path};
my $path = $options->{path};
my $pattern = $r->pattern;
return
unless my $captures = $pattern->match_partial(\$path, $r->is_endpoint);
local $self->{path} = $path;
local $options->{path} = $path;
$captures = $self->{captures} = {%{$self->{captures} || {}}, %$captures};

# Method (HEAD will be treated as GET)
# Method
if (my $methods = $r->via) {
my $method = $self->{method} eq 'HEAD' ? 'GET' : $self->{method};
return unless grep { $_ eq $method } @$methods;
return unless grep { $_ eq $options->{method} } @$methods;
}

# Conditions
Expand All @@ -96,7 +88,7 @@ sub _match {
}

# WebSocket
return if $r->is_websocket && !$self->{websocket};
return if $r->is_websocket && !$options->{websocket};

# Partial
my $empty = !length $path || $path eq '/';
Expand All @@ -117,7 +109,7 @@ sub _match {
# Match children
my $snapshot = [@{$self->stack}];
for my $child (@{$r->children}) {
$self->_match($child, $c);
$self->_match($child, $c, $options);

# Endpoint found
return if $self->endpoint;
Expand All @@ -142,15 +134,15 @@ Mojolicious::Routes::Match - Routes visitor
# Routes
my $r = Mojolicious::Routes->new;
$r->get('/foo')->to(action => 'foo');
$r->put('/bar')->to(action => 'bar');
$r->get('/foo')->to('test#foo');
$r->put('/bar')->to('test#bar');
# Match
my $c = Mojolicious::Controller->new;
my $m = Mojolicious::Routes::Match->new(PUT => '/bar');
$m->root($r)->match($c);
say $m->stack->[0]{controller};
say $m->stack->[0]{action};
my $match = Mojolicious::Routes::Match->new(root => $r);
$match->match($c => {method => 'PUT', path => '/bar'});
say $match->stack->[0]{controller};
say $match->stack->[0]{action};
=head1 DESCRIPTION
Expand All @@ -163,22 +155,22 @@ L<Mojolicious::Routes::Match> implements the following attributes.
=head2 endpoint
my $endpoint = $m->endpoint;
$m = $m->endpoint(Mojolicious::Routes::Route->new);
my $endpoint = $match->endpoint;
$match = $match->endpoint(Mojolicious::Routes::Route->new);
The route endpoint that actually matched.
=head2 root
my $root = $m->root;
$m = $m->root(Mojolicious::Routes->new);
my $root = $match->root;
$match = $match->root(Mojolicious::Routes->new);
The root of the route tree.
=head2 stack
my $stack = $m->stack;
$m = $m->stack([{foo => 'bar'}]);
my $stack = $match->stack;
$match = $match->stack([{foo => 'bar'}]);
Captured parameters with nesting history.
Expand All @@ -187,33 +179,26 @@ Captured parameters with nesting history.
L<Mojolicious::Routes::Match> inherits all methods from L<Mojo::Base> and
implements the following new ones.
=head2 new
my $m = Mojolicious::Routes::Match->new(GET => '/foo');
my $m = Mojolicious::Routes::Match->new(GET => '/foo', $ws);
Construct a new L<Mojolicious::Routes::Match> object.
=head2 match
$m->match(Mojolicious::Controller->new);
$match->match(Mojolicious::Controller->new, {method => 'GET', path => '/'});
Match against C<root>.
=head2 path_for
my $path = $m->path_for;
my $path = $m->path_for(foo => 'bar');
my $path = $m->path_for({foo => 'bar'});
my $path = $m->path_for('named');
my $path = $m->path_for('named', foo => 'bar');
my $path = $m->path_for('named', {foo => 'bar'});
my ($path, $ws) = $m->path_for;
my ($path, $ws) = $m->path_for(foo => 'bar');
my ($path, $ws) = $m->path_for({foo => 'bar'});
my ($path, $ws) = $m->path_for('named');
my ($path, $ws) = $m->path_for('named', foo => 'bar');
my ($path, $ws) = $m->path_for('named', {foo => 'bar'});
my $path = $match->path_for;
my $path = $match->path_for(foo => 'bar');
my $path = $match->path_for({foo => 'bar'});
my $path = $match->path_for('named');
my $path = $match->path_for('named', foo => 'bar');
my $path = $match->path_for('named', {foo => 'bar'});
my ($path, $ws) = $match->path_for;
my ($path, $ws) = $match->path_for(foo => 'bar');
my ($path, $ws) = $match->path_for({foo => 'bar'});
my ($path, $ws) = $match->path_for('named');
my ($path, $ws) = $match->path_for('named', foo => 'bar');
my ($path, $ws) = $match->path_for('named', {foo => 'bar'});
Render matching route with parameters into path.
Expand Down

0 comments on commit 037f2eb

Please sign in to comment.