more tests for utf8 and docs
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
index 141099c..9592b81 100644 (file)
@@ -86,8 +86,10 @@ has response => (
     lazy => 1,
 );
 sub _build_response_constructor_args {
-    my $self = shift;
-    { _log => $self->log };
+    return +{
+      _log => $_[0]->log,
+      encoding => $_[0]->encoding,
+    };
 }
 
 has namespace => (is => 'rw');
@@ -111,6 +113,7 @@ 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?
@@ -127,7 +130,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.90080_001';
+our $VERSION = '5.90079_003';
 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
 
 sub import {
@@ -1333,6 +1336,8 @@ sub setup_finalize {
 
 =head2 $c->uri_for( $action, \@captures?, @args?, \%query_values? )
 
+=head2 $c->uri_for( $action, [@captures, @args], \%query_values? )
+
 Constructs an absolute L<URI> object based on the application root, the
 provided path, and the additional arguments and query parameters provided.
 When used as a string, provides a textual URI.  If you need more flexibility
@@ -1372,6 +1377,10 @@ path, use C<< $c->uri_for_action >> instead.
   # Path to a static resource
   $c->uri_for('/static/images/logo.png');
 
+In general the scheme of the generated URI object will follow the incoming request
+however if your targeted action or action chain has the Scheme attribute it will
+use that instead.
+
 =cut
 
 sub uri_for {
@@ -1407,6 +1416,7 @@ sub uri_for {
       }
     }
 
+    my $target_action = $path->$_isa('Catalyst::Action') ? $path : undef;
     if ( $path->$_isa('Catalyst::Action') ) { # action object
         s|/|%2F|g for @encoded_args;
         my $captures = [ map { s|/|%2F|g; $_; }
@@ -1418,7 +1428,6 @@ sub uri_for {
         # ->uri_for( $action, \@captures_and_args, \%query_values? )
         if( !@encoded_args && $action->number_of_args ) {
             my $expanded_action = $c->dispatcher->expand_action( $action );
-
             my $num_captures = $expanded_action->number_of_captures;
             unshift @encoded_args, splice @$captures, $num_captures;
         }
@@ -1450,7 +1459,19 @@ sub uri_for {
     my ($base, $class) = ('/', 'URI::_generic');
     if(blessed($c)) {
       $base = $c->req->base;
-      $class = ref($base);
+      if($target_action) {
+        $target_action = $c->dispatcher->expand_action($target_action);
+        if(my $s = $target_action->scheme) {
+          $s = lc($s);
+          $class = "URI::$s";
+          $base->scheme($s);
+        } else {
+          $class = ref($base);
+        }
+      } else {
+        $class = ref($base);
+      }
+
       $base =~ s{(?<!/)$}{/};
     }
 
@@ -2035,7 +2056,7 @@ sub finalize_headers {
        my ($ct, $ct_enc) = $c->response->content_type;
 
         # Only touch 'text-like' contents
-        if($c->response->content_type =~ /^text|xml$|javascript$/) {
+        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 '" .
@@ -2074,7 +2095,7 @@ sub finalize_encoding {
     return unless $enc;
 
     # Only touch 'text-like' contents
-    if($c->response->content_type =~ /^text|xml$|javascript$/) {
+    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 ) );
       }
@@ -3980,6 +4001,26 @@ logical characters. On response, encodes body into encoding.
 By default encoding is now 'UTF-8'.  You may turn it off by setting
 the encoding configuration to undef.
 
+Encoding is automatically applied when the content-type is set to
+a type that can be encoded.  Currently we encode when the content type
+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
+
+This may change in the future.  Be default we don't automatically
+encode 'application/json' since the most popular JSON encoders (such
+as L<JSON::MaybeXS> which is the library that L<Catalyst> 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.
+
 =head2 Methods
 
 =over 4