# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.89002';
+our $VERSION = '5.90004';
sub import {
my ( $class, @arguments ) = @_;
MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used.
If none of these are set, Catalyst will attempt to automatically detect the
-home directory. If you are working in a development envirnoment, Catalyst
+home directory. If you are working in a development environment, Catalyst
will try and find the directory containing either Makefile.PL, Build.PL or
dist.ini. If the application has been installed into the system (i.e.
you have done C<make install>), then Catalyst will use the path to your
-application module, without the .pm extension (ie, /foo/MyApp if your
+application module, without the .pm extension (e.g., /foo/MyApp if your
application was installed at /foo/MyApp.pm)
=head2 -Log
Note that L<< forward|/"$c->forward( $action [, \@arguments ] )" >> implies
an C<< eval { } >> around the call (actually
-L<< execute|/"$c->execute( $class, $coderef )" >> does), thus de-fatalizing
-all 'dies' within the called action. If you want C<die> to propagate you
-need to do something like:
+L<< execute|/"$c->execute( $class, $coderef )" >> does), thus rendering all
+exceptions thrown by the called action non-fatal and pushing them onto
+$c->error instead. If you want C<die> to propagate you need to do something
+like:
$c->forward('foo');
die join "\n", @{ $c->error } if @{ $c->error };
when they are invoked within the visited action. This is different from the
behavior of L<< forward|/"$c->forward( $action [, \@arguments ] )" >>, which
continues to use the $c->action object from the caller action even when
-invoked from the callee.
+invoked from the called action.
C<< $c->stash >> is kept unchanged.
}
my $action = $path;
- $path = $c->dispatcher->uri_for_action($action, $captures);
+ # ->uri_for( $action, \@captures_and_args, \%query_values? )
+ if( !@args && $action->number_of_args ) {
+ my $expanded_action = $c->dispatcher->expand_action( $action );
+
+ my $num_captures = $expanded_action->number_of_captures;
+ unshift @args, splice @$captures, $num_captures;
+ }
+
+ $path = $c->dispatcher->uri_for_action($action, $captures);
if (not defined $path) {
$c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
if $c->debug;
if ( !$response->has_body ) {
# Add a default body if none is already present
- $response->body(
- qq{<html><body><p>This item has moved <a href="$location">here</a>.</p></body></html>}
- );
+ $response->body(<<"EOF");
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Moved</title>
+ </head>
+ <body>
+ <p>This item has moved <a href="$location">here</a>.</p>
+ </body>
+</html>
+EOF
+ $response->content_type('text/html; charset=utf-8');
}
}
return $status;
}
-=head2 $c->prepare( @arguments )
+=head2 $class->prepare( @arguments )
Creates a Catalyst context from an engine-specific request (Apache, CGI,
etc.).
=head2 $c->log_response_headers($headers);
-Hook method which can be wrapped by plugins to log the responseheaders.
+Hook method which can be wrapped by plugins to log the response headers.
No-op in the default implementation.
=cut
=cut
sub engine_class {
- my $class = shift;
- $class->engine_loader->catalyst_engine_class(@_);
+ my ($class, $requested_engine) = @_;
+
+ if (!$class->engine_loader || $requested_engine) {
+ $class->engine_loader(
+ Catalyst::EngineLoader->new({
+ application_name => $class,
+ (defined $requested_engine
+ ? (catalyst_engine_class => $requested_engine) : ()),
+ }),
+ );
+ }
+
+ $class->engine_loader->catalyst_engine_class;
}
sub setup_engine {
my ($class, $requested_engine) = @_;
- $class->engine_loader(
- Catalyst::EngineLoader->new({
- application_name => $class,
- (defined $requested_engine
- ? (requested_engine => $requested_engine) : ()),
- }),
- );
+ my $engine = do {
+ my $loader = $class->engine_loader;
+
+ if (!$loader || $requested_engine) {
+ $loader = Catalyst::EngineLoader->new({
+ application_name => $class,
+ (defined $requested_engine
+ ? (requested_engine => $requested_engine) : ()),
+ }),
+
+ $class->engine_loader($loader);
+ }
+
+ $loader->catalyst_engine_class;
+ };
# Don't really setup_engine -- see _setup_psgi_app for explanation.
return if $class->loading_psgi_file;
- my $engine = $class->engine_class;
Class::MOP::load_class($engine);
if ($ENV{MOD_PERL}) {
},
);
- my $server_matches = sub {
- my ($re) = @_;
- return sub {
- my ($env) = @_;
- my $server = $env->{SERVER_SOFTWARE};
- return unless $server;
- return $server =~ $re ? 1 : 0;
- };
- };
-
# 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,
- condition => $server_matches->(qr/^nginx/),
- builder => sub {
- my ($to_wrap) = @_;
- return sub {
- my ($env) = @_;
- my $script_name = $env->{SCRIPT_NAME};
- $env->{PATH_INFO} =~ s/^$script_name//g;
- return $to_wrap->($env);
- };
- },
- );
-
# 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
# IIS versions
C<parse_on_demand> - The request body (for example file uploads) will not be parsed
until it is accessed. This allows you to (for example) check authentication (and reject
-the upload) before actually recieving all the data. See L</ON-DEMAND PARSER>
+the upload) before actually receiving all the data. See L</ON-DEMAND PARSER>
=item *
=item *
C<use_request_uri_for_path> - Controlls if the C<REQUEST_URI> or C<PATH_INFO> environment
-variable should be used for determining the request path. See L<Catalyst::Engine::CGI/PATH DECODING>
-for more information.
+variable should be used for determining the request path.
+
+Most web server environments pass the requested path to the application using environment variables,
+from which Catalyst has to reconstruct the request base (i.e. the top level path to / in the application,
+exposed as C<< $c->request->base >>) and the request path below that base.
+
+There are two methods of doing this, both of which have advantages and disadvantages. Which method is used
+is determined by the C<< $c->config(use_request_uri_for_path) >> setting (which can either be true or false).
+
+=over
+
+=item use_request_uri_for_path => 0
+
+This is the default (and the) traditional method that Catalyst has used for determining the path information.
+The path is synthesised from a combination of the C<PATH_INFO> and C<SCRIPT_NAME> environment variables.
+The allows the application to behave correctly when C<mod_rewrite> is being used to redirect requests
+into the application, as these variables are adjusted by mod_rewrite to take account for the redirect.
+
+However this method has the major disadvantage that it is impossible to correctly decode some elements
+of the path, as RFC 3875 says: "C<< Unlike a URI path, the PATH_INFO is not URL-encoded, and cannot
+contain path-segment parameters. >>" This means PATH_INFO is B<always> decoded, and therefore Catalyst
+can't distinguish / vs %2F in paths (in addition to other encoded values).
+
+=item use_request_uri_for_path => 1
+
+This method uses the C<REQUEST_URI> and C<SCRIPT_NAME> environment variables. As C<REQUEST_URI> is never
+decoded, this means that applications using this mode can correctly handle URIs including the %2F character
+(i.e. with C<AllowEncodedSlashes> set to C<On> in Apache).
+
+Given that this method of path resolution is provably more correct, it is recommended that you use
+this unless you have a specific need to deploy your application in a non-standard environment, and you are
+aware of the implications of not being able to handle encoded URI paths correctly.
+
+However it also means that in a number of cases when the app isn't installed directly at a path, but instead
+is having paths rewritten into it (e.g. as a .cgi/fcgi in a public_html directory, with mod_rewrite in a
+.htaccess file, or when SSI is used to rewrite pages into the app, or when sub-paths of the app are exposed
+at other URIs than that which the app is 'normally' based at with C<mod_rewrite>), the resolution of
+C<< $c->request->base >> will be incorrect.
+
+=back
=item *
=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.