X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst.pm;h=3ef4bc867d75587a8a743b24da510e798bc42e22;hp=9592b812f4d7be884c4fcdd1b48ef403eff54aaa;hb=c017b11bf96db335cf4efce1808d56d13651b10a;hpb=12982f8623b4a3520146d4f52c5705d2b8a3b5ab diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index 9592b81..3ef4bc8 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -113,7 +113,6 @@ our $START = time; our $RECURSION = 1000; our $DETACH = Catalyst::Exception::Detach->new; our $GO = Catalyst::Exception::Go->new; -our $DEFAULT_ENCODE_CONTENT_TYPE_MATCH = qr{text|xml$|javascript$}; #I imagine that very few of these really need to be class variables. if any. #maybe we should just make them attributes with a default? @@ -130,7 +129,7 @@ __PACKAGE__->stats_class('Catalyst::Stats'); __PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC); # Remember to update this in Catalyst::Runtime as well! -our $VERSION = '5.90079_003'; +our $VERSION = '5.90079_004'; $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases sub import { @@ -1014,12 +1013,31 @@ And later: Your log class should implement the methods described in L. +=head2 has_encoding + +Returned True if there's a valid encoding + +=head2 clear_encoding + +Clears the encoding for the current context + =head2 encoding Sets or gets the application encoding. =cut +sub has_encoding { shift->encoding ? 1:0 } + +sub clear_encoding { + my $c = shift; + if(blessed $c) { + $c->encoding(undef); + } else { + $c->debug->error("You can't clear encoding on the application"); + } +} + sub encoding { my $c = shift; my $encoding; @@ -2050,25 +2068,10 @@ sub finalize_headers { $c->finalize_cookies; + # This currently is a NOOP but I don't want to remove it since I guess people + # might have Response subclasses that use it for something... (JNAP) $c->response->finalize_headers(); - if(my $enc = $c->encoding) { - my ($ct, $ct_enc) = $c->response->content_type; - - # Only touch 'text-like' contents - if($c->response->content_type =~ /$DEFAULT_ENCODE_CONTENT_TYPE_MATCH/) { - if ($ct_enc && $ct_enc =~ /charset=([^;]*)/) { - if (uc($1) ne uc($enc->mime_name)) { - $c->log->debug("Catalyst encoding config is set to encode in '" . - $enc->mime_name . - "', content type is '$1', not encoding "); - } - } else { - $c->res->content_type($c->res->content_type . "; charset=" . $enc->mime_name); - } - } - } - # Done $response->finalized_headers(1); } @@ -2079,26 +2082,44 @@ Make sure your body is encoded properly IF you set an encoding. By default the encoding is UTF-8 but you can disable it by explictly setting the encoding configuration value to undef. +We can only encode when the body is a scalar. Methods for encoding via the +streaming interfaces (such as C and C on L +are available). + See L. =cut sub finalize_encoding { my $c = shift; + my $res = $c->res || return; + + # Warn if the set charset is different from the one you put into encoding. We need + # to do this early since encodable_response is false for this condition and we need + # to match the debug output for backcompat (there's a test for this...) -JNAP + if( + $res->content_type_charset and $c->encoding and + (uc($c->encoding->mime_name) ne uc($res->content_type_charset)) + ) { + my $ct = lc($res->content_type_charset); + $c->log->debug("Catalyst encoding config is set to encode in '" . + $c->encoding->mime_name . + "', content type is '$ct', not encoding "); + } - my $body = $c->response->body; - - return unless defined($body); - - my $enc = $c->encoding; - - return unless $enc; - - # Only touch 'text-like' contents - if($c->response->content_type =~ /$DEFAULT_ENCODE_CONTENT_TYPE_MATCH/) { - if (ref(\$body) eq 'SCALAR') { - $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) ); - } + if( + ($res->encodable_response) and + (defined($res->body)) and + (ref(\$res->body) eq 'SCALAR') + ) { + $c->res->body( $c->encoding->encode( $c->res->body, $c->_encode_check ) ); + + # 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 + $c->res->content_type($c->res->content_type . "; charset=" . $c->encoding->mime_name) + unless($c->res->content_type_charset); } } @@ -4007,20 +4028,27 @@ matches the following regular expression: $content_type =~ /^text|xml$|javascript$/ -The value of this regex is contained in the global variable - - $Catalyst::DEFAULT_ENCODE_CONTENT_TYPE_MATCH +Encoding is set on the application, but it is copied to the response object +so you can override encoding rules per request (See L +for more information). -This may change in the future. Be default we don't automatically -encode 'application/json' since the most popular JSON encoders (such -as L which is the library that L can make use -of) will do the UTF8 encoding and decoding automatically. Having it on -in Catalyst could result in double encoding. +Be default we don't automatically encode 'application/json' since the most +popular JSON encoders (such as L which is the library that +L can make use of) will do the UTF8 encoding and decoding automatically. +Having it on in Catalyst could result in double encoding. If you are producing JSON response in an unconventional manner (such as via a template or manual strings) you should perform the UTF8 encoding manually as well such as to conform to the JSON specification. +NOTE: We also examine the value of $c->response->content_encoding. If +you set this (like for example 'gzip', and manually gzipping the body) +we assume that you have done all the neccessary encoding yourself, since +we cannot encode the gzipped contents. If you use a plugin like +L we will be updating that plugin to work +with the new UTF8 encoding code, or you can use L +or (probably best) do your compression on a front end proxy. + =head2 Methods =over 4