Add _set_env writer to non-PSGI Catalyst
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / CGI.pm
index 57274f8..bd670da 100644 (file)
@@ -47,7 +47,7 @@ into the application, as these variables are adjusted by mod_rewrite to take acc
 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.
+can't distinguish / vs %2F in paths (in addition to other encoded values).
 
 =head2 use_request_uri_for_path => 1
 
@@ -55,6 +55,10 @@ This method uses the C<REQUEST_URI> and C<SCRIPT_NAME> environment variables. As
 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
@@ -150,6 +154,12 @@ sub prepare_path {
     my $scheme = $c->request->secure ? 'https' : 'http';
     my $host      = $ENV{HTTP_HOST}   || $ENV{SERVER_NAME};
     my $port      = $ENV{SERVER_PORT} || 80;
+
+    # fix up for IIS
+    if ($ENV{SERVER_SOFTWARE} && $ENV{SERVER_SOFTWARE} =~ m{IIS/[6-9]\.\d}) {
+        $ENV{PATH_INFO} =~ s/^\Q$ENV{SCRIPT_NAME}\E//;
+    }
+
     my $script_name = $ENV{SCRIPT_NAME};
     $script_name =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go if $script_name;
 
@@ -251,7 +261,7 @@ sub prepare_request {
     my ( $self, $c, %args ) = @_;
 
     if ( $args{env} ) {
-        $self->env( $args{env} );
+        $self->_set_env( $args{env} );
     }
 }
 
@@ -278,7 +288,10 @@ around write => sub {
 
     # Prepend the headers if they have not yet been sent
     if ( $self->_has_header_buf ) {
-        $buffer = $self->_clear_header_buf . $buffer;
+        my $headers = $self->_clear_header_buf;
+
+        $buffer = defined $buffer
+            ? $headers . $buffer : $headers;
     }
 
     return $self->$orig( $c, $buffer );