# This file documents the revision history for Perl extension Catalyst.
+5.90093 - 2015-05-29
+ - Fixed a bug where if you used $res->write and then $res->body, the
+ contents of body would be double encoded (gshank++).
+
5.90092 - 2015-05-19
- Allows you to use a namespace suffix for request, response and stats
class traits. Docs and tests for this.
__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90092';
+our $VERSION = '5.90093';
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
sub import {
# 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));
}
}
}
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 );
}
}
$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 >>.
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;
# Remember to update this in Catalyst as well!
-our $VERSION = '5.90092';
+our $VERSION = '5.90093';
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
=head1 NAME
response. However since you've already started streaming this will not show up as an HTTP error
status code, but rather error information in your body response and an error in your logs.
+B<NOTE> If you use ->body AFTER using ->write (for example you may do this to write your HTML
+HEAD information as fast as possible) we expect the contents to body to be encoded as it
+normally would be if you never called ->write. In general unless you are doing weird custom
+stuff with encoding this is likely to just already do the correct thing.
+
The second way to stream a response is to get the response writer object and invoke methods
on that directly:
$c->response->body($contents);
}
+ sub write_then_body :Local {
+ my ($self, $c) = @_;
+
+ $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>");
+ }
+
sub file_upload :POST Consumes(Multipart) Local {
my ($self, $c) = @_;
Test::More::is $c->req->body_parameters->{'♥'}, '♥♥';
}
{
+ my $res = request "/root/write_then_body";
+
+ is $res->code, 200, 'OK';
+ is decode_utf8($res->content), "<p>This is early_write action ♥</p><p>This is body_write action ♥</p>";
+ is $res->content_charset, 'UTF-8';
+}
+
+{
ok my $path = File::Spec->catfile('t', 'utf8.txt');
ok my $req = POST '/root/file_upload',
Content_Type => 'form-data',