X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst%2FResponse.pm;h=74d59fe87b7e719469646624c8a1ff151c347f45;hp=13a1f639d207d2a33c091407d194d6a4167e66cc;hb=67fd25bc03bc87a19db237a13fcb1cd157252101;hpb=688e2420d1731666afab58c3e8dcfc1cffd6c2d1 diff --git a/lib/Catalyst/Response.pm b/lib/Catalyst/Response.pm index 13a1f63..74d59fe 100644 --- a/lib/Catalyst/Response.pm +++ b/lib/Catalyst/Response.pm @@ -148,7 +148,10 @@ sub from_psgi_response { my ($status, $headers, $body) = @$psgi_res; $self->status($status); $self->headers(HTTP::Headers->new(@$headers)); - $self->body($body); + # Can be arrayref or filehandle... + if(defined $body) { # probably paranoia + ref $body eq 'ARRAY' ? $self->body(join('', @$body)) : $self->body($body); + } } elsif(ref $psgi_res eq 'CODE') { $psgi_res->(sub { my $response = shift; @@ -156,7 +159,8 @@ sub from_psgi_response { $self->status($status); $self->headers(HTTP::Headers->new(@$headers)); if(defined $maybe_body) { - $self->body($maybe_body); + # Can be arrayref or filehandle... + ref $maybe_body eq 'ARRAY' ? $self->body(join('', @$maybe_body)) : $self->body($maybe_body); } else { return $self->write_fh; } @@ -164,6 +168,15 @@ sub from_psgi_response { } 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) { + # We have to do this since for backcompat reasons having a charset doesn't always + # mean that the body is already encoded :( + $self->_context->clear_encoding; + } } =head1 NAME @@ -542,7 +555,13 @@ Example: } Please note this does not attempt to map or nest your PSGI application under -the Controller and Action namespace or path. +the Controller and Action namespace or path. You may wish to review 'PSGI Helpers' +under L for help in properly nesting applications. + +B If your external PSGI application returns a response that has a character +set associated with the content type (such as "text/html; charset=UTF-8") we set +$c->clear_encoding to remove any additional content type encoding processing later +in the application (this is done to avoid double encoding issues). =head2 encodable_content_type @@ -589,16 +608,28 @@ sub encodable_response { 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;