# This file documents the revision history for Perl extension Catalyst.
+ Documentation:
+ - Fix the display of PROJECT FOUNDER and CONTRIBUTORS sections in the
+ documentation. These were erroneously being emitted when the Pod
+ was converted to HTML for search.cpan.org
+
+5.90007 - 2011-11-22 20:35:00
+
+ New features:
+ - Implement a match_captures hook which, if it exists on an action,
+ is called with the $ctx and \@captures and is expected to return
+ true to continue the chain matching and false to stop matching.
+ This can be used to implement action classes or roles which match
+ conditionally (for example only matching captures which are integers).
+
+ Bug fixes:
+ - Lighttpd script name fix is only applied for lighttpd versions
+ < 1.4.23. This should fix non-root installs of lighttpd in versions
+ over that.
+ - Prepare_action is now inside a try {} block, so that requests containing
+ bad unicode can be appropriately trapped by
+ Catalyst::Plugin::Unicode::Encoding
+
5.90006 - 2011-10-25 09:18:00
New features:
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90006';
+our $VERSION = '5.90007';
sub import {
my ( $class, @arguments ) = @_;
sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
+=head2 $c->visit( $action [, \@arguments ] )
+
=head2 $c->visit( $action [, \@captures, \@arguments ] )
+=head2 $c->visit( $class, $method, [, \@arguments ] )
+
=head2 $c->visit( $class, $method, [, \@captures, \@arguments ] )
Almost the same as L<< forward|/"$c->forward( $action [, \@arguments ] )" >>,
sub visit { my $c = shift; $c->dispatcher->visit( $c, @_ ) }
+=head2 $c->go( $action [, \@arguments ] )
+
=head2 $c->go( $action [, \@captures, \@arguments ] )
+=head2 $c->go( $class, $method, [, \@arguments ] )
+
=head2 $c->go( $class, $method, [, \@captures, \@arguments ] )
The relationship between C<go> and
$c->prepare_body;
}
}
+ $c->prepare_action;
}
# VERY ugly and probably shouldn't rely on ->finalize actually working
catch {
$c->response->status(400);
$c->response->content_type('text/plain');
$c->response->body('Bad Request');
+ # Note we call finalize and then die here, which escapes
+ # finalize being called in the enclosing block..
+ # It in fact couldn't be called, as we don't return $c..
+ # This is a mess - but I'm unsure you can fix this without
+ # breaking compat for people doing crazy things (we should set
+ # the 400 and just return the ctx here IMO, letting finalize get called
+ # above...
$c->finalize;
die $_;
};
- my $method = $c->req->method || '';
- my $path = $c->req->path;
- $path = '/' unless length $path;
- my $address = $c->req->address || '';
-
$c->log_request;
- $c->prepare_action;
-
return $c;
}
# If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
# http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html
- $psgi_app = Plack::Middleware::LighttpdScriptNameFix->wrap($psgi_app);
+ $psgi_app = Plack::Middleware::Conditional->wrap(
+ $psgi_app,
+ builder => sub { Plack::Middleware::LighttpdScriptNameFix->wrap($_[0]) },
+ condition => sub {
+ my ($env) = @_;
+ return unless $env->{SERVER_SOFTWARE} && $env->{SERVER_SOFTWARE} =~ m!lighttpd[-/]1\.(\d+\.\d+)!;
+ return unless $1 < 4.23;
+ 1;
+ },
+ );
# we're applying this unconditionally as the middleware itself already makes
# sure it doesn't fuck things up if it's not running under one of the right
=head2 L<Catalyst::Test> - The test suite.
-=begin stopwords
-
=head1 PROJECT FOUNDER
sri: Sebastian Riedel <sri@cpan.org>
dd070: Dhaval Dhanani <dhaval070@gmail.com>
-=end stopwords
-
=head1 COPYRIGHT
Copyright (c) 2005, the above named PROJECT FOUNDER and CONTRIBUTORS.
Provided by Moose.
+=head1 OPTIONAL METHODS
+
+=head2 match_captures
+
+Can be implemented by action class and action role authors. If the method
+exists, then it will be called with the request context and an array reference
+of the captures for this action.
+
+Returning true from this method causes the chain match to continue, returning
+makes the chain not match (and alternate, less preferred chains will be attempted).
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
# strip CaptureArgs into list
push(@captures, splice(@parts, 0, $capture_attr->[0]));
+ # check if the action may fit, depending on a given test by the app
+ if ($action->can('match_captures')) { next TRY_ACTION unless $action->match_captures($c, \@captures) }
+
# try the remaining parts against children of this action
my ($actions, $captures, $action_parts, $n_pathparts) = $self->recurse_match(
$c, '/'.$action->reverse, \@parts
you C<detach> out of a chain, the rest of the chain will not get called
after the C<detach>.
+=head2 match_captures
+
+A method which can optionally be implemented by actions to
+stop chain matching.
+
+See L<Catalyst::Action> for further details.
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
=head2 $self->prepare_request(@arguments)
-Populate the context object from the request object.
+Sets up the PSGI environment in the Engine.
=cut
=head2 build_psgi_app ($app, @args)
-Builds and returns a PSGI application closure, wrapping it in the reverse proxy
-middleware if the using_frontend_proxy config setting is set.
+Builds and returns a PSGI application closure. (Raw, not wrapped in middleware)
=cut
# Remember to update this in Catalyst as well!
-our $VERSION = '5.90006';
+our $VERSION = '5.90007';
=head1 NAME
ok( index($content, $path) > 1, 'uri can round trip through uri_for' )
or diag("Expected $path, got $content");
}
+
+ #
+ # match_captures
+ #
+ {
+
+ ok( my $response = request('http://localhost/chained/match_captures/foo/bar'), 'match_captures: falling through' );
+ is($response->header('X-TestAppActionTestMatchCaptures'), 'fallthrough', 'match_captures: fell through');
+
+ ok($response = request('http://localhost/chained/match_captures/force/bar'), 'match_captures: *not* falling through' );
+ is($response->header('X-TestAppActionTestMatchCaptures'), 'forcing', 'match_captures: forced');
+ is($response->header('X-TestAppActionTestMatchCapturesHasRan'), 'yes', 'match_captures: actually ran');
+ }
}
done_testing;
--- /dev/null
+package TestApp::Action::TestMatchCaptures;
+
+use Moose;
+
+extends 'Catalyst::Action';
+
+sub match_captures {
+ my ($self, $c, $cap) = @_;
+ if ($cap->[0] eq 'force') {
+ $c->res->header( 'X-TestAppActionTestMatchCaptures', 'forcing' );
+ return 1;
+ } else {
+ $c->res->header( 'X-TestAppActionTestMatchCaptures', 'fallthrough' );
+ return 0;
+ }
+}
+
+1;
\ No newline at end of file
$c->stash->{no_end} = 1;
}
+sub match_captures : Chained('/') PathPart('chained/match_captures') CaptureArgs(1) ActionClass('+TestApp::Action::TestMatchCaptures') {
+ my ($self, $c) = @_;
+ $c->res->header( 'X-TestAppActionTestMatchCapturesHasRan', 'yes');
+}
+
+sub match_captures_end : Chained('match_captures') PathPart('bar') Args(0) { }
+
sub end :Private {
my ($self, $c) = @_;
return if $c->stash->{no_end};