From: Matt S Trout Date: Fri, 11 Feb 2011 06:32:12 +0000 (+0000) Subject: fix environment changes within subdispatch and arrange for middleware to uplevel... X-Git-Tag: release_0.006~4 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=1f4dd6f9a3666ef59e96b87553e97dcf581b870e;hp=ce446593a2c969d2567a9d9dddacc031ffd7d292;p=catagits%2FWeb-Simple.git fix environment changes within subdispatch and arrange for middleware to uplevel correctly --- diff --git a/lib/Web/Dispatch.pm b/lib/Web/Dispatch.pm index d9e76ca..184cada 100644 --- a/lib/Web/Dispatch.pm +++ b/lib/Web/Dispatch.pm @@ -2,6 +2,9 @@ package Web::Dispatch; use Sub::Quote; use Scalar::Util qw(blessed); + +sub MAGIC_MIDDLEWARE_KEY { __PACKAGE__.'.middleware' } + use Moo; use Web::Dispatch::Parser; use Web::Dispatch::Node; @@ -47,7 +50,14 @@ sub _dispatch { } elsif (blessed($result[0]) && $result[0]->isa('Plack::Middleware')) { die "Multiple results but first one is a middleware ($result[0])" if @result > 1; + # middleware needs to uplevel exactly once to wrap the rest of the + # level it was created for - next elsif unwraps it + return { MAGIC_MIDDLEWARE_KEY, $result[0] }; my $mw = $result[0]; + } elsif ( + ref($result[0]) eq 'HASH' + and my $mw = $result[0]->{+MAGIC_MIDDLEWARE_KEY} + ) { $mw->app(sub { $self->_dispatch($_[0], @match) }); return $mw->to_app->($env); } elsif (blessed($result[0]) && !$result[0]->can('to_app')) { @@ -55,12 +65,7 @@ sub _dispatch { } else { # make a copy so we don't screw with it assigning further up my $env = $env; - # try not to end up quite so bloody deep in the call stack - if (@match) { - unshift @match, sub { $self->_dispatch($env, @result) }; - } else { - @match = @result; - } + unshift @match, sub { $self->_dispatch($env, @result) }; } } return; diff --git a/lib/Web/Dispatch/Node.pm b/lib/Web/Dispatch/Node.pm index 4fbc46d..bd83a7c 100644 --- a/lib/Web/Dispatch/Node.pm +++ b/lib/Web/Dispatch/Node.pm @@ -11,7 +11,7 @@ for (qw(match run)) { sub call { my ($self, $env) = @_; if (my ($env_delta, @match) = $self->_match->($env)) { - $self->_curry(@match)->({ %$env, %$env_delta }); + ($env_delta, $self->_curry(@match)); } else { () } diff --git a/t/response-filter.t b/t/response-filter.t index 645e4e6..1cac671 100644 --- a/t/response-filter.t +++ b/t/response-filter.t @@ -15,7 +15,7 @@ use HTTP::Request::Common qw(GET POST); [ 'Content-Type' => 'text/html' ], [ shift->{name} ], ]; - }; + } }, sub (GET + /index) { bless {name=>'john'}, 'CrazyHotWildWet'; diff --git a/t/sub-dispatch-env.t b/t/sub-dispatch-env.t new file mode 100644 index 0000000..14a7a31 --- /dev/null +++ b/t/sub-dispatch-env.t @@ -0,0 +1,26 @@ +use strictures 1; +use Test::More; + +{ + package TestApp; + + use Web::Simple; + + sub dispatch_request { + sub (/foo/...) { + sub (GET) { [ 200, [], [ $_[PSGI_ENV]->{PATH_INFO} ] ] } + }, + sub (POST) { [ 200, [], [ $_[PSGI_ENV]->{PATH_INFO} ] ] } + } +} + +my $app = TestApp->new->to_psgi_app; + +my $call = sub { $app->({ + SCRIPT_NAME => '/base', PATH_INFO => '/foo/bar', REQUEST_METHOD => shift +})->[2]->[0] }; + +is($call->('GET'), '/bar', 'recursive strip ok'); +is($call->('POST'), '/foo/bar', 'later dispatchers unaffected'); + +done_testing;