when finalizing body after earlier write use unencoded_write
Gerda Shank [Thu, 28 May 2015 18:55:23 +0000 (14:55 -0400)]
lib/Catalyst.pm
lib/Catalyst/Engine.pm
lib/Catalyst/Response.pm
t/utf_incoming.t

index 1512c12..59f6167 100644 (file)
@@ -2228,9 +2228,10 @@ sub finalize_encoding {
         # Set the charset if necessary.  This might be a bit bonkers since encodable response
         # is false when the set charset is not the same as the encoding mimetype (maybe 
         # confusing action at a distance here..
-        # Don't try to set the charset if one already exists
+        # Don't try to set the charset if one already exists or if headers are already finalized
         $c->res->content_type($c->res->content_type . "; charset=" . $c->encoding->mime_name)
-          unless($c->res->content_type_charset);
+          unless($c->res->content_type_charset ||
+                ($c->res->_context && $c->res->finalized_headers && !$c->res->_has_response_cb));
     }
 }
 
index e4deb9e..5e87e9f 100644 (file)
@@ -159,11 +159,11 @@ sub finalize_body {
           }
           else {
               
-              # Case where body was set afgter calling ->write.  We'd prefer not to
+              # Case where body was set after calling ->write.  We'd prefer not to
               # support this, but I can see some use cases with the way most of the
-              # views work.
-
-              $self->write($c, $body );
+              # views work. Since body has already been encoded, we need to do
+              # an 'unencoded_write' here.
+              $self->unencoded_write( $c, $body );
           }
         }
 
@@ -700,6 +700,20 @@ sub write {
     $c->response->write($buffer);
 }
 
+=head2 $self->unencoded_write($c, $buffer)
+
+Writes the buffer to the client without encoding. Necessary for
+already encoded buffers. Used when a $c->write has been done
+followed by $c->res->body.
+
+=cut
+
+sub unencoded_write {
+    my ( $self, $c, $buffer ) = @_;
+
+    $c->response->unencoded_write($buffer);
+}
+
 =head2 $self->read($c, [$maxlength])
 
 Reads from the input stream by calling C<< $self->read_chunk >>.
index eb99ab7..fa15afb 100644 (file)
@@ -134,6 +134,20 @@ sub write {
     return $len;
 }
 
+sub unencoded_write {
+    my ( $self, $buffer ) = @_;
+
+    # Finalize headers if someone manually writes output
+    $self->_context->finalize_headers unless $self->finalized_headers;
+
+    $buffer = q[] unless defined $buffer;
+
+    my $len = length($buffer);
+    $self->_writer->write($buffer);
+
+    return $len;
+}
+
 sub finalize_headers {
     my ($self) = @_;
     return;
index 6c0205d..ff61a6b 100644 (file)
@@ -113,8 +113,8 @@ use Scalar::Util ();
 
   sub write_then_body :Local {
     my ($self, $c) = @_;
-    $c->clear_encoding;
-    $c->res->content_type('text/plain');
+
+    $c->res->content_type('text/html');
     $c->res->write("<p>This is early_write action ♥</p>");
     $c->res->body("<p>This is body_write action ♥</p>");
   }