Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Dancer CPAN distribution.

Report information
The Basics
Id: 57720
Status: new
Priority: 0/
Queue: Dancer

People
Owner: Nobody in particular
Requestors: stephane [...] shimaore.net
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Adding support for both named and splat() parameters (in the same URI)
This patch provides support for both named and splat() parameters in the same URI. I posted a shorter version of this patch earlier on the dancer-users list. The patch attached here contains the same code but adds validation tests.
Subject: splat.diff
diff --git a/lib/Dancer/Route.pm b/lib/Dancer/Route.pm index eaf99b6..7823668 100644 --- a/lib/Dancer/Route.pm +++ b/lib/Dancer/Route.pm @@ -300,7 +300,12 @@ sub match { # if named variables were found, return params accordingly if (@$variables) { for (my $i = 0; $i < ~~ @$variables; $i++) { + if($variables->[$i] eq 'splat' && $capture) { + $params{splat} ||= []; + push @{$params{splat}}, $values[$i]; + } else { $params{$variables->[$i]} = $values[$i]; + } } return \%params; } diff --git a/lib/Dancer/Route/Builder.pm b/lib/Dancer/Route/Builder.pm index 53ff3f0..ebf428b 100644 --- a/lib/Dancer/Route/Builder.pm +++ b/lib/Dancer/Route/Builder.pm @@ -45,20 +45,15 @@ sub make_regexp { } else { # look for route with params (/hello/:foo) - if ($pattern =~ /:/) { - @params = $pattern =~ /:([^\/\.]+)/g; + if ($pattern =~ /[:*]/) { + @params = $pattern =~ /(:[^\/\.]+|\*)/g; if (@params) { - $pattern =~ s/(:[^\/\.]+)/\(\[\^\/\]\+\)/g; + $pattern =~ s/(:[^\/\.]+|\*)/\(\[\^\/\]\+\)/g; + @params = map { /^:(.*)$/ ? $1 : 'splat' } @params; $capture = 1; } } - # parse wildcards - if ($pattern =~ /\*/) { - $pattern =~ s/\*/\(\[\^\/\]\+\)/g; - $capture = 1; - } - # escape dots $pattern =~ s/\./\\\./g if $pattern =~ /\./; } diff --git a/t/03_route_handler/04_wildcards.t b/t/03_route_handler/04_wildcards.t index 60d0495..cb4d7d4 100644 --- a/t/03_route_handler/04_wildcards.t +++ b/t/03_route_handler/04_wildcards.t @@ -7,7 +7,7 @@ use t::lib::TestUtils; use Dancer ':syntax'; use Dancer::Route; -my @paths = ('/hello/*', '/hello/*/welcome/*', '/download/*.*'); +my @paths = ('/hello/*', '/hello/*/welcome/*', '/download/*.*', '/mix/:name/*'); my @tests = ( {path => '/hello/sukria', @@ -18,6 +18,9 @@ my @tests = ( {path => '/download/wolverine.pdf', expected => ['wolverine', 'pdf']}, + + {path => '/mix/alexis/sukrieh', + expected => ['sukrieh']}, ); my $nb_tests = (scalar(@paths)) + (scalar(@tests) * 2); diff --git a/t/03_route_handler/24_multiple_params.t b/t/03_route_handler/24_multiple_params.t index acb8736..050f273 100644 --- a/t/03_route_handler/24_multiple_params.t +++ b/t/03_route_handler/24_multiple_params.t @@ -1,7 +1,7 @@ use strict; use warnings; -use Test::More tests => 26*2+9, import => ['!pass']; +use Test::More tests => 38*2+11, import => ['!pass']; use t::lib::TestUtils; @@ -14,10 +14,10 @@ use Dancer::Config 'setting'; ok(get('/' => sub { 'index' }), 'first route set'); ok(get('/name/:name' => sub { params->{name} }), 'second route set'); ok(get('/name/:name/:location' => sub { params->{name} }), 'third route set'); -# ok(get('/name/:name/:location/*' => sub { [params->{name},splat] }), 'third route set'); + ok(get('/name/:name/:location/*' => sub { [params->{name},splat] }), 'third route set'); ok(get('/location/:location' => sub { params->{location} }), 'fourth route set'); ok(get('/location/:name/:location' => sub { params->{location} }), 'fifth route set'); -# ok(get('/location/:name/:location/*' => sub { [params->{location},splat] }), 'fifth route set'); + ok(get('/location/:name/:location/*' => sub { [params->{location},splat] }), 'fifth route set'); ok(post('/name/:name' => sub { params->{name} }), 'sixth route set'); ok(post('/name/:name/:location' => sub { params->{name} }), 'seventh route set'); ok(post('/location/:location' => sub { params->{location} }), 'eigth route set'); @@ -31,17 +31,17 @@ my @tests = ( {method => 'GET', path => '/name/bill', expected => 'bill'}, {method => 'GET', path => '/name/bob', expected => 'bob'}, -# {method => 'GET', path => '/name/bob/paris/wine', expected => ['bob','wine'] }, -# {method => 'GET', path => '/name/bob/dublin/beer', expected => ['bob','beer'] }, -# {method => 'GET', path => '/name/bob/paris/wine', expected => ['bob','wine'] }, + {method => 'GET', path => '/name/bob/paris/wine', expected => ['bob','wine'] }, + {method => 'GET', path => '/name/bob/dublin/beer', expected => ['bob','beer'] }, + {method => 'GET', path => '/name/bob/paris/wine', expected => ['bob','wine'] }, -# {method => 'GET', path => '/name/bill/paris/wine', expected => ['bill','wine'] }, -# {method => 'GET', path => '/name/bill/dublin/beer', expected => ['bill','beer'] }, -# {method => 'GET', path => '/name/bill/paris/wine', expected => ['bill','wine'] }, + {method => 'GET', path => '/name/bill/paris/wine', expected => ['bill','wine'] }, + {method => 'GET', path => '/name/bill/dublin/beer', expected => ['bill','beer'] }, + {method => 'GET', path => '/name/bill/paris/wine', expected => ['bill','wine'] }, -# {method => 'GET', path => '/name/bob/paris/today', expected => ['bob','today'] }, -# {method => 'GET', path => '/name/bob/dublin/now', expected => ['bob','now'] }, -# {method => 'GET', path => '/name/bob/paris/tomorrow', expected => ['bob','tomorrow'] }, + {method => 'GET', path => '/name/bob/paris/today', expected => ['bob','today'] }, + {method => 'GET', path => '/name/bob/dublin/now', expected => ['bob','now'] }, + {method => 'GET', path => '/name/bob/paris/tomorrow', expected => ['bob','tomorrow'] }, {method => 'GET', path => '/name/bob/paris', expected => 'bob' }, {method => 'GET', path => '/name/bob/dublin', expected => 'bob' }, @@ -64,9 +64,9 @@ my @tests = ( {method => 'GET', path => '/location/bob/dublin', expected => 'dublin' }, {method => 'GET', path => '/location/bob/paris', expected => 'paris' }, -# {method => 'GET', path => '/location/bob/paris/wine', expected => ['paris','wine'] }, -# {method => 'GET', path => '/location/bob/dublin/beer', expected => ['dublin','beer'] }, -# {method => 'GET', path => '/location/bob/paris/wine', expected => ['paris','wine'] }, + {method => 'GET', path => '/location/bob/paris/wine', expected => ['paris','wine'] }, + {method => 'GET', path => '/location/bob/dublin/beer', expected => ['dublin','beer'] }, + {method => 'GET', path => '/location/bob/paris/wine', expected => ['paris','wine'] }, {method => 'post', path => '/name/bob', expected => 'bob'}, {method => 'post', path => '/name/bob/paris', expected => 'bob' },