list the authordeps in a cpanfile for easier installation
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
index 559f76b..9e7d156 100644 (file)
@@ -23,6 +23,7 @@ use Path::Class::File ();
 use URI ();
 use URI::http;
 use URI::https;
+use HTML::Entities;
 use Tree::Simple qw/use_weak_refs/;
 use Tree::Simple::Visitor::FindByUID;
 use Class::C3::Adopt::NEXT;
@@ -52,20 +53,30 @@ has request => (
     is => 'rw',
     default => sub {
         my $self = shift;
-        my %p = ( _log => $self->log );
-        $p{_uploadtmp} = $self->_uploadtmp if $self->_has_uploadtmp;
-        $self->request_class->new(\%p);
+        $self->request_class->new($self->_build_request_constructor_args);
     },
     lazy => 1,
 );
+sub _build_request_constructor_args {
+    my $self = shift;
+    my %p = ( _log => $self->log );
+    $p{_uploadtmp} = $self->_uploadtmp if $self->_has_uploadtmp;
+    \%p;
+}
+
 has response => (
     is => 'rw',
     default => sub {
         my $self = shift;
-        $self->response_class->new({ _log => $self->log });
+        $self->response_class->new($self->_build_response_constructor_args);
     },
     lazy => 1,
 );
+sub _build_response_constructor_args {
+    my $self = shift;
+    { _log => $self->log };
+}
+
 has namespace => (is => 'rw');
 
 sub depth { scalar @{ shift->stack || [] }; }
@@ -102,7 +113,7 @@ __PACKAGE__->stats_class('Catalyst::Stats');
 
 # Remember to update this in Catalyst::Runtime as well!
 
-our $VERSION = '5.90015';
+our $VERSION = '5.90042';
 
 sub import {
     my ( $class, @arguments ) = @_;
@@ -256,9 +267,9 @@ MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used.
 
 If none of these are set, Catalyst will attempt to automatically detect the
 home directory. If you are working in a development environment, Catalyst
-will try and find the directory containing either Makefile.PL, Build.PL or
-dist.ini. If the application has been installed into the system (i.e.
-you have done C<make install>), then Catalyst will use the path to your
+will try and find the directory containing either Makefile.PL, Build.PL,
+dist.ini, or cpanfile. If the application has been installed into the system
+(i.e. you have done C<make install>), then Catalyst will use the path to your
 application module, without the .pm extension (e.g., /foo/MyApp if your
 application was installed at /foo/MyApp.pm)
 
@@ -1331,9 +1342,13 @@ sub uri_for {
     my $args = join('/', grep { defined($_) } @args);
     $args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
     $args =~ s!^/+!!;
-    my $base = $c->req->base;
-    my $class = ref($base);
-    $base =~ s{(?<!/)$}{/};
+
+    my ($base, $class) = ('/', 'URI::_generic');
+    if(blessed($c)) {
+      $base = $c->req->base;
+      $class = ref($base);
+      $base =~ s{(?<!/)$}{/};
+    }
 
     my $query = '';
 
@@ -1778,6 +1793,14 @@ sub finalize {
         $c->log->error($error);
     }
 
+    # Support skipping finalize for psgix.io style 'jailbreak'.  Used to support
+    # stuff like cometd and websockets
+    
+    if($c->request->has_io_fh) {
+      $c->log_response;
+      return;
+    }
+
     # Allow engine to handle finalize flow (for POE)
     my $engine = $c->engine;
     if ( my $code = $engine->can('finalize') ) {
@@ -1805,7 +1828,7 @@ sub finalize {
     $c->log_response;
 
     if ($c->use_stats) {
-        my $elapsed = sprintf '%f', $c->stats->elapsed;
+        my $elapsed = $c->stats->elapsed;
         my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
         $c->log->info(
             "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
@@ -1859,6 +1882,7 @@ sub finalize_headers {
 
         if ( !$response->has_body ) {
             # Add a default body if none is already present
+            my $encoded_location = encode_entities($location);
             $response->body(<<"EOF");
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml"> 
@@ -1866,7 +1890,7 @@ sub finalize_headers {
     <title>Moved</title>
   </head>
   <body>
-     <p>This item has moved <a href="$location">here</a>.</p>
+     <p>This item has moved <a href="$encoded_location">here</a>.</p>
   </body>
 </html>
 EOF
@@ -2958,10 +2982,26 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
         return $class;
     }
 
+    sub _default_plugins { return qw(Unicode::Encoding) }
+
     sub setup_plugins {
         my ( $class, $plugins ) = @_;
 
         $class->_plugins( {} ) unless $class->_plugins;
+        $plugins = [ grep {
+            m/Unicode::Encoding/ ? do {
+                $class->log->warn(
+                    'Unicode::Encoding plugin is auto-applied,'
+                    . ' please remove this from your appclass'
+                    . ' and make sure to define "encoding" config'
+                );
+                unless (exists $class->config->{'encoding'}) {
+                  $class->config->{'encoding'} = 'UTF-8';
+                }
+                () }
+                : $_
+        } @$plugins ];
+        push @$plugins, $class->_default_plugins;
         $plugins = Data::OptList::mkopt($plugins || []);
 
         my @plugins = map {
@@ -3153,12 +3193,33 @@ is having paths rewritten into it (e.g. as a .cgi/fcgi in a public_html director
 at other URIs than that which the app is 'normally' based at with C<mod_rewrite>), the resolution of
 C<< $c->request->base >> will be incorrect.
 
-=back
+=back 
 
 =item *
 
 C<using_frontend_proxy> - See L</PROXY SUPPORT>.
 
+=item *
+
+C<encoding> - See L</ENCODING>
+
+=item *
+
+C<abort_chain_on_error_fix>
+
+When there is an error in an action chain, the default behavior is to continue
+processing the remaining actions and then catch the error upon chain end.  This
+can lead to running actions when the application is in an unexpected state.  If
+you have this issue, setting this config value to true will promptly exit a
+chain when there is an error raised in any action (thus terminating the chain 
+early.)
+
+use like:
+
+    __PACKAGE__->config(abort_chain_on_error_fix => 1);
+
+In the future this might become the default behavior.
+
 =back
 
 =head1 INTERNAL ACTIONS
@@ -3250,6 +3311,53 @@ If you plan to operate in a threaded environment, remember that all other
 modules you are using must also be thread-safe. Some modules, most notably
 L<DBD::SQLite>, are not thread-safe.
 
+=head1 ENCODING
+
+On request, decodes all params from encoding into a sequence of
+logical characters. On response, encodes body into encoding.
+
+=head2 Methods
+
+=over 4
+
+=item encoding
+
+Returns an instance of an C<Encode> encoding
+
+    print $c->encoding->name
+
+=item handle_unicode_encoding_exception ($exception_context)
+
+Method called when decoding process for a request fails.
+
+An C<$exception_context> hashref is provided to allow you to override the
+behaviour of your application when given data with incorrect encodings.
+
+The default method throws exceptions in the case of invalid request parameters
+(resulting in a 500 error), but ignores errors in upload filenames.
+
+The keys passed in the C<$exception_context> hash are:
+
+=over
+
+=item param_value
+
+The value which was not able to be decoded.
+
+=item error_msg
+
+The exception received from L<Encode>.
+
+=item encoding_step
+
+What type of data was being decoded. Valid values are (currently)
+C<params> - for request parameters / arguments / captures
+and C<uploads> - for request upload filenames.
+
+=back
+
+=back
+
 =head1 SUPPORT
 
 IRC:
@@ -3377,6 +3485,8 @@ marcus: Marcus Ramberg <mramberg@cpan.org>
 
 miyagawa: Tatsuhiko Miyagawa <miyagawa@bulknews.net>
 
+mgrimes: Mark Grimes <mgrimes@cpan.org>
+
 mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
 
 mugwump: Sam Vilain
@@ -3421,7 +3531,7 @@ Will Hawes C<info@whawes.co.uk>
 
 willert: Sebastian Willert <willert@cpan.org>
 
-wreis: Wallace Reis <wallace@reis.org.br>
+wreis: Wallace Reis <wreis@cpan.org>
 
 Yuval Kogman, C<nothingmuch@woobling.org>