From a54cb81807d5241c0ff401c6cb6e29d7f923fafd Mon Sep 17 00:00:00 2001 From: Sebastian Riedel Date: Fri, 3 Jun 2011 19:24:48 +0200 Subject: [PATCH] added experimental support for unquoted wildcard placeholders in Mojolicious::Routes::Pattern --- Changes | 2 ++ lib/Mojolicious/Guides/Routing.pod | 34 +++++++++++++++--------------- lib/Mojolicious/Lite.pm | 19 +---------------- lib/Mojolicious/Routes/Pattern.pm | 31 ++++++++++----------------- t/mojolicious/embedded_lite_app.t | 2 +- t/mojolicious/lite_app.t | 14 +++++++++++- t/mojolicious/pattern.t | 14 ++++++++---- t/mojolicious/routes.t | 14 +++++++++++- 8 files changed, 68 insertions(+), 62 deletions(-) diff --git a/Changes b/Changes index 43289d2614..0fd8bbff3f 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ This file documents the revision history for Perl extension Mojolicious. 1.42 2011-06-03 00:00:00 + - Added EXPERIMENTAL support for unquoted wildcard placeholders in + Mojolicious::Routes::Pattern. - Improved layout tests. - Improved documentation. diff --git a/lib/Mojolicious/Guides/Routing.pod b/lib/Mojolicious/Guides/Routing.pod index 7a5f59941e..a91526f241 100644 --- a/lib/Mojolicious/Guides/Routing.pod +++ b/lib/Mojolicious/Guides/Routing.pod @@ -108,9 +108,21 @@ surrounding text. /sebastian23hello -> /(:name)hello -> {name => 'sebastian23'} /sebastian 23hello -> /(:name)hello -> {name => 'sebastian 23'} +=head2 Wildcard Placeholders + +Wildcard placeholders are just like generic placeholders, but match +absolutely everything. + + /hello -> /*name/hello -> undef + /sebastian/23/hello -> /*name/hello -> {name => 'sebastian/23'} + /sebastian.23/hello -> /*name/hello -> {name => 'sebastian.23'} + /sebastian/hello -> /*name/hello -> {name => 'sebastian'} + /sebastian23/hello -> /*name/hello -> {name => 'sebastian23'} + /sebastian 23/hello -> /*name/hello -> {name => 'sebastian 23'} + =head2 Relaxed Placeholders -Relaxed placeholders are very similar to generic placeholders but always +Relaxed placeholders are similar to the two placeholders above, but always require brackets and match all characters except C. /hello -> /(.name)/hello -> undef @@ -120,18 +132,6 @@ require brackets and match all characters except C. /sebastian23/hello -> /(.name)/hello -> {name => 'sebastian23'} /sebastian 23/hello -> /(.name)/hello -> {name => 'sebastian 23'} -=head2 Wildcard Placeholders - -Wildcard placeholders are just like relaxed placeholders but match absolutely -everything. - - /hello -> /(*name)/hello -> undef - /sebastian/23/hello -> /(*name)/hello -> {name => 'sebastian/23'} - /sebastian.23/hello -> /(*name)/hello -> {name => 'sebastian.23'} - /sebastian/hello -> /(*name)/hello -> {name => 'sebastian'} - /sebastian23/hello -> /(*name)/hello -> {name => 'sebastian23'} - /sebastian 23/hello -> /(*name)/hello -> {name => 'sebastian 23'} - =head1 BASICS Most commonly used features every L developer should know about. @@ -661,7 +661,7 @@ Because the remaining path always gets stored in the C stash value, you could also just use it directly instead of C. # /foo/* - $r->route('/foo/(*path)')->to('bar#', name => 'Mojo'); + $r->route('/foo/*path')->to('bar#', name => 'Mojo'); =head2 Application Plugins @@ -746,9 +746,9 @@ The C command can be used from the command line to list all available routes together with name and underlying regular expressions. % script/myapp routes - /foo/:name GET fooname (?-xism:^/foo/([^\/\.]+)) - /bar/(.test) * bartest (?-xism:^/bar/([^\/]+)) - /baz/(*everything) POST bazeverything (?-xism:^/baz/(.+)) + /foo/:name GET fooname (?-xism:^/foo/([^\/\.]+)) + /baz/*everything POST bazeverything (?-xism:^/baz/(.+)) + /bar/(.test) * bartest (?-xism:^/bar/([^\/]+)) =head1 MORE diff --git a/lib/Mojolicious/Lite.pm b/lib/Mojolicious/Lite.pm index 442b62b807..f547fe8229 100644 --- a/lib/Mojolicious/Lite.pm +++ b/lib/Mojolicious/Lite.pm @@ -363,23 +363,6 @@ C. $self->render(text => "Our :bar placeholder matched $bar"); }; -=head2 Relaxed Placeholders - -Relaxed placeholders allow matching of everything until a C occurs. - - # /*/hello (everything except "/") - # /test/hello - # /test123/hello - # /test.123/hello - get '/(.you)/hello' => sub { - shift->render('groovy'); - }; - - __DATA__ - - @@ groovy.html.ep - Your name is <%= $you %>. - =head2 Wildcard Placeholders Wildcard placeholders allow matching absolutely everything, including @@ -389,7 +372,7 @@ C and C<.>. # /hello/test # /hello/test123 # /hello/test.123/test/123 - get '/hello/(*you)' => sub { + get '/hello/*you' => sub { shift->render('groovy'); }; diff --git a/lib/Mojolicious/Routes/Pattern.pm b/lib/Mojolicious/Routes/Pattern.pm index 5c518d15d6..f87c96f251 100644 --- a/lib/Mojolicious/Routes/Pattern.pm +++ b/lib/Mojolicious/Routes/Pattern.pm @@ -224,28 +224,19 @@ sub _tokenize { next; } - # Relaxed start - if ($quoted && $char eq $relaxed_start) { - - # Upgrade relaxed to wildcard - if ($state eq 'symbol') { - $state = 'relaxed'; - $tree->[-1]->[0] = 'relaxed'; - next; - } - + # Relaxed start (needs to be quoted) + if ($quoted && $char eq $relaxed_start && $state eq 'symbol') { + $state = 'relaxed'; + $tree->[-1]->[0] = 'relaxed'; + next; } - # Wildcard start - if ($quoted && $char eq $wildcard_start) { - - # Upgrade relaxed to wildcard - if ($state eq 'symbol') { - $state = 'wildcard'; - $tree->[-1]->[0] = 'wildcard'; - next; - } - + # Wildcard start (upgrade when quoted) + if ($char eq $wildcard_start) { + push @$tree, ['symbol', ''] unless $quoted; + $state = 'wildcard'; + $tree->[-1]->[0] = 'wildcard'; + next; } # Quote end diff --git a/t/mojolicious/embedded_lite_app.t b/t/mojolicious/embedded_lite_app.t index 9eab8911b2..fb3876c71b 100644 --- a/t/mojolicious/embedded_lite_app.t +++ b/t/mojolicious/embedded_lite_app.t @@ -107,7 +107,7 @@ get('/yada/yada/yada') get('/basic')->detour(MyTestApp::Basic->new, test => 'lalala'); # /third/* (dispatch to embedded app) -get '/third/(*path)' => +get '/third/*path' => {app => 'MyTestApp::Test2', name => 'third embedded', path => '/'}; # /hello/* (dispatch to embedded app) diff --git a/t/mojolicious/lite_app.t b/t/mojolicious/lite_app.t index d6fc121555..4ba13caf4d 100644 --- a/t/mojolicious/lite_app.t +++ b/t/mojolicious/lite_app.t @@ -12,7 +12,7 @@ BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 } my $backup; BEGIN { $backup = $ENV{MOJO_MODE} || ''; $ENV{MOJO_MODE} = 'development' } -use Test::More tests => 787; +use Test::More tests => 792; # Pollution 123 =~ m/(\d+)/; @@ -268,6 +268,12 @@ get '/foo_wildcard/(*test)' => sub { $self->render_text($self->stash('test')); }; +# GET /foo_wildcard_too/* +get '/foo_wildcard_too/*test' => sub { + my $self = shift; + $self->render_text($self->stash('test')); +}; + # GET /with/header/condition get '/with/header/condition' => (headers => {'X-Secret-Header' => 'bar'}) => 'with_header_condition'; @@ -1043,6 +1049,12 @@ $t->get_ok('/foo_wildcard/123')->status_is(200)->content_is('123'); # GET /foo_wildcard $t->get_ok('/foo_wildcard/')->status_is(404); +# GET /foo_wildcard_too/123 +$t->get_ok('/foo_wildcard_too/123')->status_is(200)->content_is('123'); + +# GET /foo_wildcard_too +$t->get_ok('/foo_wildcard_too/')->status_is(404); + # GET /with/header/condition $t->get_ok('/with/header/condition', {'X-Secret-Header' => 'bar'}) ->status_is(200)->content_like(qr/^Test okroute('/wildcards/2/(*wildcard)') $r->route('/wildcards/3/(*wildcard)/foo') ->to(controller => 'very', action => 'dangerous'); +# /wildcards/4/*/foo +$r->route('/wildcards/4/*wildcard/foo') + ->to(controller => 'somewhat', action => 'dangerous'); + # /format # /format.html $r->route('/format') @@ -313,6 +317,14 @@ is $m->stack->[0]->{action}, 'dangerous', 'right value'; is $m->stack->[0]->{wildcard}, 'hello/there', 'right value'; is $m->path_for, '/wildcards/3/hello/there/foo', 'right path'; is @{$m->stack}, 1, 'right number of elements'; +$m = + Mojolicious::Routes::Match->new(get => '/wildcards/4/hello/there/foo') + ->match($r); +is $m->stack->[0]->{controller}, 'somewhat', 'right value'; +is $m->stack->[0]->{action}, 'dangerous', 'right value'; +is $m->stack->[0]->{wildcard}, 'hello/there', 'right value'; +is $m->path_for, '/wildcards/4/hello/there/foo', 'right path'; +is @{$m->stack}, 1, 'right number of elements'; # Escaped $m =