Fix Engine::Stomp with psgi
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine.pm
index 8092888..16895f3 100644 (file)
@@ -14,6 +14,9 @@ use Moose::Util::TypeConstraints;
 use Plack::Loader;
 use Plack::Middleware::Conditional;
 use Plack::Middleware::ReverseProxy;
+use Catalyst::Engine::Loader;
+use Encode ();
+use utf8;
 
 use namespace::clean -except => 'meta';
 
@@ -155,6 +158,14 @@ sub finalize_error {
 
     $c->res->content_type('text/html; charset=utf-8');
     my $name = ref($c)->config->{name} || join(' ', split('::', ref $c));
+    
+    # Prevent Catalyst::Plugin::Unicode::Encoding from running.
+    # This is a little nasty, but it's the best way to be clean whether or
+    # not the user has an encoding plugin.
+
+    if ($c->can('encoding')) {
+      $c->{encoding} = '';
+    }
 
     my ( $title, $error, $infos );
     if ( $c->debug ) {
@@ -303,11 +314,12 @@ sub finalize_error {
 </body>
 </html>
 
-
     # Trick IE. Old versions of IE would display their own error page instead
     # of ours if we'd give it less than 512 bytes.
     $c->res->{body} .= ( ' ' x 512 );
 
+    $c->res->{body} = Encode::encode("UTF-8", $c->res->{body});
+
     # Return 500
     $c->res->status(500);
 }
@@ -523,10 +535,24 @@ sub prepare_path {
     my $base_path = $env->{SCRIPT_NAME} || "/";
 
     # set the request URI
-    my $req_uri = $env->{REQUEST_URI};
-    $req_uri =~ s/\?.*$//;
-    my $path = $req_uri;
-    $path =~ s{^/+}{};
+    my $path;
+    if (!$ctx->config->{use_request_uri_for_path}) {
+        my $path_info = $env->{PATH_INFO};
+        if ( exists $env->{REDIRECT_URL} ) {
+            $base_path = $env->{REDIRECT_URL};
+            $base_path =~ s/\Q$path_info\E$//;
+        }
+        $path = $base_path . $path_info;
+        $path =~ s{^/+}{};
+        $path =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+        $path =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
+    }
+    else {
+        my $req_uri = $env->{REQUEST_URI};
+        $req_uri =~ s/\?.*$//;
+        $path = $req_uri;
+        $path =~ s{^/+}{};
+    }
 
     # Using URI directly is way too slow, so we construct the URLs manually
     my $uri_class = "URI::$scheme";
@@ -750,19 +776,33 @@ The amount of input data that has already been read.
 =head2 $self->run($app, $server)
 
 Start the engine. Builds a PSGI application and calls the
-run method on the server passed in..
+run method on the server passed in, which then causes the
+engine to loop, handling requests..
 
 =cut
 
 sub run {
-    my ($self, $app, @args) = @_;
-    my $server = pop @args if blessed $args[-1];
-    $server ||= Plack::Loader->auto(); # We're not being called from a script,
-                                       # so auto detect what backend to run on.
-                                       # This does *NOT* cover mod_perl.
-    # FIXME - Do something sensible with the options we're passed
-    my $psgi = $self->build_psgi_app($app, @args);
-    $server->run($psgi);
+    my ($self, $app, $psgi, @args) = @_;
+    # @args left here rather than just a $options, $server for back compat with the
+    # old style scripts which send a few args, then a hashref
+
+    # They should never actually be used in the normal case as the Plack engine is
+    # passed in got all the 'standard' args via the loader in the script already.
+
+    # FIXME - we should stash the options in an attribute so that custom args
+    # like Gitalist's --git_dir are possible to get from the app without stupid tricks.
+    my $server = pop @args if (scalar @args && blessed $args[-1]);
+    my $options = pop @args if (scalar @args && ref($args[-1]) eq 'HASH');
+    if (! $server ) {
+        $server = Catalyst::Engine::Loader->new(application_name => ref($self))->auto();
+        # We're not being called from a script,
+                                                    # so auto detect what backend to run on.
+                                                    # This should never happen, as mod_perl
+                                                    # never calls ->run, instead the $app->handle
+                                                    # method is called per request.
+        $app->log->warn("Not supplied a Plack engine, falling back to engine auto-loader (are your scripts ancient?)")
+    }
+    $server->run($psgi, $options);
 }
 
 =head2 build_psgi_app ($app, @args)
@@ -775,7 +815,7 @@ middleware if the using_frontend_proxy config setting is set.
 sub build_psgi_app {
     my ($self, $app, @args) = @_;
 
-    my $psgi_app = sub {
+    return sub {
         my ($env) = @_;
 
         return sub {
@@ -784,18 +824,6 @@ sub build_psgi_app {
             $app->handle_request(env => $env);
         };
     };
-
-    $psgi_app = Plack::Middleware::Conditional->wrap(
-        $psgi_app,
-        condition => sub {
-            my ($env) = @_;
-            return if $app->config->{ignore_frontend_proxy};
-            return $env->{REMOTE_ADDR} eq '127.0.0.1' || $app->config->{using_frontend_proxy};
-        },
-        builder   => sub { Plack::Middleware::ReverseProxy->wrap($_[0]) },
-    );
-
-    return $psgi_app;
 }
 
 =head2 $self->write($c, $buffer)
@@ -812,7 +840,7 @@ sub write {
         $self->_prepared_write(1);
     }
 
-    return 0 if !defined $buffer;
+    $buffer = q[] unless defined $buffer;
 
     my $len = length($buffer);
     $self->_writer->write($buffer);