Docs
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
index 9f25c7e..bdb37bf 100644 (file)
@@ -16,7 +16,6 @@ use Catalyst::Utils;
 use Catalyst::Controller;
 use Data::OptList;
 use Devel::InnerPackage ();
-use File::stat;
 use Module::Pluggable::Object ();
 use Text::SimpleTable ();
 use Path::Class::Dir ();
@@ -36,6 +35,8 @@ use Carp qw/croak carp shortmess/;
 use Try::Tiny;
 use Plack::Middleware::Conditional;
 use Plack::Middleware::ReverseProxy;
+use Plack::Middleware::IIS6ScriptNameFix;
+use Plack::Middleware::LighttpdScriptNameFix;
 
 BEGIN { require 5.008004; }
 
@@ -74,7 +75,7 @@ our $GO        = Catalyst::Exception::Go->new;
 __PACKAGE__->mk_classdata($_)
   for qw/components arguments dispatcher engine log dispatcher_class
   engine_loader context_class request_class response_class stats_class
-  setup_finished _psgi_app/;
+  setup_finished _psgi_app loading_psgi_file/;
 
 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
 __PACKAGE__->request_class('Catalyst::Request');
@@ -865,6 +866,9 @@ sub component {
             return $c->_filter_component( $comp, @args ) if $comp;
         }
 
+        return
+            if $c->config->{disable_component_resolution_regex_fallback};
+
         # This is here so $c->comp( '::M::' ) works
         my $query = ref $name ? $name : qr{$name}i;
 
@@ -1119,7 +1123,7 @@ sub setup {
     $class->setup_plugins( delete $flags->{plugins} );
     $class->setup_dispatcher( delete $flags->{dispatcher} );
     if (my $engine = delete $flags->{engine}) {
-        $class->log->warn("Specifying the engine in ->setup is no longer supported, XXX FIXME");
+        $class->log->warn("Specifying the engine in ->setup is no longer supported, see Catalyst::Upgrading");
     }
     $class->setup_engine();
     $class->setup_stats( delete $flags->{stats} );
@@ -1248,7 +1252,7 @@ EOF
 A hook to attach modifiers to. This method does not do anything except set the
 C<setup_finished> accessor.
 
-Applying method modifiers to the C<setup> method doesn't work, because of quirky thingsdone for plugin setup.
+Applying method modifiers to the C<setup> method doesn't work, because of quirky things done for plugin setup.
 
 Example:
 
@@ -1691,8 +1695,8 @@ sub execute {
                 $error = qq/Caught exception in $class->$name "$error"/;
             }
             $c->error($error);
-            $c->state(0);
         }
+        $c->state(0);
     }
     return $c->state;
 }
@@ -1871,9 +1875,9 @@ sub finalize_headers {
         # get the length from a filehandle
         if ( blessed( $response->body ) && $response->body->can('read') || ref( $response->body ) eq 'GLOB' )
         {
-            my $stat = stat $response->body;
-            if ( $stat && $stat->size > 0 ) {
-                $response->content_length( $stat->size );
+            my $size = -s $response->body;
+            if ( $size ) {
+                $response->content_length( $size );
             }
             else {
                 $c->log->warn('Serving filehandle without a content-length');
@@ -2409,7 +2413,12 @@ Starts the engine.
 
 =cut
 
-sub run { my $c = shift; return $c->engine->run( $c, $c->_finalized_psgi_app, @_ ) }
+sub run {
+  my $app = shift;
+  $app->engine_loader->needs_psgi_engine_compat_hack ?
+    $app->engine->run($app, @_) :
+      $app->engine->run( $app, $app->_finalized_psgi_app, @_ );
+}
 
 =head2 $c->set_action( $action, $code, $namespace, $attrs )
 
@@ -2599,9 +2608,18 @@ sub engine_class {
 }
 
 sub setup_engine {
-    my ($class) = @_;
+    my ($class, $requested_engine) = @_;
+
+    $class->engine_loader(
+        Catalyst::EngineLoader->new({
+            application_name => $class,
+            (defined $requested_engine
+                 ? (requested_engine => $requested_engine) : ()),
+        }),
+    );
 
-    $class->engine_loader(Catalyst::EngineLoader->new(application_name => $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);
@@ -2635,23 +2653,56 @@ sub _finalized_psgi_app {
 sub _setup_psgi_app {
     my ($app) = @_;
 
-    if (my $home = Path::Class::Dir->new($app->config->{home})) {
+    for my $home (Path::Class::Dir->new($app->config->{home})) {
         my $psgi_file = $home->file(
             Catalyst::Utils::appprefix($app) . '.psgi',
         );
 
-        return Plack::Util::load_psgi($psgi_file)
-            if -e $psgi_file;
+        next unless -e $psgi_file;
+
+        # If $psgi_file calls ->setup_engine, it's doing so to load
+        # Catalyst::Engine::PSGI. But if it does that, we're only going to
+        # throw away the loaded PSGI-app and load the 5.9 Catalyst::Engine
+        # anyway. So set a flag (ick) that tells setup_engine not to populate
+        # $c->engine or do any other things we might regret.
+
+        $app->loading_psgi_file(1);
+        my $psgi_app = Plack::Util::load_psgi($psgi_file);
+        $app->loading_psgi_file(0);
+
+        return $psgi_app
+            unless $app->engine_loader->needs_psgi_engine_compat_hack;
+
+        warn <<"EOW";
+Found a legacy Catalyst::Engine::PSGI .psgi file at ${psgi_file}.
+
+Its content has been ignored. Please consult the Catalyst::Upgrading
+documentation on how to upgrade from Catalyst::Engine::PSGI.
+EOW
     }
 
-    return $app->_wrapped_legacy_psgi_app($app->psgi_app);
+    return $app->apply_default_middlewares($app->psgi_app);
 }
 
-# Note - this is for back compatibility. Catalyst should not know or care about
-#        how it's deployed. The recommended way of configuring this is now to
-#        use the ReverseProxy middleware yourself if you want it in a .psgi
-#        file.
-sub _wrapped_legacy_psgi_app {
+=head2 $c->apply_default_middlewares
+
+Adds the following L<Plack> middlewares to your application, since they are
+useful and commonly needed:
+
+L<Plack::Middleware::ReverseProxy>, (conditionally added based on the status
+of your $ENV{REMOTE_ADDR}, and can be forced on with C<using_frontend_proxy>
+or forced off with C<ignore_frontend_proxy>), L<Plack::Middleware::LighttpdScriptNameFix>
+(if you are using Lighttpd), L<Plack::Middleware::IIS6ScriptNameFix> (always
+applied since this middleware is smart enough to conditionally apply itself).
+
+Additionally if we detect we are using Nginx, we add a bit of custom middleware
+to solve some problems with the way that server handles $ENV{PATH_INFO} and
+$ENV{SCRIPT_NAME}
+
+=cut
+
+
+sub apply_default_middlewares {
     my ($app, $psgi_app) = @_;
 
     $psgi_app = Plack::Middleware::Conditional->wrap(
@@ -2665,31 +2716,39 @@ sub _wrapped_legacy_psgi_app {
         },
     );
 
+    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
-    # Thanks to Mark Blythe for this fix
-    #
-    # Note that this has probably the same effect as
-    # Plack::Middleware::LighttpdScriptNameFix and we should switch to that if
-    # we can.
+    $psgi_app = Plack::Middleware::LighttpdScriptNameFix->wrap($psgi_app);
+
     $psgi_app = Plack::Middleware::Conditional->wrap(
         $psgi_app,
-        builder => sub {
+        condition => $server_matches->(qr/^nginx/),
+        builder   => sub {
             my ($to_wrap) = @_;
             return sub {
                 my ($env) = @_;
-                $env->{PATH_INFO} ||= delete $env->{SCRIPT_NAME};
+                my $script_name = $env->{SCRIPT_NAME};
+                $env->{PATH_INFO} =~ s/^$script_name//g;
                 return $to_wrap->($env);
             };
         },
-        condition => sub {
-            my ($env) = @_;
-            my $server = $env->{SERVER_SOFTWARE};
-            return unless $server;
-            return $server =~ /lighttpd/ ? 1 : 0;
-        },
     );
 
+    # 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
+    $psgi_app = Plack::Middleware::IIS6ScriptNameFix->wrap($psgi_app);
+
     return $psgi_app;
 }
 
@@ -2826,7 +2885,7 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
         my $class = ref $proto || $proto;
 
         Class::MOP::load_class( $plugin );
-        $class->log->warn( "$plugin inherits from 'Catalyst::Component' - this is decated and will not work in 5.81" )
+        $class->log->warn( "$plugin inherits from 'Catalyst::Component' - this is deprecated and will not work in 5.81" )
             if $plugin->isa( 'Catalyst::Component' );
         $proto->_plugins->{$plugin} = 1;
         unless ($instant) {
@@ -3250,6 +3309,10 @@ rainboxx: Matthias Dietrich, C<perl@rainboxx.de>
 
 dd070: Dhaval Dhanani <dhaval070@gmail.com>
 
+=head1 COPYRIGHT
+
+Copyright (c) 2005, the above named PROJECT FOUNDER and CONTRIBUTORS.
+
 =head1 LICENSE
 
 This library is free software. You can redistribute it and/or modify it under