# This file documents the revision history for Perl extension Catalyst.
-TDB
+5.90079_008 - 2015-01-07
+ - If we get a response set from $res->from_psgi_response and that response
+ has a charset for the content type, we clear encoding for the rest of the
+ response (avoid double encoding).
+ -
+
+5.90079_007 - 2015-01-07
- Merged from Stable (5.90079)
- reviewed and cleaned up UTF8 related docs
- replace missing utf8 pragma in Catalyst::Engine
my ($status, $headers, $body) = @$psgi_res;
$self->status($status);
$self->headers(HTTP::Headers->new(@$headers));
- $self->body($body);
+ $self->body(join('', @$body));
} elsif(ref $psgi_res eq 'CODE') {
$psgi_res->(sub {
my $response = shift;
$self->status($status);
$self->headers(HTTP::Headers->new(@$headers));
if(defined $maybe_body) {
- $self->body($maybe_body);
+ $self->body(join('', @$maybe_body));
} else {
return $self->write_fh;
}
} else {
die "You can't set a Catalyst response from that, expect a valid PSGI response";
}
+
+ # Encoding compatibilty. If the response set a charset, well... we need
+ # to assume its properly encoded and NOT encode for this response. Otherwise
+ # We risk double encoding.
+ if($self->content_type_charset) {
+ $self->_context->clear_encoding;
+ }
}
=head1 NAME
return 0 unless $self->_context; # Cases like returning a HTTP Exception response you don't have a context here...
return 0 unless $self->_context->encoding;
+ # The response is considered to have a 'manual charset' when a charset is already set on
+ # the content type of the response AND it is not the same as the one we set in encoding.
+ # If there is no charset OR we are asking for the one which is the same as the current
+ # required encoding, that is a flag that we want Catalyst to encode the response automatically.
my $has_manual_charset = 0;
if(my $charset = $self->content_type_charset) {
$has_manual_charset = (uc($charset) ne uc($self->_context->encoding->mime_name)) ? 1:0;
}
+ # Content type is encodable if it matches the regular expression stored in this attribute
+ my $encodable_content_type = $self->content_type =~ m/${\$self->encodable_content_type}/ ? 1:0;
+
+ # The content encoding is allowed (for charset encoding) only if its empty or is set to identity
+ my $allowed_content_encoding = (!$self->content_encoding || $self->content_encoding eq 'identity') ? 1:0;
+
+ # The content type must be an encodable type, and there must be NO manual charset and also
+ # the content encoding must be the allowed values;
if(
- ($self->content_type =~ m/${\$self->encodable_content_type}/) and
- (!$has_manual_charset) and
- (!$self->content_encoding || $self->content_encoding eq 'identity' )
- ) {
+ $encodable_content_type and
+ !$has_manual_charset and
+ $allowed_content_encoding
+ ) {
return 1;
} else {
return 0;
use strict;
use Test::More;
use HTTP::Request::Common;
+use HTTP::Message::PSGI ();
use Encode 2.21 'decode_utf8', 'encode_utf8';
use File::Spec;
use JSON::MaybeXS;
$c->response->write("<p>This is stream_write action ♥</p>");
}
+ sub from_external_psgi :Local {
+ my ($self, $c) = @_;
+ my $env = HTTP::Message::PSGI::req_to_psgi( HTTP::Request::Common::GET '/root/♥');
+ $c->res->from_psgi_response( ref($c)->to_app->($env));
+ }
+
package MyApp;
use Catalyst;
like decode_utf8($res->content), qr[<p>This is stream_write action ♥</p><!DOCTYPE html], 'correct body';
}
+{
+ my $res = request "/root/from_external_psgi";
+
+ is $res->code, 200, 'OK';
+ is decode_utf8($res->content), '<p>This is path-heart action ♥</p>', 'correct body';
+ is $res->content_length, 36, 'correct length';
+ is $res->content_charset, 'UTF-8';
+}
## should we use binmode on filehandles to force the encoding...?
## Not sure what else to do with multipart here, if docs are enough...