fixed docs
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
index fd57ca6..64c097c 100644 (file)
@@ -4,7 +4,7 @@ use Moose;
 use Moose::Meta::Class ();
 extends 'Catalyst::Component';
 use Moose::Util qw/find_meta/;
-use B::Hooks::EndOfScope ();
+use namespace::clean -except => 'meta';
 use Catalyst::Exception;
 use Catalyst::Exception::Detach;
 use Catalyst::Exception::Go;
@@ -16,7 +16,6 @@ use Catalyst::Utils;
 use Catalyst::Controller;
 use Data::OptList;
 use Devel::InnerPackage ();
-use File::stat;
 use Module::Pluggable::Object ();
 use Text::SimpleTable ();
 use Path::Class::Dir ();
@@ -24,24 +23,109 @@ 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;
 use List::MoreUtils qw/uniq/;
 use attributes;
+use String::RewritePrefix;
+use Catalyst::EngineLoader;
 use utf8;
 use Carp qw/croak carp shortmess/;
-
-BEGIN { require 5.008004; }
+use Try::Tiny;
+use Safe::Isa;
+use Moose::Util 'find_meta';
+use Plack::Middleware::Conditional;
+use Plack::Middleware::ReverseProxy;
+use Plack::Middleware::IIS6ScriptNameFix;
+use Plack::Middleware::IIS7KeepAliveFix;
+use Plack::Middleware::LighttpdScriptNameFix;
+use Plack::Middleware::ContentLength;
+use Plack::Middleware::Head;
+use Plack::Middleware::HTTPExceptions;
+use Plack::Middleware::FixMissingBodyInRedirect;
+use Plack::Middleware::MethodOverride;
+use Plack::Middleware::RemoveRedundantBody;
+use Catalyst::Middleware::Stash;
+use Plack::Util;
+use Class::Load 'load_class';
+use Encode 2.21 'decode_utf8', 'encode_utf8';
+
+BEGIN { require 5.008003; }
 
 has stack => (is => 'ro', default => sub { [] });
-has stash => (is => 'rw', default => sub { {} });
 has state => (is => 'rw', default => 0);
 has stats => (is => 'rw');
 has action => (is => 'rw');
 has counter => (is => 'rw', default => sub { {} });
-has request => (is => 'rw', default => sub { $_[0]->request_class->new({}) }, required => 1, lazy => 1);
-has response => (is => 'rw', default => sub { $_[0]->response_class->new({}) }, required => 1, lazy => 1);
+has request => (
+    is => 'rw',
+    default => sub {
+        my $self = shift;
+        my $class = ref $self;
+        my $composed_request_class = $class->composed_request_class;
+        return $composed_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{data_handlers} = {$self->registered_data_handlers};
+    $p{_use_hash_multivalue} = $self->config->{use_hash_multivalue_in_request}
+      if $self->config->{use_hash_multivalue_in_request};
+    \%p;
+}
+
+sub composed_request_class {
+  my $class = shift;
+  my @traits = (@{$class->request_class_traits||[]}, @{$class->config->{request_class_traits}||[]});
+
+  # For each trait listed, figure out what the namespace is.  First we try the $trait
+  # as it is in the config.  Then try $MyApp::TraitFor::Request:$trait. Last we try
+  # Catalyst::TraitFor::Request::$trait.  If none load, throw error.
+
+  my $trait_ns = 'TraitFor::Request';
+  my @normalized_traits = map {
+    Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
+  } @traits;
+
+  return $class->_composed_request_class ||
+    $class->_composed_request_class(Moose::Util::with_traits($class->request_class, @normalized_traits));
+}
+
+has response => (
+    is => 'rw',
+    default => sub {
+        my $self = shift;
+        my $class = ref $self;
+        my $composed_response_class = $class->composed_response_class;
+        return $composed_response_class->new( $self->_build_response_constructor_args);
+    },
+    lazy => 1,
+);
+sub _build_response_constructor_args {
+    return +{
+      _log => $_[0]->log,
+      encoding => $_[0]->encoding,
+    };
+}
+
+sub composed_response_class {
+  my $class = shift;
+  my @traits = (@{$class->response_class_traits||[]}, @{$class->config->{response_class_traits}||[]});
+
+  my $trait_ns = 'TraitFor::Response';
+  my @normalized_traits = map {
+    Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
+  } @traits;
+
+  return $class->_composed_response_class ||
+    $class->_composed_response_class(Moose::Util::with_traits($class->response_class, @normalized_traits));
+}
+
 has namespace => (is => 'rw');
 
 sub depth { scalar @{ shift->stack || [] }; }
@@ -64,22 +148,40 @@ our $RECURSION = 1000;
 our $DETACH    = Catalyst::Exception::Detach->new;
 our $GO        = Catalyst::Exception::Go->new;
 
-#I imagine that very few of these really need to be class variables. if any.
+#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?
 __PACKAGE__->mk_classdata($_)
   for qw/components arguments dispatcher engine log dispatcher_class
-  engine_class context_class request_class response_class stats_class
-  setup_finished/;
+  engine_loader context_class request_class response_class stats_class
+  setup_finished _psgi_app loading_psgi_file run_options _psgi_middleware
+  _data_handlers _encoding _encode_check finalized_default_middleware
+  request_class_traits response_class_traits stats_class_traits
+  _composed_request_class _composed_response_class _composed_stats_class/;
 
 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
-__PACKAGE__->engine_class('Catalyst::Engine::CGI');
 __PACKAGE__->request_class('Catalyst::Request');
 __PACKAGE__->response_class('Catalyst::Response');
 __PACKAGE__->stats_class('Catalyst::Stats');
 
-# Remember to update this in Catalyst::Runtime as well!
+sub composed_stats_class {
+  my $class = shift;
+  my @traits = (@{$class->stats_class_traits||[]}, @{$class->config->{stats_class_traits}||[]});
 
-our $VERSION = '5.80033';
+  my $trait_ns = 'TraitFor::Stats';
+  my @normalized_traits = map {
+    Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
+  } @traits;
+
+  return $class->_composed_stats_class ||
+    $class->_composed_stats_class(Moose::Util::with_traits($class->stats_class, @normalized_traits));
+}
+
+__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
+
+# Remember to update this in Catalyst::Runtime as well!
+our $VERSION = '5.90096';
+$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
 
 sub import {
     my ( $class, @arguments ) = @_;
@@ -114,10 +216,17 @@ sub import {
 
 sub _application { $_[0] }
 
+=encoding UTF-8
+
 =head1 NAME
 
 Catalyst - The Elegant MVC Web Application Framework
 
+=for html
+<a href="https://badge.fury.io/pl/Catalyst-Runtime"><img src="https://badge.fury.io/pl/Catalyst-Runtime.svg" alt="CPAN version" height="18"></a>
+<a href="https://travis-ci.org/perl-catalyst/catalyst-runtime/"><img src="https://api.travis-ci.org/perl-catalyst/catalyst-runtime.png" alt="Catalyst></a>
+<a href="http://cpants.cpanauthors.org/dist/Catalyst-Runtime"><img src="http://cpants.cpanauthors.org/dist/Catalyst-Runtime.png" alt='Kwalitee Score' /></a>
+
 =head1 SYNOPSIS
 
 See the L<Catalyst::Manual> distribution for comprehensive
@@ -143,7 +252,7 @@ documentation and tutorials.
     use Catalyst qw/-Debug/; # include plugins here as well
 
     ### In lib/MyApp/Controller/Root.pm (autocreated)
-    sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
+    sub foo : Chained('/') Args() { # called for /foo, /foo/1, /foo/1/2, etc.
         my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
         $c->stash->{template} = 'foo.tt'; # set the template
         # lookup something from db -- stash vars are passed to TT
@@ -161,50 +270,16 @@ documentation and tutorials.
     [% END %]
 
     # called for /bar/of/soap, /bar/of/soap/10, etc.
-    sub bar : Path('/bar/of/soap') { ... }
-
-    # called for all actions, from the top-most controller downwards
-    sub auto : Private {
-        my ( $self, $c ) = @_;
-        if ( !$c->user_exists ) { # Catalyst::Plugin::Authentication
-            $c->res->redirect( '/login' ); # require login
-            return 0; # abort request and go immediately to end()
-        }
-        return 1; # success; carry on to next action
-    }
+    sub bar : Chained('/') PathPart('/bar/of/soap') Args() { ... }
 
     # called after all actions are finished
-    sub end : Private {
+    sub end : Action {
         my ( $self, $c ) = @_;
         if ( scalar @{ $c->error } ) { ... } # handle errors
         return if $c->res->body; # already have a response
         $c->forward( 'MyApp::View::TT' ); # render template
     }
 
-    ### in MyApp/Controller/Foo.pm
-    # called for /foo/bar
-    sub bar : Local { ... }
-
-    # called for /blargle
-    sub blargle : Global { ... }
-
-    # an index action matches /foo, but not /foo/1, etc.
-    sub index : Private { ... }
-
-    ### in MyApp/Controller/Foo/Bar.pm
-    # called for /foo/bar/baz
-    sub baz : Local { ... }
-
-    # first Root auto is called, then Foo auto, then this
-    sub auto : Private { ... }
-
-    # powerful regular expression paths are also possible
-    sub details : Regex('^product/(\w+)/details$') {
-        my ( $self, $c ) = @_;
-        # extract the (\w+) from the URI
-        my $product = $c->req->captures->[0];
-    }
-
 See L<Catalyst::Manual::Intro> for additional information.
 
 =head1 DESCRIPTION
@@ -231,7 +306,7 @@ fully qualify the name by using a unary plus:
         +Fully::Qualified::Plugin::Name
     /;
 
-Special flags like C<-Debug> and C<-Engine> can also be specified as
+Special flags like C<-Debug> can also be specified as
 arguments when Catalyst is loaded:
 
     use Catalyst qw/-Debug My::Module/;
@@ -251,13 +326,6 @@ priority.
 This sets the log level to 'debug' and enables full debug output on the
 error screen. If you only want the latter, see L<< $c->debug >>.
 
-=head2 -Engine
-
-Forces Catalyst to use a specific engine. Omit the
-C<Catalyst::Engine::> prefix of the engine name, i.e.:
-
-    use Catalyst qw/-Engine=CGI/;
-
 =head2 -Home
 
 Forces Catalyst to use a specific home directory, e.g.:
@@ -271,11 +339,11 @@ the name will be replaced with underscores, e.g. MyApp::Web should use
 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 envirnoment, 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
-application module, without the .pm extension (ie, /foo/MyApp if your
+home directory. If you are working in a development environment, Catalyst
+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)
 
 =head2 -Log
@@ -327,7 +395,18 @@ cookies, HTTP headers, etc.). See L<Catalyst::Request>.
 
 =head2 $c->forward( $class, $method, [, \@arguments ] )
 
-Forwards processing to another action, by its private name. If you give a
+This is one way of calling another action (method) in the same or
+a different controller. You can also use C<< $self->my_method($c, @args) >>
+in the same controller or C<< $c->controller('MyController')->my_method($c, @args) >>
+in a different controller.
+The main difference is that 'forward' uses some of the Catalyst request
+cycle overhead, including debugging, which may be useful to you. On the
+other hand, there are some complications to using 'forward', restrictions
+on values returned from 'forward', and it may not handle errors as you prefer.
+Whether you use 'forward' or not is up to you; it is not considered superior to
+the other ways to call a method.
+
+'forward' calls  another action, by its private name. If you give a
 class name but no method, C<process()> is called. You may also optionally
 pass arguments in an arrayref. The action will receive the arguments in
 C<@_> and C<< $c->req->args >>. Upon returning from the function,
@@ -343,9 +422,10 @@ call to forward.
 
 Note that L<< forward|/"$c->forward( $action [, \@arguments ] )" >> implies
 an C<< eval { } >> around the call (actually
-L<< execute|/"$c->execute( $class, $coderef )" >> does), thus de-fatalizing
-all 'dies' within the called action. If you want C<die> to propagate you
-need to do something like:
+L<< execute|/"$c->execute( $class, $coderef )" >> does), thus rendering all
+exceptions thrown by the called action non-fatal and pushing them onto
+$c->error instead. If you want C<die> to propagate you need to do something
+like:
 
     $c->forward('foo');
     die join "\n", @{ $c->error } if @{ $c->error };
@@ -391,8 +471,12 @@ When called with no arguments it escapes the processing chain entirely.
 
 sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
 
+=head2 $c->visit( $action [, \@arguments ] )
+
 =head2 $c->visit( $action [, \@captures, \@arguments ] )
 
+=head2 $c->visit( $class, $method, [, \@arguments ] )
+
 =head2 $c->visit( $class, $method, [, \@captures, \@arguments ] )
 
 Almost the same as L<< forward|/"$c->forward( $action [, \@arguments ] )" >>,
@@ -407,7 +491,7 @@ L<reverse|Catalyst::Action/reverse> return information for the visited action
 when they are invoked within the visited action.  This is different from the
 behavior of L<< forward|/"$c->forward( $action [, \@arguments ] )" >>, which
 continues to use the $c->action object from the caller action even when
-invoked from the callee.
+invoked from the called action.
 
 C<< $c->stash >> is kept unchanged.
 
@@ -421,8 +505,12 @@ transfer control to another action as if it had been reached directly from a URL
 
 sub visit { my $c = shift; $c->dispatcher->visit( $c, @_ ) }
 
+=head2 $c->go( $action [, \@arguments ] )
+
 =head2 $c->go( $action [, \@captures, \@arguments ] )
 
+=head2 $c->go( $class, $method, [, \@arguments ] )
+
 =head2 $c->go( $class, $method, [, \@captures, \@arguments ] )
 
 The relationship between C<go> and
@@ -466,23 +554,25 @@ Catalyst).
     # stash is automatically passed to the view for use in a template
     $c->forward( 'MyApp::View::TT' );
 
-=cut
+The stash hash is currently stored in the PSGI C<$env> and is managed by
+L<Catalyst::Middleware::Stash>.  Since it's part of the C<$env> items in
+the stash can be accessed in sub applications mounted under your main
+L<Catalyst> application.  For example if you delegate the response of an
+action to another L<Catalyst> application, that sub application will have
+access to all the stash keys of the main one, and if can of course add
+more keys of its own.  However those new keys will not 'bubble' back up
+to the main application.
 
-around stash => sub {
-    my $orig = shift;
-    my $c = shift;
-    my $stash = $orig->($c);
-    if (@_) {
-        my $new_stash = @_ > 1 ? {@_} : $_[0];
-        croak('stash takes a hash or hashref') unless ref $new_stash;
-        foreach my $key ( keys %$new_stash ) {
-          $stash->{$key} = $new_stash->{$key};
-        }
-    }
+For more information the best thing to do is to review the test case:
+t/middleware-stash.t in the distribution /t directory.
 
-    return $stash;
-};
+=cut
 
+sub stash {
+  my $c = shift;
+  $c->log->error("You are requesting the stash but you don't have a context") unless blessed $c;
+  return Catalyst::Middleware::Stash::get_stash($c->req->env)->(@_);
+}
 
 =head2 $c->error
 
@@ -500,6 +590,9 @@ Add a new error.
 
     $c->error('Something bad happened');
 
+Calling this will always return an arrayref (if there are no errors it
+will be an empty arrayref.
+
 =cut
 
 sub error {
@@ -536,6 +629,57 @@ sub clear_errors {
     $c->error(0);
 }
 
+=head2 $c->has_errors
+
+Returns true if you have errors
+
+=cut
+
+sub has_errors { scalar(@{shift->error}) ? 1:0 }
+
+=head2 $c->last_error
+
+Returns the most recent error in the stack (the one most recently added...)
+or nothing if there are no errors.  This does not modify the contents of the
+error stack.
+
+=cut
+
+sub last_error {
+  my (@errs) = @{shift->error};
+  return scalar(@errs) ? $errs[-1]: undef;
+}
+
+=head2 shift_errors
+
+shifts the most recently added error off the error stack and returns it.  Returns
+nothing if there are no more errors.
+
+=cut
+
+sub shift_errors {
+    my ($self) = @_;
+    my @errors = @{$self->error};
+    my $err = shift(@errors);
+    $self->{error} = \@errors;
+    return $err;
+}
+
+=head2 pop_errors
+
+pops the most recently added error off the error stack and returns it.  Returns
+nothing if there are no more errors.
+
+=cut
+
+sub pop_errors {
+    my ($self) = @_;
+    my @errors = @{$self->error};
+    my $err = pop(@errors);
+    $self->{error} = \@errors;
+    return $err;
+}
+
 sub _comp_search_prefixes {
     my $c = shift;
     return map $c->components->{ $_ }, $c->_comp_names_search_prefixes(@_);
@@ -555,13 +699,13 @@ sub _comp_names_search_prefixes {
     # undef for a name will return all
     return keys %eligible if !defined $name;
 
-    my $query  = ref $name ? $name : qr/^$name$/i;
+    my $query  = $name->$_isa('Regexp') ? $name : qr/^$name$/i;
     my @result = grep { $eligible{$_} =~ m{$query} } keys %eligible;
 
     return @result if @result;
 
     # if we were given a regexp to search against, we're done.
-    return if ref $name;
+    return if $name->$_isa('Regexp');
 
     # skip regexp fallback if configured
     return
@@ -618,13 +762,20 @@ sub _comp_names {
 }
 
 # Filter a component before returning by calling ACCEPT_CONTEXT if available
+
 sub _filter_component {
     my ( $c, $comp, @args ) = @_;
 
+    if(ref $comp eq 'CODE') {
+      $comp = $comp->();
+    }
+
     if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
-        return $comp->ACCEPT_CONTEXT( $c, @args );
+      return $comp->ACCEPT_CONTEXT( $c, @args );
     }
 
+    $c->log->warn("You called component '${\$comp->catalyst_component_name}' with arguments [@args], but this component does not ACCEPT_CONTEXT, so args are ignored.") if scalar(@args) && $c->debug;
+
     return $comp;
 }
 
@@ -652,7 +803,7 @@ sub controller {
 
     my $appclass = ref($c) || $c;
     if( $name ) {
-        unless ( ref($name) ) { # Direct component hash lookup to avoid costly regexps
+        unless ( $name->$_isa('Regexp') ) { # Direct component hash lookup to avoid costly regexps
             my $comps = $c->components;
             my $check = $appclass."::Controller::".$name;
             return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
@@ -671,7 +822,8 @@ Gets a L<Catalyst::Model> instance by name.
 
     $c->model('Foo')->do_stuff;
 
-Any extra arguments are directly passed to ACCEPT_CONTEXT.
+Any extra arguments are directly passed to ACCEPT_CONTEXT, if the model
+defines ACCEPT_CONTEXT.  If it does not, the args are discarded.
 
 If the name is omitted, it will look for
  - a model object in $c->stash->{current_model_instance}, then
@@ -690,7 +842,7 @@ sub model {
     my ( $c, $name, @args ) = @_;
     my $appclass = ref($c) || $c;
     if( $name ) {
-        unless ( ref($name) ) { # Direct component hash lookup to avoid costly regexps
+        unless ( $name->$_isa('Regexp') ) { # Direct component hash lookup to avoid costly regexps
             my $comps = $c->components;
             my $check = $appclass."::Model::".$name;
             return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
@@ -749,7 +901,7 @@ sub view {
 
     my $appclass = ref($c) || $c;
     if( $name ) {
-        unless ( ref($name) ) { # Direct component hash lookup to avoid costly regexps
+        unless ( $name->$_isa('Regexp') ) { # Direct component hash lookup to avoid costly regexps
             my $comps = $c->components;
             my $check = $appclass."::View::".$name;
             if( exists $comps->{$check} ) {
@@ -972,6 +1124,68 @@ And later:
 Your log class should implement the methods described in
 L<Catalyst::Log>.
 
+=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.  Setting encoding takes either an
+Encoding object or a string that we try to resolve via L<Encode::find_encoding>.
+
+You would expect to get the encoding object back if you attempt to set it.  If
+there is a failure you will get undef returned and an error message in the log.
+
+=cut
+
+sub has_encoding { shift->encoding ? 1:0 }
+
+sub clear_encoding {
+    my $c = shift;
+    if(blessed $c) {
+        $c->encoding(undef);
+    } else {
+        $c->log->error("You can't clear encoding on the application");
+    }
+}
+
+sub encoding {
+    my $c = shift;
+    my $encoding;
+
+    if ( scalar @_ ) {
+
+        # Don't let one change this once we are too far into the response
+        if(blessed $c && $c->res->finalized_headers) {
+          Carp::croak("You may not change the encoding once the headers are finalized");
+          return;
+        }
+
+        # Let it be set to undef
+        if (my $wanted = shift)  {
+            $encoding = Encode::find_encoding($wanted)
+              or Carp::croak( qq/Unknown encoding '$wanted'/ );
+            binmode(STDERR, ':encoding(' . $encoding->name . ')');
+        }
+        else {
+            binmode(STDERR);
+        }
+
+        $encoding = ref $c
+                  ? $c->{encoding} = $encoding
+                  : $c->_encoding($encoding);
+    } else {
+      $encoding = ref $c && exists $c->{encoding}
+                ? $c->{encoding}
+                : $c->_encoding;
+    }
+
+    return $encoding;
+}
 
 =head2 $c->debug
 
@@ -1030,26 +1244,11 @@ sub path_to {
     else { return Path::Class::File->new( $c->config->{home}, @path ) }
 }
 
-=head2 $c->plugin( $name, $class, @args )
-
-Helper method for plugins. It creates a class data accessor/mutator and
-loads and instantiates the given class.
-
-    MyApp->plugin( 'prototype', 'HTML::Prototype' );
-
-    $c->prototype->define_javascript_functions;
-
-B<Note:> This method of adding plugins is deprecated. The ability
-to add plugins like this B<will be removed> in a Catalyst 5.81.
-Please do not use this functionality in new code.
-
-=cut
-
 sub plugin {
     my ( $class, $name, $plugin, @args ) = @_;
 
     # See block comment in t/unit_core_plugin.t
-    $class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in Catalyst 5.81/);
+    $class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in a future release/);
 
     $class->_register_plugin( $plugin, 1 );
 
@@ -1078,6 +1277,20 @@ Catalyst> line.
     MyApp->setup;
     MyApp->setup( qw/-Debug/ );
 
+B<Note:> You B<should not> wrap this method with method modifiers
+or bad things will happen - wrap the C<setup_finalize> method instead.
+
+B<Note:> You can create a custom setup stage that will execute when the
+application is starting.  Use this to customize setup.
+
+    MyApp->setup(-Custom=value);
+
+    sub setup_custom {
+      my ($class, $value) = @_;
+    }
+
+Can be handy if you want to hook into the setup phase.
+
 =cut
 
 sub setup {
@@ -1116,8 +1329,13 @@ sub setup {
 
     $class->setup_log( delete $flags->{log} );
     $class->setup_plugins( delete $flags->{plugins} );
+
+    $class->setup_data_handlers();
     $class->setup_dispatcher( delete $flags->{dispatcher} );
-    $class->setup_engine( delete $flags->{engine} );
+    if (my $engine = delete $flags->{engine}) {
+        $class->log->warn("Specifying the engine in ->setup is no longer supported, see Catalyst::Upgrading");
+    }
+    $class->setup_engine();
     $class->setup_stats( delete $flags->{stats} );
 
     for my $flag ( sort keys %{$flags} ) {
@@ -1144,6 +1362,26 @@ You are running an old script!
 EOF
     }
 
+    # Call plugins setup, this is stupid and evil.
+    # Also screws C3 badly on 5.10, hack to avoid.
+    {
+        no warnings qw/redefine/;
+        local *setup = sub { };
+        $class->setup unless $Catalyst::__AM_RESTARTING;
+    }
+
+    # If you are expecting configuration info as part of your setup, it needs
+    # to get called here and below, since we need the above line to support
+    # ConfigLoader based configs.
+
+    $class->setup_encoding();
+    $class->setup_middleware();
+
+    # Initialize our data structure
+    $class->components( {} );
+
+    $class->setup_components;
+
     if ( $class->debug ) {
         my @plugins = map { "$_  " . ( $_->VERSION || '' ) } $class->registered_plugins;
 
@@ -1154,6 +1392,27 @@ EOF
             $class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" );
         }
 
+        my @middleware = map {
+          ref $_ eq 'CODE' ? 
+            "Inline Coderef" : 
+              (ref($_) .'  '. ($_->can('VERSION') ? $_->VERSION || '' : '') 
+                || '')  } $class->registered_middlewares;
+
+        if (@middleware) {
+            my $column_width = Catalyst::Utils::term_width() - 6;
+            my $t = Text::SimpleTable->new($column_width);
+            $t->row($_) for @middleware;
+            $class->log->debug( "Loaded PSGI Middleware:\n" . $t->draw . "\n" );
+        }
+
+        my %dh = $class->registered_data_handlers;
+        if (my @data_handlers = keys %dh) {
+            my $column_width = Catalyst::Utils::term_width() - 6;
+            my $t = Text::SimpleTable->new($column_width);
+            $t->row($_) for @data_handlers;
+            $class->log->debug( "Loaded Request Data Handlers:\n" . $t->draw . "\n" );
+        }
+
         my $dispatcher = $class->dispatcher;
         my $engine     = $class->engine;
         my $home       = $class->config->{home};
@@ -1166,23 +1425,9 @@ EOF
           ? $class->log->debug(qq/Found home "$home"/)
           : $class->log->debug(qq/Home "$home" doesn't exist/)
           : $class->log->debug(q/Couldn't find home/);
-    }
-
-    # Call plugins setup, this is stupid and evil.
-    # Also screws C3 badly on 5.10, hack to avoid.
-    {
-        no warnings qw/redefine/;
-        local *setup = sub { };
-        $class->setup unless $Catalyst::__AM_RESTARTING;
-    }
-
-    # Initialize our data structure
-    $class->components( {} );
 
-    $class->setup_components;
-
-    if ( $class->debug ) {
         my $column_width = Catalyst::Utils::term_width() - 8 - 9;
+
         my $t = Text::SimpleTable->new( [ $column_width, 'Class' ], [ 8, 'Type' ] );
         for my $comp ( sort keys %{ $class->components } ) {
             my $type = ref $class->components->{$comp} ? 'instance' : 'class';
@@ -1204,39 +1449,17 @@ EOF
         $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
     }
 
-    # Make sure that the application class becomes immutable at this point,
-    B::Hooks::EndOfScope::on_scope_end {
-        return if $@;
-        my $meta = Class::MOP::get_metaclass_by_name($class);
-        if (
-            $meta->is_immutable
-            && ! { $meta->immutable_options }->{replace_constructor}
-            && (
-                   $class->isa('Class::Accessor::Fast')
-                || $class->isa('Class::Accessor')
-            )
-        ) {
-            warn "You made your application class ($class) immutable, "
-                . "but did not inline the\nconstructor. "
-                . "This will break catalyst, as your app \@ISA "
-                . "Class::Accessor(::Fast)?\nPlease pass "
-                . "(replace_constructor => 1)\nwhen making your class immutable.\n";
-        }
-        $meta->make_immutable(
-            replace_constructor => 1,
-        ) unless $meta->is_immutable;
-    };
-
     if ($class->config->{case_sensitive}) {
         $class->log->warn($class . "->config->{case_sensitive} is set.");
         $class->log->warn("This setting is deprecated and planned to be removed in Catalyst 5.81.");
     }
 
     $class->setup_finalize;
-    # Should be the last thing we do so that user things hooking
-    # setup_finalize can log..
+
+    # Flush the log for good measure (in case something turned off 'autoflush' early)
     $class->log->_flush() if $class->log->can('_flush');
-    return 1; # Explicit return true as people have __PACKAGE__->setup as the last thing in their class. HATE.
+
+    return $class || 1; # Just in case someone named their Application 0...
 }
 
 =head2 $app->setup_finalize
@@ -1261,9 +1484,11 @@ sub setup_finalize {
     $class->setup_finished(1);
 }
 
-=head2 $c->uri_for( $path?, @args?, \%query_values? )
+=head2 $c->uri_for( $path?, @args?, \%query_values?, \$fragment? )
+
+=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values?, \$fragment? )
 
-=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values? )
+=head2 $c->uri_for( $action, [@captures, @args], \%query_values?, \$fragment? )
 
 Constructs an absolute L<URI> object based on the application root, the
 provided path, and the additional arguments and query parameters provided.
@@ -1304,12 +1529,20 @@ 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.
+
+Also, if the targeted Action or Action chain declares Args/CaptureArgs that have
+type constraints, we will require that your proposed URL verify on those declared
+constraints.
+
 =cut
 
 sub uri_for {
     my ( $c, $path, @args ) = @_;
 
-    if (blessed($path) && $path->isa('Catalyst::Controller')) {
+    if ( $path->$_isa('Catalyst::Controller') ) {
         $path = $path->path_prefix;
         $path =~ s{/+\z}{};
         $path .= '/';
@@ -1317,28 +1550,37 @@ sub uri_for {
 
     undef($path) if (defined $path && $path eq '');
 
+    my $fragment =  ((scalar(@args) && ref($args[-1]) eq 'SCALAR') ? pop @args : undef );
+
     my $params =
       ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
 
     carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
-    foreach my $arg (@args) {
-        utf8::encode($arg) if utf8::is_utf8($arg);
-        $arg =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
-    }
 
-    if ( blessed($path) ) { # action object
+    my $target_action = $path->$_isa('Catalyst::Action') ? $path : undef;
+    if ( $path->$_isa('Catalyst::Action') ) { # action object
         s|/|%2F|g for @args;
         my $captures = [ map { s|/|%2F|g; $_; }
                         ( scalar @args && ref $args[0] eq 'ARRAY'
                          ? @{ shift(@args) }
                          : ()) ];
 
-        foreach my $capture (@$captures) {
-            utf8::encode($capture) if utf8::is_utf8($capture);
-            $capture =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+        my $action = $path;
+        my $expanded_action = $c->dispatcher->expand_action( $action );
+        my $num_captures = $expanded_action->number_of_captures;
+
+        # ->uri_for( $action, \@captures_and_args, \%query_values? )
+        if( !@args && $action->number_of_args ) {
+          unshift @args, splice @$captures, $num_captures;
+        }
+
+        if($num_captures) {
+          unless($expanded_action->match_captures_constraints($c, $captures)) {
+            carp "captures [@{$captures}] do not match the type constraints in actionchain ending with '$expanded_action'";
+            return;
+          }
         }
 
-        my $action = $path;
         $path = $c->dispatcher->uri_for_action($action, $captures);
         if (not defined $path) {
             $c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
@@ -1346,6 +1588,14 @@ sub uri_for {
             return undef;
         }
         $path = '/' if $path eq '';
+
+        # At this point @encoded_args is the remaining Args (all captures removed).
+        if($expanded_action->has_args_constraints) {
+          unless($expanded_action->match_args($c,\@args)) {
+             carp "args [@args] do not match the type constraints in action '$expanded_action'";
+             return;
+          }
+        }
     }
 
     unshift(@args, $path);
@@ -1362,37 +1612,70 @@ 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 $query = '';
+    my ($base, $class) = ('/', 'URI::_generic');
+    if(blessed($c)) {
+      $base = $c->req->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{(?<!/)$}{/};
+    }
 
+    my $query = '';
     if (my @keys = keys %$params) {
       # somewhat lifted from URI::_query's query_form
       $query = '?'.join('&', map {
           my $val = $params->{$_};
-          s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
+          #s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go; ## Commented out because seems to lead to double encoding - JNAP
           s/ /+/g;
           my $key = $_;
           $val = '' unless defined $val;
           (map {
               my $param = "$_";
-              utf8::encode( $param ) if utf8::is_utf8($param);
+              $param = encode_utf8($param);
               # using the URI::Escape pattern here so utf8 chars survive
               $param =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
               $param =~ s/ /+/g;
+
+              $key = encode_utf8($key);
+              # using the URI::Escape pattern here so utf8 chars survive
+              $key =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
+              $key =~ s/ /+/g;
+
               "${key}=$param"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
       } @keys);
     }
 
+    $base = encode_utf8 $base;
+    $base =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+    $args = encode_utf8 $args;
+    $args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+
+    if(defined $fragment) {
+      $fragment = encode_utf8(${$fragment});
+      $fragment =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
+      $fragment =~ s/ /+/g;
+      $query .= "#$fragment";
+    }
+
     my $res = bless(\"${base}${args}${query}", $class);
     $res;
 }
 
-=head2 $c->uri_for_action( $path, \@captures?, @args?, \%query_values? )
+=head2 $c->uri_for_action( $path, \@captures_and_args?, @args?, \%query_values? )
 
-=head2 $c->uri_for_action( $action, \@captures?, @args?, \%query_values? )
+=head2 $c->uri_for_action( $action, \@captures_and_args?, @args?, \%query_values? )
 
 =over
 
@@ -1421,6 +1704,31 @@ You can use:
 
 and it will create the URI /users/the-list.
 
+=item \@captures_and_args?
+
+Optional array reference of Captures (i.e. C<<CaptureArgs or $c->req->captures>)
+and arguments to the request. Usually used with L<Catalyst::DispatchType::Chained>
+to interpolate all the parameters in the URI.
+
+=item @args?
+
+Optional list of extra arguments - can be supplied in the
+C<< \@captures_and_args? >> array ref, or here - whichever is easier for your
+code.
+
+Your action can have zero, a fixed or a variable number of args (e.g.
+C<< Args(1) >> for a fixed number or C<< Args() >> for a variable number)..
+
+=item \%query_values?
+
+Optional array reference of query parameters to append. E.g.
+
+  { foo => 'bar' }
+
+will generate
+
+  /rest/of/your/uri?foo=bar
+
 =back
 
 =cut
@@ -1540,18 +1848,18 @@ sub welcome_message {
                     We do, however, provide you with a few starting points.</p>
                  <p>If you want to jump right into web development with Catalyst
                     you might want to start with a tutorial.</p>
-<pre>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
+<pre>perldoc <a href="https://metacpan.org/module/Catalyst::Manual::Tutorial">Catalyst::Manual::Tutorial</a></code>
 </pre>
 <p>Afterwards you can go on to check out a more complete look at our features.</p>
 <pre>
-<code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
+<code>perldoc <a href="https://metacpan.org/module/Catalyst::Manual::Intro">Catalyst::Manual::Intro</a>
 <!-- Something else should go here, but the Catalyst::Manual link seems unhelpful -->
 </code></pre>
                  <h2>What to do next?</h2>
                  <p>Next it's time to write an actual application. Use the
-                    helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&amp;mode=all">controllers</a>,
-                    <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&amp;mode=all">models</a>, and
-                    <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&amp;mode=all">views</a>;
+                    helper scripts to generate <a href="https://metacpan.org/search?q=Catalyst%3A%3AController">controllers</a>,
+                    <a href="https://metacpan.org/search?q=Catalyst%3A%3AModel">models</a>, and
+                    <a href="https://metacpan.org/search?q=Catalyst%3A%3AView">views</a>;
                     they can save you a lot of work.</p>
                     <pre><code>script/${prefix}_create.pl --help</code></pre>
                     <p>Also, be sure to check out the vast and growing
@@ -1584,6 +1892,16 @@ sub welcome_message {
 EOF
 }
 
+=head2 run_options
+
+Contains a hash of options passed from the application script, including
+the original ARGV the script received, the processed values from that
+ARGV and any extra arguments to the script which were not processed.
+
+This can be used to add custom options to your application's scripts
+and setup your application differently depending on the values of these
+options.
+
 =head1 INTERNAL METHODS
 
 These methods are not meant to be used by end users.
@@ -1672,6 +1990,16 @@ sub execute {
     my $last = pop( @{ $c->stack } );
 
     if ( my $error = $@ ) {
+        #rethow if this can be handled by middleware
+        if ( $c->_handle_http_exception($error) ) {
+            foreach my $err (@{$c->error}) {
+                $c->log->error($err);
+            }
+            $c->clear_errors;
+            $c->log->_flush if $c->log->can('_flush');
+
+            $error->can('rethrow') ? $error->rethrow : croak $error;
+        }
         if ( blessed($error) and $error->isa('Catalyst::Exception::Detach') ) {
             $error->rethrow if $c->depth > 1;
         }
@@ -1774,6 +2102,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') ) {
@@ -1788,20 +2124,15 @@ sub finalize {
             $c->finalize_error;
         }
 
-        $c->finalize_headers;
-
-        # HEAD request
-        if ( $c->request->method eq 'HEAD' ) {
-            $c->response->body('');
-        }
-
+        $c->finalize_encoding;
+        $c->finalize_headers unless $c->response->finalized_headers;
         $c->finalize_body;
     }
 
     $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" );
@@ -1828,11 +2159,28 @@ sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
 
 =head2 $c->finalize_error
 
-Finalizes error.
+Finalizes error.  If there is only one error in L</error> and it is an object that
+does C<as_psgi> or C<code> we rethrow the error and presume it caught by middleware
+up the ladder.  Otherwise we return the debugging error page (in debug mode) or we
+return the default error page (production mode).
 
 =cut
 
-sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
+sub finalize_error {
+    my $c = shift;
+    if($#{$c->error} > 0) {
+        $c->engine->finalize_error( $c, @_ );
+    } else {
+        my ($error) = @{$c->error};
+        if ( $c->_handle_http_exception($error) ) {
+            # In the case where the error 'knows what it wants', becauses its PSGI
+            # aware, just rethow and let middleware catch it
+            $error->can('rethrow') ? $error->rethrow : croak $error;
+        } else {
+            $c->engine->finalize_error( $c, @_ )
+        }
+    }
+}
 
 =head2 $c->finalize_headers
 
@@ -1852,49 +2200,69 @@ sub finalize_headers {
     if ( my $location = $response->redirect ) {
         $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
         $response->header( Location => $location );
-
-        if ( !$response->has_body ) {
-            # Add a default body if none is already present
-            $response->body(
-                qq{<html><body><p>This item has moved <a href="$location">here</a>.</p></body></html>}
-            );
-        }
-    }
-
-    # Content-Length
-    if ( defined $response->body && length $response->body && !$response->content_length ) {
-
-        # get the length from a filehandle
-        if ( blessed( $response->body ) && $response->body->can('read') || ref( $response->body ) eq 'GLOB' )
-        {
-            my $stat = stat $response->body;
-            if ( $stat && $stat->size > 0 ) {
-                $response->content_length( $stat->size );
-            }
-            else {
-                $c->log->warn('Serving filehandle without a content-length');
-            }
-        }
-        else {
-            # everything should be bytes at this point, but just in case
-            $response->content_length( length( $response->body ) );
-        }
     }
 
-    # Errors
-    if ( $response->status =~ /^(1\d\d|[23]04)$/ ) {
-        $response->headers->remove_header("Content-Length");
-        $response->body('');
-    }
+    # Remove incorrectly added body and content related meta data when returning
+    # an information response, or a response the is required to not include a body
 
     $c->finalize_cookies;
 
-    $c->engine->finalize_headers( $c, @_ );
+    # 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();
 
     # Done
     $response->finalized_headers(1);
 }
 
+=head2 $c->finalize_encoding
+
+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 explicitly 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<write> and C<write_fh> on L<Catalyst::Response>
+are available).
+
+See L</ENCODING>.
+
+=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 ");
+    }
+
+    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 or if headers are already finalized
+        $c->res->content_type($c->res->content_type . "; charset=" . $c->encoding->mime_name)
+          unless($c->res->content_type_charset ||
+                ($c->res->_context && $c->res->finalized_headers && !$c->res->_has_response_cb));
+    }
+}
+
 =head2 $c->finalize_output
 
 An alias for finalize_body.
@@ -1943,7 +2311,7 @@ sub handle_request {
 
     # Always expect worst case!
     my $status = -1;
-    eval {
+    try {
         if ($class->debug) {
             my $secs = time - $START || 1;
             my $av = sprintf '%.3f', $COUNT / $secs;
@@ -1954,12 +2322,14 @@ sub handle_request {
         my $c = $class->prepare(@arguments);
         $c->dispatch;
         $status = $c->finalize;
-    };
-
-    if ( my $error = $@ ) {
-        chomp $error;
+    } catch {
+        #rethow if this can be handled by middleware
+        if ( $class->_handle_http_exception($_) ) {
+            $_->can('rethrow') ? $_->rethrow : croak $_;
+        }
+        chomp(my $error = $_);
         $class->log->error(qq/Caught exception in engine "$error"/);
-    }
+    };
 
     $COUNT++;
 
@@ -1969,13 +2339,18 @@ sub handle_request {
     return $status;
 }
 
-=head2 $c->prepare( @arguments )
+=head2 $class->prepare( @arguments )
 
 Creates a Catalyst context from an engine-specific request (Apache, CGI,
 etc.).
 
 =cut
 
+has _uploadtmp => (
+    is => 'ro',
+    predicate => '_has_uploadtmp',
+);
+
 sub prepare {
     my ( $class, @arguments ) = @_;
 
@@ -1984,50 +2359,60 @@ sub prepare {
     # into the application.
     $class->context_class( ref $class || $class ) unless $class->context_class;
 
-    my $c = $class->context_class->new({});
+    my $uploadtmp = $class->config->{uploadtmp};
+    my $c = $class->context_class->new({ $uploadtmp ? (_uploadtmp => $uploadtmp) : ()});
 
-    # For on-demand data
-    $c->request->_context($c);
     $c->response->_context($c);
 
-    #surely this is not the most efficient way to do things...
     $c->stats($class->stats_class->new)->enable($c->use_stats);
+
     if ( $c->debug || $c->config->{enable_catalyst_header} ) {
         $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
     }
 
-    #XXX reuse coderef from can
-    # Allow engine to direct the prepare flow (for POE)
-    if ( $c->engine->can('prepare') ) {
-        $c->engine->prepare( $c, @arguments );
-    }
-    else {
-        $c->prepare_request(@arguments);
-        $c->prepare_connection;
-        $c->prepare_query_parameters;
-        $c->prepare_headers;
-        $c->prepare_cookies;
-        $c->prepare_path;
-
-        # Prepare the body for reading, either by prepare_body
-        # or the user, if they are using $c->read
-        $c->prepare_read;
-
-        # Parse the body unless the user wants it on-demand
-        unless ( ref($c)->config->{parse_on_demand} ) {
-            $c->prepare_body;
+    try {
+        # Allow engine to direct the prepare flow (for POE)
+        if ( my $prepare = $c->engine->can('prepare') ) {
+            $c->engine->$prepare( $c, @arguments );
+        }
+        else {
+            $c->prepare_request(@arguments);
+            $c->prepare_connection;
+            $c->prepare_query_parameters;
+            $c->prepare_headers; # Just hooks, no longer needed - they just
+            $c->prepare_cookies; # cause the lazy attribute on req to build
+            $c->prepare_path;
+
+            # Prepare the body for reading, either by prepare_body
+            # or the user, if they are using $c->read
+            $c->prepare_read;
+
+            # Parse the body unless the user wants it on-demand
+            unless ( ref($c)->config->{parse_on_demand} ) {
+                $c->prepare_body;
+            }
         }
+        $c->prepare_action;
     }
-
-    my $method  = $c->req->method  || '';
-    my $path    = $c->req->path;
-    $path       = '/' unless length $path;
-    my $address = $c->req->address || '';
+    # VERY ugly and probably shouldn't rely on ->finalize actually working
+    catch {
+        # failed prepare is always due to an invalid request, right?
+        $c->response->status(400);
+        $c->response->content_type('text/plain');
+        $c->response->body('Bad Request');
+        # Note we call finalize and then die here, which escapes
+        # finalize being called in the enclosing block..
+        # It in fact couldn't be called, as we don't return $c..
+        # This is a mess - but I'm unsure you can fix this without
+        # breaking compat for people doing crazy things (we should set
+        # the 400 and just return the ctx here IMO, letting finalize get called
+        # above...
+        $c->finalize;
+        die $_;
+    };
 
     $c->log_request;
 
-    $c->prepare_action;
-
     return $c;
 }
 
@@ -2037,7 +2422,19 @@ Prepares action. See L<Catalyst::Dispatcher>.
 
 =cut
 
-sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
+sub prepare_action {
+    my $c = shift;
+    my $ret = $c->dispatcher->prepare_action( $c, @_);
+
+    if($c->encoding) {
+        foreach (@{$c->req->arguments}, @{$c->req->captures}) {
+          $_ = $c->_handle_param_unicode_decoding($_);
+        }
+    }
+
+    return $ret;
+}
+
 
 =head2 $c->prepare_body
 
@@ -2077,7 +2474,7 @@ Prepares body parameters.
 
 sub prepare_body_parameters {
     my $c = shift;
-    $c->engine->prepare_body_parameters( $c, @_ );
+    $c->request->prepare_body_parameters( $c, @_ );
 }
 
 =head2 $c->prepare_connection
@@ -2088,24 +2485,26 @@ Prepares connection.
 
 sub prepare_connection {
     my $c = shift;
-    $c->engine->prepare_connection( $c, @_ );
+    $c->request->prepare_connection($c);
 }
 
 =head2 $c->prepare_cookies
 
-Prepares cookies.
+Prepares cookies by ensuring that the attribute on the request
+object has been built.
 
 =cut
 
-sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
+sub prepare_cookies { my $c = shift; $c->request->cookies }
 
 =head2 $c->prepare_headers
 
-Prepares headers.
+Prepares request headers by ensuring that the attribute on the request
+object has been built.
 
 =cut
 
-sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
+sub prepare_headers { my $c = shift; $c->request->headers }
 
 =head2 $c->prepare_parameters
 
@@ -2169,6 +2568,10 @@ sub log_request {
     $method ||= '';
     $path = '/' unless length $path;
     $address ||= '';
+
+    $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+    $path = decode_utf8($path);
+
     $c->log->debug(qq/"$method" request for "$path" from "$address"/);
 
     $c->log_request_headers($request->headers);
@@ -2232,7 +2635,7 @@ sub log_response_status_line {
 
 =head2 $c->log_response_headers($headers);
 
-Hook method which can be wrapped by plugins to log the responseheaders.
+Hook method which can be wrapped by plugins to log the response headers.
 No-op in the default implementation.
 
 =cut
@@ -2353,7 +2756,6 @@ Prepares uploads.
 
 sub prepare_uploads {
     my $c = shift;
-
     $c->engine->prepare_uploads( $c, @_ );
 }
 
@@ -2369,10 +2771,65 @@ sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
 
 Returns or sets the request class. Defaults to L<Catalyst::Request>.
 
+=head2 $app->request_class_traits
+
+An arrayref of L<Moose::Role>s which are applied to the request class.  You can
+name the full namespace of the role, or a namespace suffix, which will then
+be tried against the following standard namespace prefixes.
+
+    $MyApp::TraitFor::Request::$trait_suffix
+    Catalyst::TraitFor::Request::$trait_suffix
+
+So for example if you set:
+
+    MyApp->request_class_traits(['Foo']);
+
+We try each possible role in turn (and throw an error if none load)
+
+    Foo
+    MyApp::TraitFor::Request::Foo
+    Catalyst::TraitFor::Request::Foo
+
+The namespace part 'TraitFor::Request' was choosen to assist in backwards
+compatibility with L<CatalystX::RoleApplicator> which previously provided
+these features in a stand alone package.
+  
+=head2 $app->composed_request_class
+
+This is the request class which has been composed with any request_class_traits.
+
 =head2 $c->response_class
 
 Returns or sets the response class. Defaults to L<Catalyst::Response>.
 
+=head2 $app->response_class_traits
+
+An arrayref of L<Moose::Role>s which are applied to the response class.  You can
+name the full namespace of the role, or a namespace suffix, which will then
+be tried against the following standard namespace prefixes.
+
+    $MyApp::TraitFor::Response::$trait_suffix
+    Catalyst::TraitFor::Response::$trait_suffix
+
+So for example if you set:
+
+    MyApp->response_class_traits(['Foo']);
+
+We try each possible role in turn (and throw an error if none load)
+
+    Foo
+    MyApp::TraitFor::Response::Foo
+    Catalyst::TraitFor::Responset::Foo
+
+The namespace part 'TraitFor::Response' was choosen to assist in backwards
+compatibility with L<CatalystX::RoleApplicator> which previously provided
+these features in a stand alone package.
+
+
+=head2 $app->composed_response_class
+
+This is the request class which has been composed with any response_class_traits.
+
 =head2 $c->read( [$maxlength] )
 
 Reads a chunk of data from the request body. This method is designed to
@@ -2388,7 +2845,7 @@ $c->request.  You must handle all body parsing yourself.
 
 =cut
 
-sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
+sub read { my $c = shift; return $c->request->read( @_ ) }
 
 =head2 $c->run
 
@@ -2396,7 +2853,36 @@ Starts the engine.
 
 =cut
 
-sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
+sub run {
+  my $app = shift;
+  $app->_make_immutable_if_needed;
+  $app->engine_loader->needs_psgi_engine_compat_hack ?
+    $app->engine->run($app, @_) :
+      $app->engine->run( $app, $app->_finalized_psgi_app, @_ );
+}
+
+sub _make_immutable_if_needed {
+    my $class = shift;
+    my $meta = find_meta($class);
+    my $isa_ca = $class->isa('Class::Accessor::Fast') || $class->isa('Class::Accessor');
+    if (
+        $meta->is_immutable
+        && ! { $meta->immutable_options }->{replace_constructor}
+        && $isa_ca
+    ) {
+        warn("You made your application class ($class) immutable, "
+            . "but did not inline the\nconstructor. "
+            . "This will break catalyst, as your app \@ISA "
+            . "Class::Accessor(::Fast)?\nPlease pass "
+            . "(replace_constructor => 1)\nwhen making your class immutable.\n");
+    }
+    unless ($meta->is_immutable) {
+        # XXX - FIXME warning here as you should make your app immutable yourself.
+        $meta->make_immutable(
+            replace_constructor => 1,
+        );
+    }
+}
 
 =head2 $c->set_action( $action, $code, $namespace, $attrs )
 
@@ -2452,17 +2938,119 @@ sub setup_components {
     }
 
     for my $component (@comps) {
-        my $instance = $class->components->{ $component } = $class->setup_component($component);
-        my @expanded_components = $instance->can('expand_modules')
-            ? $instance->expand_modules( $component, $config )
-            : $class->expand_component_module( $component, $config );
-        for my $component (@expanded_components) {
-            next if $comps{$component};
-            $class->components->{ $component } = $class->setup_component($component);
-        }
+        my $instance = $class->components->{ $component } = $class->delayed_setup_component($component);
+    }
+
+    # Inject a component or wrap a stand alone class in an adaptor. This makes a list
+    # of named components in the configuration that are not actually existing (not a
+    # real file).
+
+    my @injected = $class->setup_injected_components;
+
+    # All components are registered, now we need to 'init' them.
+    foreach my $component_name (@comps, @injected) {
+      $class->components->{$component_name} = $class->components->{$component_name}->() if
+        (ref($class->components->{$component_name}) || '') eq 'CODE';
     }
 }
 
+=head2 $app->setup_injected_components
+
+Called by setup_compoents to setup components that are injected.
+
+=cut
+
+sub setup_injected_components {
+    my ($class) = @_;
+    my @injected_components = keys %{$class->config->{inject_components} ||+{}};
+
+    foreach my $injected_comp_name(@injected_components) {
+        $class->setup_injected_component(
+          $injected_comp_name,
+          $class->config->{inject_components}->{$injected_comp_name});
+    }
+
+    return map { $class ."::" . $_ }
+      @injected_components;
+}
+
+=head2 $app->setup_injected_component( $injected_component_name, $config )
+
+Setup a given injected component.
+
+=cut
+
+sub setup_injected_component {
+    my ($class, $injected_comp_name, $config) = @_;
+    if(my $component_class = $config->{from_component}) {
+        my @roles = @{$config->{roles} ||[]};
+        Catalyst::Utils::inject_component(
+          into => $class,
+          component => $component_class,
+          (scalar(@roles) ? (traits => \@roles) : ()),
+          as => $injected_comp_name);
+    }
+}
+
+=head2 $app->inject_component($MyApp_Component_name => \%args);
+
+Add a component that is injected at setup:
+
+    MyApp->inject_component( 'Model::Foo' => { from_component => 'Common::Foo' } );
+
+Must be called before ->setup.  Expects a component name for your
+current application and \%args where
+
+=over 4
+
+=item from_component
+
+The target component being injected into your application
+
+=item roles
+
+An arrayref of L<Moose::Role>s that are applied to your component.
+
+=back
+
+Example
+
+    MyApp->inject_component(
+      'Model::Foo' => {
+        from_component => 'Common::Model::Foo',
+        roles => ['Role1', 'Role2'],
+      });
+
+=head2 $app->inject_components
+
+Inject a list of components:
+
+    MyApp->inject_components(
+      'Model::FooOne' => {
+        from_component => 'Common::Model::Foo',
+        roles => ['Role1', 'Role2'],
+      },
+      'Model::FooTwo' => {
+        from_component => 'Common::Model::Foo',
+        roles => ['Role1', 'Role2'],
+      });
+
+=cut
+
+sub inject_component {
+  my ($app, $name, $args) = @_;
+  die "Component $name exists" if
+    $app->config->{inject_components}->{$name};
+  $app->config->{inject_components}->{$name} = $args;
+}
+
+sub inject_components {
+  my $app = shift;
+  while(@_) {
+    $app->inject_component(shift, shift);
+  }
+}
+
 =head2 $c->locate_components( $setup_component_config )
 
 This method is meant to provide a list of component modules that should be
@@ -2479,18 +3067,15 @@ sub locate_components {
     my $class  = shift;
     my $config = shift;
 
-    my @paths   = qw( ::Controller ::C ::Model ::M ::View ::V );
+    my @paths   = qw( ::M ::Model ::V ::View ::C ::Controller );
     my $extra   = delete $config->{ search_extra } || [];
 
-    push @paths, @$extra;
+    unshift @paths, @$extra;
 
-    my $locator = Module::Pluggable::Object->new(
-        search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
-        %$config
-    );
-
-    # XXX think about ditching this sort entirely
-    my @comps = sort { length $a <=> length $b } $locator->plugins;
+    my @comps = map { sort { length($a) <=> length($b) } Module::Pluggable::Object->new(
+      search_path => [ map { s/^(?=::)/$class/; $_; } ($_) ],
+      %$config
+    )->plugins } @paths;
 
     return @comps;
 }
@@ -2507,6 +3092,21 @@ sub expand_component_module {
     return Devel::InnerPackage::list_packages( $module );
 }
 
+=head2 $app->delayed_setup_component
+
+Returns a coderef that points to a setup_component instance.  Used
+internally for when you want to delay setup until the first time
+the component is called.
+
+=cut
+
+sub delayed_setup_component {
+  my($class, $component, @more) = @_;
+  return sub {
+    return my $instance = $class->setup_component($component, @more);
+  };
+}
+
 =head2 $c->setup_component
 
 =cut
@@ -2518,21 +3118,21 @@ sub setup_component {
         return $component;
     }
 
-    my $suffix = Catalyst::Utils::class2classsuffix( $component );
-    my $config = $class->config->{ $suffix } || {};
+    my $config = $class->config_for($component);
     # Stash catalyst_component_name in the config here, so that custom COMPONENT
     # methods also pass it. local to avoid pointlessly shitting in config
     # for the debug screen, as $component is already the key name.
     local $config->{catalyst_component_name} = $component;
 
-    my $instance = eval { $component->COMPONENT( $class, $config ); };
-
-    if ( my $error = $@ ) {
-        chomp $error;
-        Catalyst::Exception->throw(
-            message => qq/Couldn't instantiate component "$component", "$error"/
-        );
-    }
+    my $instance = eval {
+      $component->COMPONENT( $class, $config );
+    } || do {
+      my $error = $@;
+      chomp $error;
+      Catalyst::Exception->throw(
+        message => qq/Couldn't instantiate component "$component", "$error"/
+      );
+    };
 
     unless (blessed $instance) {
         my $metaclass = Moose::Util::find_meta($component);
@@ -2544,7 +3144,43 @@ sub setup_component {
             qq/Couldn't instantiate component "$component", COMPONENT() method (from $component_method_from) didn't return an object-like value (value was $value)./
         );
     }
-    return $instance;
+
+    my @expanded_components = $instance->can('expand_modules')
+      ? $instance->expand_modules( $component, $config )
+      : $class->expand_component_module( $component, $config );
+    for my $component (@expanded_components) {
+      next if $class->components->{ $component };
+      $class->components->{ $component } = $class->setup_component($component);
+    }
+
+    return $instance; 
+}
+
+=head2 $app->config_for( $component_name )
+
+Return the application level configuration (which is not yet merged with any
+local component configuration, via $component_class->config) for the named
+component or component object. Example:
+
+    MyApp->config(
+      'Model::Foo' => { a => 1, b => 2},
+    );
+
+    my $config = MyApp->config_for('MyApp::Model::Foo');
+
+In this case $config is the hashref C< {a=>1, b=>2} >.
+
+This is also handy for looking up configuration for a plugin, to make sure you follow
+existing L<Catalyst> standards for where a plugin should put its configuration.
+
+=cut
+
+sub config_for {
+    my ($class, $component_name) = @_;
+    my $component_suffix = Catalyst::Utils::class2classsuffix($component_name);
+    my $config = $class->config->{ $component_suffix } || {};
+
+    return $config;
 }
 
 =head2 $c->setup_dispatcher
@@ -2568,7 +3204,7 @@ sub setup_dispatcher {
         $dispatcher = $class->dispatcher_class;
     }
 
-    Class::MOP::load_class($dispatcher);
+    load_class($dispatcher);
 
     # dispatcher instance
     $class->dispatcher( $dispatcher->new );
@@ -2580,114 +3216,239 @@ Sets up engine.
 
 =cut
 
-sub setup_engine {
-    my ( $class, $engine ) = @_;
+sub engine_class {
+    my ($class, $requested_engine) = @_;
 
-    if ($engine) {
-        $engine = 'Catalyst::Engine::' . $engine;
+    if (!$class->engine_loader || $requested_engine) {
+        $class->engine_loader(
+            Catalyst::EngineLoader->new({
+                application_name => $class,
+                (defined $requested_engine
+                     ? (catalyst_engine_class => $requested_engine) : ()),
+            }),
+        );
     }
 
-    if ( my $env = Catalyst::Utils::env_value( $class, 'ENGINE' ) ) {
-        $engine = 'Catalyst::Engine::' . $env;
-    }
+    $class->engine_loader->catalyst_engine_class;
+}
 
-    if ( $ENV{MOD_PERL} ) {
-        my $meta = Class::MOP::get_metaclass_by_name($class);
+sub setup_engine {
+    my ($class, $requested_engine) = @_;
 
-        # create the apache method
-        $meta->add_method('apache' => sub { shift->engine->apache });
+    my $engine = do {
+        my $loader = $class->engine_loader;
 
-        my ( $software, $version ) =
-          $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
+        if (!$loader || $requested_engine) {
+            $loader = Catalyst::EngineLoader->new({
+                application_name => $class,
+                (defined $requested_engine
+                     ? (requested_engine => $requested_engine) : ()),
+            }),
 
-        $version =~ s/_//g;
-        $version =~ s/(\.[^.]+)\./$1/g;
+            $class->engine_loader($loader);
+        }
 
-        if ( $software eq 'mod_perl' ) {
+        $loader->catalyst_engine_class;
+    };
 
-            if ( !$engine ) {
+    # Don't really setup_engine -- see _setup_psgi_app for explanation.
+    return if $class->loading_psgi_file;
 
-                if ( $version >= 1.99922 ) {
-                    $engine = 'Catalyst::Engine::Apache2::MP20';
-                }
+    load_class($engine);
 
-                elsif ( $version >= 1.9901 ) {
-                    $engine = 'Catalyst::Engine::Apache2::MP19';
-                }
+    if ($ENV{MOD_PERL}) {
+        my $apache = $class->engine_loader->auto;
 
-                elsif ( $version >= 1.24 ) {
-                    $engine = 'Catalyst::Engine::Apache::MP13';
-                }
+        my $meta = find_meta($class);
+        my $was_immutable = $meta->is_immutable;
+        my %immutable_options = $meta->immutable_options;
+        $meta->make_mutable if $was_immutable;
 
-                else {
-                    Catalyst::Exception->throw( message =>
-                          qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
-                }
+        $meta->add_method(handler => sub {
+            my $r = shift;
+            my $psgi_app = $class->_finalized_psgi_app;
+            $apache->call_app($r, $psgi_app);
+        });
 
-            }
+        $meta->make_immutable(%immutable_options) if $was_immutable;
+    }
 
-            # install the correct mod_perl handler
-            if ( $version >= 1.9901 ) {
-                *handler = sub  : method {
-                    shift->handle_request(@_);
-                };
-            }
-            else {
-                *handler = sub ($$) { shift->handle_request(@_) };
-            }
+    $class->engine( $engine->new );
 
-        }
+    return;
+}
 
-        elsif ( $software eq 'Zeus-Perl' ) {
-            $engine = 'Catalyst::Engine::Zeus';
-        }
+## This exists just to supply a prebuild psgi app for mod_perl and for the 
+## build in server support (back compat support for pre psgi port behavior).
+## This is so that we don't build a new psgi app for each request when using
+## the mod_perl handler or the built in servers (http and fcgi, etc).
 
-        else {
-            Catalyst::Exception->throw(
-                message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
-        }
-    }
+sub _finalized_psgi_app {
+    my ($app) = @_;
 
-    unless ($engine) {
-        $engine = $class->engine_class;
+    unless ($app->_psgi_app) {
+        my $psgi_app = $app->_setup_psgi_app;
+        $app->_psgi_app($psgi_app);
     }
 
-    Class::MOP::load_class($engine);
+    return $app->_psgi_app;
+}
 
-    # check for old engines that are no longer compatible
-    my $old_engine;
-    if ( $engine->isa('Catalyst::Engine::Apache')
-        && !Catalyst::Engine::Apache->VERSION )
-    {
-        $old_engine = 1;
-    }
+## Look for a psgi file like 'myapp_web.psgi' (if the app is MyApp::Web) in the
+## home directory and load that and return it (just assume it is doing the 
+## right thing :) ).  If that does not exist, call $app->psgi_app, wrap that
+## in default_middleware and return it ( this is for backward compatibility
+## with pre psgi port behavior ).
 
-    elsif ( $engine->isa('Catalyst::Engine::Server::Base')
-        && Catalyst::Engine::Server->VERSION le '0.02' )
-    {
-        $old_engine = 1;
-    }
+sub _setup_psgi_app {
+    my ($app) = @_;
 
-    elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
-        && $engine->VERSION eq '0.01' )
-    {
-        $old_engine = 1;
-    }
+    for my $home (Path::Class::Dir->new($app->config->{home})) {
+        my $psgi_file = $home->file(
+            Catalyst::Utils::appprefix($app) . '.psgi',
+        );
 
-    elsif ($engine->isa('Catalyst::Engine::Zeus')
-        && $engine->VERSION eq '0.01' )
-    {
-        $old_engine = 1;
+        next unless -e $psgi_file;
+
+        # If $psgi_file calls ->setup_engine, it's doing so to load
+        # Catalyst::Engine::PSGI. But if it does that, we're only going to
+        # throw away the loaded PSGI-app and load the 5.9 Catalyst::Engine
+        # anyway. So set a flag (ick) that tells setup_engine not to populate
+        # $c->engine or do any other things we might regret.
+
+        $app->loading_psgi_file(1);
+        my $psgi_app = Plack::Util::load_psgi($psgi_file);
+        $app->loading_psgi_file(0);
+
+        return $psgi_app
+            unless $app->engine_loader->needs_psgi_engine_compat_hack;
+
+        warn <<"EOW";
+Found a legacy Catalyst::Engine::PSGI .psgi file at ${psgi_file}.
+
+Its content has been ignored. Please consult the Catalyst::Upgrading
+documentation on how to upgrade from Catalyst::Engine::PSGI.
+EOW
     }
 
-    if ($old_engine) {
-        Catalyst::Exception->throw( message =>
-              qq/Engine "$engine" is not supported by this version of Catalyst/
-        );
+    return $app->apply_default_middlewares($app->psgi_app);
+}
+
+=head2 $c->apply_default_middlewares
+
+Adds the following L<Plack> middlewares to your application, since they are
+useful and commonly needed:
+
+L<Plack::Middleware::LighttpdScriptNameFix> (if you are using Lighttpd),
+L<Plack::Middleware::IIS6ScriptNameFix> (always applied since this middleware
+is smart enough to conditionally apply itself).
+
+We will also automatically add L<Plack::Middleware::ReverseProxy> if we notice
+that your HTTP $env variable C<REMOTE_ADDR> is '127.0.0.1'.  This is usually
+an indication that your server is running behind a proxy frontend.  However in
+2014 this is often not the case.  We preserve this code for backwards compatibility
+however I B<highly> recommend that if you are running the server behind a front
+end proxy that you clearly indicate so with the C<using_frontend_proxy> configuration
+setting to true for your environment configurations that run behind a proxy.  This
+way if you change your front end proxy address someday your code would inexplicably
+stop working as expected.
+
+Additionally if we detect we are using Nginx, we add a bit of custom middleware
+to solve some problems with the way that server handles $ENV{PATH_INFO} and
+$ENV{SCRIPT_NAME}.
+
+Please B<NOTE> that if you do use C<using_frontend_proxy> the middleware is now
+adding via C<registered_middleware> rather than this method.
+
+If you are using Lighttpd or IIS6 you may wish to apply these middlewares.  In
+general this is no longer a common case but we have this here for backward
+compatibility.
+
+=cut
+
+
+sub apply_default_middlewares {
+    my ($app, $psgi_app) = @_;
+
+    # Don't add this conditional IF we are explicitly saying we want the
+    # frontend proxy support.  We don't need it here since if that is the
+    # case it will be always loaded in the default_middleware.
+
+    unless($app->config->{using_frontend_proxy}) {
+      $psgi_app = Plack::Middleware::Conditional->wrap(
+          $psgi_app,
+          builder   => sub { Plack::Middleware::ReverseProxy->wrap($_[0]) },
+          condition => sub {
+              my ($env) = @_;
+              return if $app->config->{ignore_frontend_proxy};
+              return $env->{REMOTE_ADDR} eq '127.0.0.1';
+          },
+      );
     }
 
-    # engine instance
-    $class->engine( $engine->new );
+    # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
+    # http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html
+    $psgi_app = Plack::Middleware::Conditional->wrap(
+        $psgi_app,
+        builder   => sub { Plack::Middleware::LighttpdScriptNameFix->wrap($_[0]) },
+        condition => sub {
+            my ($env) = @_;
+            return unless $env->{SERVER_SOFTWARE} && $env->{SERVER_SOFTWARE} =~ m!lighttpd[-/]1\.(\d+\.\d+)!;
+            return unless $1 < 4.23;
+            1;
+        },
+    );
+
+    # we're applying this unconditionally as the middleware itself already makes
+    # sure it doesn't fuck things up if it's not running under one of the right
+    # IIS versions
+    $psgi_app = Plack::Middleware::IIS6ScriptNameFix->wrap($psgi_app);
+
+    # And another IIS issue, this time with IIS7.
+    $psgi_app = Plack::Middleware::Conditional->wrap(
+        $psgi_app,
+        builder => sub { Plack::Middleware::IIS7KeepAliveFix->wrap($_[0]) },
+        condition => sub {
+            my ($env) = @_;
+            return $env->{SERVER_SOFTWARE} && $env->{SERVER_SOFTWARE} =~ m!IIS/7\.[0-9]!;
+        },
+    );
+
+    return $psgi_app;
+}
+
+=head2 App->psgi_app
+
+=head2 App->to_app
+
+Returns a PSGI application code reference for the catalyst application
+C<$c>. This is the bare application created without the C<apply_default_middlewares>
+method called.  We do however apply C<registered_middleware> since those are
+integral to how L<Catalyst> functions.  Also, unlike starting your application
+with a generated server script (via L<Catalyst::Devel> and C<catalyst.pl>) we do
+not attempt to return a valid L<PSGI> application using any existing C<${myapp}.psgi>
+scripts in your $HOME directory.
+
+B<NOTE> C<apply_default_middlewares> was originally created when the first PSGI
+port was done for v5.90000.  These are middlewares that are added to achieve
+backward compatibility with older applications.  If you start your application
+using one of the supplied server scripts (generated with L<Catalyst::Devel> and
+the project skeleton script C<catalyst.pl>) we apply C<apply_default_middlewares>
+automatically.  This was done so that pre and post PSGI port applications would
+work the same way.
+
+This is what you want to be using to retrieve the PSGI application code
+reference of your Catalyst application for use in a custom F<.psgi> or in your
+own created server modules.
+
+=cut
+
+*to_app = \&psgi_app;
+
+sub psgi_app {
+    my ($app) = @_;
+    my $psgi = $app->engine->build_psgi_app($app);
+    return $app->Catalyst::Utils::apply_registered_middleware($psgi);
 }
 
 =head2 $c->setup_home
@@ -2712,6 +3473,92 @@ sub setup_home {
     }
 }
 
+=head2 $c->setup_encoding
+
+Sets up the input/output encoding. See L<ENCODING>
+
+=cut
+
+sub setup_encoding {
+    my $c = shift;
+    if( exists($c->config->{encoding}) && !defined($c->config->{encoding}) ) {
+        # Ok, so the user has explicitly said "I don't want encoding..."
+        return;
+    } else {
+      my $enc = defined($c->config->{encoding}) ?
+        delete $c->config->{encoding} : 'UTF-8'; # not sure why we delete it... (JNAP)
+      $c->encoding($enc);
+    }
+}
+
+=head2 handle_unicode_encoding_exception
+
+Hook to let you customize how encoding errors are handled.  By default
+we just throw an exception.  Receives a hashref of debug information.
+Example:
+
+    $c->handle_unicode_encoding_exception({
+        param_value => $value,
+        error_msg => $_,
+            encoding_step => 'params',
+        });
+
+=cut
+
+sub handle_unicode_encoding_exception {
+    my ( $self, $exception_ctx ) = @_;
+    die $exception_ctx->{error_msg};
+}
+
+# Some unicode helpers cargo culted from the old plugin.  These could likely
+# be neater.
+
+sub _handle_unicode_decoding {
+    my ( $self, $value ) = @_;
+
+    return unless defined $value;
+
+    ## I think this mess is to support the old nested
+    if ( ref $value eq 'ARRAY' ) {
+        foreach ( @$value ) {
+            $_ = $self->_handle_unicode_decoding($_);
+        }
+        return $value;
+    }
+    elsif ( ref $value eq 'HASH' ) {
+        foreach (keys %$value) {
+            my $encoded_key = $self->_handle_param_unicode_decoding($_);
+            $value->{$encoded_key} = $self->_handle_unicode_decoding($value->{$_});
+
+            # If the key was encoded we now have two (the original and current so
+            # delete the original.
+            delete $value->{$_} if $_ ne $encoded_key;
+        }
+        return $value;
+    }
+    else {
+        return $self->_handle_param_unicode_decoding($value);
+    }
+}
+
+sub _handle_param_unicode_decoding {
+    my ( $self, $value ) = @_;
+    return unless defined $value; # not in love with just ignoring undefs - jnap
+    return $value if blessed($value); #don't decode when the value is an object.
+
+    my $enc = $self->encoding;
+    return try {
+      $enc->decode( $value, $self->_encode_check );
+    }
+    catch {
+        $self->handle_unicode_encoding_exception({
+            param_value => $value,
+            error_msg => $_,
+            encoding_step => 'params',
+        });
+    };
+}
+
 =head2 $c->setup_log
 
 Sets up log by instantiating a L<Catalyst::Log|Catalyst::Log> object and
@@ -2780,7 +3627,7 @@ sub setup_stats {
 =head2 $c->registered_plugins
 
 Returns a sorted list of the plugins which have either been stated in the
-import list or which have been added via C<< MyApp->plugin(@args); >>.
+import list.
 
 If passed a given plugin name, it will report a boolean value indicating
 whether or not that plugin is loaded.  A fully qualified name is required if
@@ -2806,21 +3653,42 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
         my ( $proto, $plugin, $instant ) = @_;
         my $class = ref $proto || $proto;
 
-        Class::MOP::load_class( $plugin );
+        load_class( $plugin );
         $class->log->warn( "$plugin inherits from 'Catalyst::Component' - this is deprecated and will not work in 5.81" )
             if $plugin->isa( 'Catalyst::Component' );
-        $proto->_plugins->{$plugin} = 1;
-        unless ($instant) {
+        my $plugin_meta = Moose::Meta::Class->create($plugin);
+        if (!$plugin_meta->has_method('new')
+            && ( $plugin->isa('Class::Accessor::Fast') || $plugin->isa('Class::Accessor') ) ) {
+            $plugin_meta->add_method('new', Moose::Object->meta->get_method('new'))
+        }
+        if (!$instant && !$proto->_plugins->{$plugin}) {
             my $meta = Class::MOP::get_metaclass_by_name($class);
             $meta->superclasses($plugin, $meta->superclasses);
         }
+        $proto->_plugins->{$plugin} = 1;
         return $class;
     }
 
+    sub _default_plugins { return qw() }
+
     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 {
@@ -2833,7 +3701,7 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
          } @{ $plugins };
 
         for my $plugin ( reverse @plugins ) {
-            Class::MOP::load_class($plugin->[0], $plugin->[1]);
+            load_class($plugin->[0], $plugin->[1]);
             my $meta = find_meta($plugin->[0]);
             next if $meta && $meta->isa('Moose::Meta::Role');
 
@@ -2852,6 +3720,252 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
     }
 }
 
+=head2 default_middleware
+
+Returns a list of instantiated PSGI middleware objects which is the default
+middleware that is active for this application (taking any configuration
+options into account, excluding your custom added middleware via the C<psgi_middleware>
+configuration option).  You can override this method if you wish to change
+the default middleware (although do so at risk since some middleware is vital
+to application function.)
+
+The current default middleware list is:
+
+      Catalyst::Middleware::Stash
+      Plack::Middleware::HTTPExceptions
+      Plack::Middleware::RemoveRedundantBody
+      Plack::Middleware::FixMissingBodyInRedirect
+      Plack::Middleware::ContentLength
+      Plack::Middleware::MethodOverride
+      Plack::Middleware::Head
+
+If the configuration setting C<using_frontend_proxy> is true we add:
+
+      Plack::Middleware::ReverseProxy
+
+If the configuration setting C<using_frontend_proxy_path> is true we add:
+
+      Plack::Middleware::ReverseProxyPath
+
+But B<NOTE> that L<Plack::Middleware::ReverseProxyPath> is not a dependency of the
+L<Catalyst> distribution so if you want to use this option you should add it to
+your project distribution file.
+
+These middlewares will be added at L</setup_middleware> during the
+L</setup> phase of application startup.
+
+=cut
+
+sub default_middleware {
+    my $class = shift;
+    my @mw = (
+      Catalyst::Middleware::Stash->new,
+      Plack::Middleware::HTTPExceptions->new,
+      Plack::Middleware::RemoveRedundantBody->new,
+      Plack::Middleware::FixMissingBodyInRedirect->new,
+      Plack::Middleware::ContentLength->new,
+      Plack::Middleware::MethodOverride->new,
+      Plack::Middleware::Head->new);
+
+    if($class->config->{using_frontend_proxy}) {
+        push @mw, Plack::Middleware::ReverseProxy->new;
+    }
+
+    if($class->config->{using_frontend_proxy_path}) {
+        if(Class::Load::try_load_class('Plack::Middleware::ReverseProxyPath')) {
+            push @mw, Plack::Middleware::ReverseProxyPath->new;
+        } else {
+          $class->log->error("Cannot use configuration 'using_frontend_proxy_path' because 'Plack::Middleware::ReverseProxyPath' is not installed");
+        }
+    }
+
+    return @mw;
+}
+
+=head2 registered_middlewares
+
+Read only accessor that returns an array of all the middleware in the order
+that they were added (which is the REVERSE of the order they will be applied).
+
+The values returned will be either instances of L<Plack::Middleware> or of a
+compatible interface, or a coderef, which is assumed to be inlined middleware
+
+=head2 setup_middleware (?@middleware)
+
+Read configuration information stored in configuration key C<psgi_middleware> or
+from passed @args.
+
+See under L</CONFIGURATION> information regarding C<psgi_middleware> and how
+to use it to enable L<Plack::Middleware>
+
+This method is automatically called during 'setup' of your application, so
+you really don't need to invoke it.  However you may do so if you find the idea
+of loading middleware via configuration weird :).  For example:
+
+    package MyApp;
+
+    use Catalyst;
+
+    __PACKAGE__->setup_middleware('Head');
+    __PACKAGE__->setup;
+
+When we read middleware definitions from configuration, we reverse the list
+which sounds odd but is likely how you expect it to work if you have prior
+experience with L<Plack::Builder> or if you previously used the plugin
+L<Catalyst::Plugin::EnableMiddleware> (which is now considered deprecated)
+
+So basically your middleware handles an incoming request from the first
+registered middleware, down and handles the response from the last middleware
+up.
+
+=cut
+
+sub registered_middlewares {
+    my $class = shift;
+    if(my $middleware = $class->_psgi_middleware) {
+        my @mw = ($class->default_middleware, @$middleware);
+
+        if($class->config->{using_frontend_proxy}) {
+          push @mw, Plack::Middleware::ReverseProxy->new;
+        }
+
+        return @mw;
+    } else {
+        die "You cannot call ->registered_middlewares until middleware has been setup";
+    }
+}
+
+sub setup_middleware {
+    my $class = shift;
+    my @middleware_definitions;
+
+    # If someone calls this method you can add middleware with args.  However if its
+    # called without an arg we need to setup the configuration middleware.
+    if(@_) {
+      @middleware_definitions = reverse(@_);
+    } else {
+      @middleware_definitions = reverse(@{$class->config->{'psgi_middleware'}||[]})
+        unless $class->finalized_default_middleware;
+      $class->finalized_default_middleware(1); # Only do this once, just in case some people call setup over and over...
+    }
+
+    my @middleware = ();
+    while(my $next = shift(@middleware_definitions)) {
+        if(ref $next) {
+            if(Scalar::Util::blessed $next && $next->can('wrap')) {
+                push @middleware, $next;
+            } elsif(ref $next eq 'CODE') {
+                push @middleware, $next;
+            } elsif(ref $next eq 'HASH') {
+                my $namespace = shift @middleware_definitions;
+                my $mw = $class->Catalyst::Utils::build_middleware($namespace, %$next);
+                push @middleware, $mw;
+            } else {
+              die "I can't handle middleware definition ${\ref $next}";
+            }
+        } else {
+          my $mw = $class->Catalyst::Utils::build_middleware($next);
+          push @middleware, $mw;
+        }
+    }
+
+    my @existing = @{$class->_psgi_middleware || []};
+    $class->_psgi_middleware([@middleware,@existing,]);
+}
+
+=head2 registered_data_handlers
+
+A read only copy of registered Data Handlers returned as a Hash, where each key
+is a content type and each value is a subref that attempts to decode that content
+type.
+
+=head2 setup_data_handlers (?@data_handler)
+
+Read configuration information stored in configuration key C<data_handlers> or
+from passed @args.
+
+See under L</CONFIGURATION> information regarding C<data_handlers>.
+
+This method is automatically called during 'setup' of your application, so
+you really don't need to invoke it.
+
+=head2 default_data_handlers
+
+Default Data Handlers that come bundled with L<Catalyst>.  Currently there are
+only two default data handlers, for 'application/json' and an alternative to
+'application/x-www-form-urlencoded' which supposed nested form parameters via
+L<CGI::Struct> or via L<CGI::Struct::XS> IF you've installed it.
+
+The 'application/json' data handler is used to parse incoming JSON into a Perl
+data structure.  It used either L<JSON::MaybeXS> or L<JSON>, depending on which
+is installed.  This allows you to fail back to L<JSON:PP>, which is a Pure Perl
+JSON decoder, and has the smallest dependency impact.
+
+Because we don't wish to add more dependencies to L<Catalyst>, if you wish to
+use this new feature we recommend installing L<JSON> or L<JSON::MaybeXS> in
+order to get the best performance.  You should add either to your dependency
+list (Makefile.PL, dist.ini, cpanfile, etc.)
+
+=cut
+
+sub registered_data_handlers {
+    my $class = shift;
+    if(my $data_handlers = $class->_data_handlers) {
+        return %$data_handlers;
+    } else {
+        $class->setup_data_handlers;
+        return $class->registered_data_handlers;
+    }
+}
+
+sub setup_data_handlers {
+    my ($class, %data_handler_callbacks) = @_;
+    %data_handler_callbacks = (
+      %{$class->default_data_handlers},
+      %{$class->config->{'data_handlers'}||+{}},
+      %data_handler_callbacks);
+
+    $class->_data_handlers(\%data_handler_callbacks);
+}
+
+sub default_data_handlers {
+    my ($class) = @_;
+    return +{
+      'application/x-www-form-urlencoded' => sub {
+          my ($fh, $req) = @_;
+          my $params = $req->_use_hash_multivalue ? $req->body_parameters->mixed : $req->body_parameters;
+          Class::Load::load_first_existing_class('CGI::Struct::XS', 'CGI::Struct')
+            ->can('build_cgi_struct')->($params);
+      },
+      'application/json' => sub {
+          my ($fh, $req) = @_;
+          my $parser = Class::Load::load_first_existing_class('JSON::MaybeXS', 'JSON');
+          my $slurped;
+          return eval { 
+            local $/;
+            $slurped = $fh->getline;
+            $parser->can("decode_json")->($slurped); # decode_json does utf8 decoding for us
+          } || Catalyst::Exception->throw(sprintf "Error Parsing POST '%s', Error: %s", (defined($slurped) ? $slurped : 'undef') ,$@);
+        },
+    };
+}
+
+sub _handle_http_exception {
+    my ( $self, $error ) = @_;
+    if (
+           !$self->config->{always_catch_http_exceptions}
+        && blessed $error
+        && (
+            $error->can('as_psgi')
+            || (   $error->can('code')
+                && $error->code =~ m/^[1-5][0-9][0-9]$/ )
+        )
+      )
+    {
+        return 1;
+    }
+}
+
 =head2 $c->stack
 
 Returns an arrayref of the internal execution stack (actions that are
@@ -2872,6 +3986,33 @@ by itself.
 
 Returns or sets the stats (timing statistics) class. L<Catalyst::Stats|Catalyst::Stats> is used by default.
 
+=head2 $app->stats_class_traits
+
+A arrayref of L<Moose::Role>s that are applied to the stats_class before creating it.
+
+=head2 $app->composed_stats_class
+
+this is the stats_class composed with any 'stats_class_traits'.  You can
+name the full namespace of the role, or a namespace suffix, which will then
+be tried against the following standard namespace prefixes.
+
+    $MyApp::TraitFor::Stats::$trait_suffix
+    Catalyst::TraitFor::Stats::$trait_suffix
+
+So for example if you set:
+
+    MyApp->stats_class_traits(['Foo']);
+
+We try each possible role in turn (and throw an error if none load)
+
+    Foo
+    MyApp::TraitFor::Stats::Foo
+    Catalyst::TraitFor::Stats::Foo
+
+The namespace part 'TraitFor::Stats' was choosen to assist in backwards
+compatibility with L<CatalystX::RoleApplicator> which previously provided
+these features in a stand alone package.
+
 =head2 $c->use_stats
 
 Returns 1 when L<< stats collection|/"-Stats" >> is enabled.
@@ -2895,10 +4036,10 @@ your output data, if known.
 sub write {
     my $c = shift;
 
-    # Finalize headers if someone manually writes output
+    # Finalize headers if someone manually writes output (for compat)
     $c->finalize_headers;
 
-    return $c->engine->write( $c, @_ );
+    return $c->response->write( @_ );
 }
 
 =head2 version
@@ -2918,6 +4059,13 @@ There are a number of 'base' config variables which can be set:
 
 =item *
 
+C<always_catch_http_exceptions> - As of version 5.90060 Catalyst
+rethrows errors conforming to the interface described by
+L<Plack::Middleware::HTTPExceptions> and lets the middleware deal with it.
+Set true to get the deprecated behaviour and have Catalyst catch HTTP exceptions.
+
+=item *
+
 C<default_model> - The default model picked if you say C<< $c->model >>. See L<< /$c->model($name) >>.
 
 =item *
@@ -2951,7 +4099,7 @@ welcome screens
 
 C<parse_on_demand> - The request body (for example file uploads) will not be parsed
 until it is accessed. This allows you to (for example) check authentication (and reject
-the upload) before actually recieving all the data. See L</ON-DEMAND PARSER>
+the upload) before actually receiving all the data. See L</ON-DEMAND PARSER>
 
 =item *
 
@@ -2972,16 +4120,252 @@ to be shown in hit debug tables in the test server.
 
 =item *
 
-C<use_request_uri_for_path> - Controlls if the C<REQUEST_URI> or C<PATH_INFO> environment
-variable should be used for determining the request path. See L<Catalyst::Engine::CGI/PATH DECODING>
-for more information.
+C<use_request_uri_for_path> - Controls if the C<REQUEST_URI> or C<PATH_INFO> environment
+variable should be used for determining the request path.
+
+Most web server environments pass the requested path to the application using environment variables,
+from which Catalyst has to reconstruct the request base (i.e. the top level path to / in the application,
+exposed as C<< $c->request->base >>) and the request path below that base.
+
+There are two methods of doing this, both of which have advantages and disadvantages. Which method is used
+is determined by the C<< $c->config(use_request_uri_for_path) >> setting (which can either be true or false).
+
+=over
+
+=item use_request_uri_for_path => 0
+
+This is the default (and the) traditional method that Catalyst has used for determining the path information.
+The path is generated from a combination of the C<PATH_INFO> and C<SCRIPT_NAME> environment variables.
+The allows the application to behave correctly when C<mod_rewrite> is being used to redirect requests
+into the application, as these variables are adjusted by mod_rewrite to take account for the redirect.
+
+However this method has the major disadvantage that it is impossible to correctly decode some elements
+of the path, as RFC 3875 says: "C<< Unlike a URI path, the PATH_INFO is not URL-encoded, and cannot
+contain path-segment parameters. >>" This means PATH_INFO is B<always> decoded, and therefore Catalyst
+can't distinguish / vs %2F in paths (in addition to other encoded values).
+
+=item use_request_uri_for_path => 1
+
+This method uses the C<REQUEST_URI> and C<SCRIPT_NAME> environment variables. As C<REQUEST_URI> is never
+decoded, this means that applications using this mode can correctly handle URIs including the %2F character
+(i.e. with C<AllowEncodedSlashes> set to C<On> in Apache).
+
+Given that this method of path resolution is provably more correct, it is recommended that you use
+this unless you have a specific need to deploy your application in a non-standard environment, and you are
+aware of the implications of not being able to handle encoded URI paths correctly.
+
+However it also means that in a number of cases when the app isn't installed directly at a path, but instead
+is having paths rewritten into it (e.g. as a .cgi/fcgi in a public_html directory, with mod_rewrite in a
+.htaccess file, or when SSI is used to rewrite pages into the app, or when sub-paths of the app are exposed
+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
 
 =item *
 
 C<using_frontend_proxy> - See L</PROXY SUPPORT>.
 
+=item *
+
+C<using_frontend_proxy_path> - Enabled L<Plack::Middleware::ReverseProxyPath> on your application (if
+installed, otherwise log an error).  This is useful if your application is not running on the
+'root' (or /) of your host server.  B<NOTE> if you use this feature you should add the required
+middleware to your project dependency list since its not automatically a dependency of L<Catalyst>.
+This has been done since not all people need this feature and we wish to restrict the growth of
+L<Catalyst> dependencies.
+
+=item *
+
+C<encoding> - See L</ENCODING>
+
+This now defaults to 'UTF-8'.  You my turn it off by setting this configuration
+value to undef.
+
+=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.
+
+=item *
+
+C<use_hash_multivalue_in_request>
+
+In L<Catalyst::Request> the methods C<query_parameters>, C<body_parametes>
+and C<parameters> return a hashref where values might be scalar or an arrayref
+depending on the incoming data.  In many cases this can be undesirable as it
+leads one to writing defensive code like the following:
+
+    my ($val) = ref($c->req->parameters->{a}) ?
+      @{$c->req->parameters->{a}} :
+        $c->req->parameters->{a};
+
+Setting this configuration item to true will make L<Catalyst> populate the
+attributes underlying these methods with an instance of L<Hash::MultiValue>
+which is used by L<Plack::Request> and others to solve this very issue.  You
+may prefer this behavior to the default, if so enable this option (be warned
+if you enable it in a legacy application we are not sure if it is completely
+backwardly compatible).
+
+=item *
+
+C<skip_complex_post_part_handling>
+
+When creating body parameters from a POST, if we run into a multpart POST
+that does not contain uploads, but instead contains inlined complex data
+(very uncommon) we cannot reliably convert that into field => value pairs.  So
+instead we create an instance of L<Catalyst::Request::PartData>.  If this causes
+issue for you, you can disable this by setting C<skip_complex_post_part_handling>
+to true (default is false).  
+
+=item *
+
+C<skip_body_param_unicode_decoding>
+
+Generally we decode incoming POST params based on your declared encoding (the
+default for this is to decode UTF-8).  If this is causing you trouble and you
+do not wish to turn all encoding support off (with the C<encoding> configuration
+parameter) you may disable this step atomically by setting this configuration
+parameter to true.
+
+=item *
+
+C<do_not_decode_query>
+
+If true, then do not try to character decode any wide characters in your
+request URL query or keywords.  Most readings of the relevent specifications
+suggest these should be UTF-* encoded, which is the default that L<Catalyst>
+will use, hwoever if you are creating a lot of URLs manually or have external
+evil clients, this might cause you trouble.  If you find the changes introduced
+in Catalyst version 5.90080+ break some of your query code, you may disable 
+the UTF-8 decoding globally using this configuration.
+
+This setting takes precedence over C<default_query_encoding> and
+C<decode_query_using_global_encoding>
+
+=item *
+
+C<default_query_encoding>
+
+By default we decode query and keywords in your request URL using UTF-8, which
+is our reading of the relevent specifications.  This setting allows one to
+specify a fixed value for how to decode your query.  You might need this if
+you are doing a lot of custom encoding of your URLs and not using UTF-8.
+
+This setting take precedence over C<decode_query_using_global_encoding>.
+
+=item *
+
+C<decode_query_using_global_encoding>
+
+Setting this to true will default your query decoding to whatever your
+general global encoding is (the default is UTF-8).
+
+=item *
+
+C<use_chained_args_0_special_case>
+
+In older versions of Catalyst, when more than one action matched the same path
+AND all those matching actions declared Args(0), we'd break the tie by choosing
+the first action defined.  We now normalized how Args(0) works so that it
+follows the same rule as Args(N), which is to say when we need to break a tie
+we choose the LAST action defined.  If this breaks your code and you don't
+have time to update to follow the new normalized approach, you may set this
+value to true and it will globally revert to the original chaining behavior.
+
+=item *
+
+C<psgi_middleware> - See L<PSGI MIDDLEWARE>.
+
+=item *
+
+C<data_handlers> - See L<DATA HANDLERS>.
+
+=item *
+
+C<stats_class_traits>
+
+An arrayref of L<Moose::Role>s that get componsed into your stats class.
+
+=item *
+
+C<request_class_traits>
+
+An arrayref of L<Moose::Role>s that get componsed into your request class.
+
+=item *
+
+C<response_class_traits>
+
+An arrayref of L<Moose::Role>s that get componsed into your response class.
+
+=item *
+
+C<inject_components>
+
+A Hashref of L<Catalyst::Component> subclasses that are 'injected' into configuration.
+For example:
+
+    MyApp->config({
+      inject_components => {
+        'Controller::Err' => { from_component => 'Local::Controller::Errors' },
+        'Model::Zoo' => { from_component => 'Local::Model::Foo' },
+        'Model::Foo' => { from_component => 'Local::Model::Foo', roles => ['TestRole'] },
+      },
+      'Controller::Err' => { a => 100, b=>200, namespace=>'error' },
+      'Model::Zoo' => { a => 2 },
+      'Model::Foo' => { a => 100 },
+    });
+
+Generally L<Catalyst> looks for components in your Model/View or Controller directories.
+However for cases when you which to use an existing component and you don't need any
+customization (where for when you can apply a role to customize it) you may inject those
+components into your application.  Please note any configuration should be done 'in the
+normal way', with a key under configuration named after the component affix, as in the
+above example.
+
+Using this type of injection allows you to construct significant amounts of your application
+with only configuration!.  This may or may not lead to increased code understanding.
+
+Please not you may also call the ->inject_components application method as well, although
+you must do so BEFORE setup.
+
 =back
 
+=head1 EXCEPTIONS
+
+Generally when you throw an exception inside an Action (or somewhere in
+your stack, such as in a model that an Action is calling) that exception
+is caught by Catalyst and unless you either catch it yourself (via eval
+or something like L<Try::Tiny> or by reviewing the L</error> stack, it
+will eventually reach L</finalize_errors> and return either the debugging
+error stack page, or the default error page.  However, if your exception
+can be caught by L<Plack::Middleware::HTTPExceptions>, L<Catalyst> will
+instead rethrow it so that it can be handled by that middleware (which
+is part of the default middleware).  For example this would allow
+
+    use HTTP::Throwable::Factory 'http_throw';
+
+    sub throws_exception :Local {
+      my ($self, $c) = @_;
+
+      http_throw(SeeOther => { location =>
+        $c->uri_for($self->action_for('redirect')) });
+
+    }
+
 =head1 INTERNAL ACTIONS
 
 Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
@@ -3040,7 +4424,26 @@ headers.
 
 If you do not wish to use the proxy support at all, you may set:
 
-    MyApp->config(ignore_frontend_proxy => 1);
+    MyApp->config(ignore_frontend_proxy => 0);
+
+=head2 Note about psgi files
+
+Note that if you supply your own .psgi file, calling
+C<< MyApp->psgi_app(@_); >>, then B<this will not happen automatically>.
+
+You either need to apply L<Plack::Middleware::ReverseProxy> yourself
+in your psgi, for example:
+
+    builder {
+        enable "Plack::Middleware::ReverseProxy";
+        MyApp->psgi_app
+    };
+
+This will unconditionally add the ReverseProxy support, or you need to call
+C<< $app = MyApp->apply_default_middlewares($app) >> (to conditionally
+apply the support depending upon your config).
+
+See L<Catalyst::PSGI> for more information.
 
 =head1 THREAD SAFETY
 
@@ -3052,6 +4455,272 @@ 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 DATA HANDLERS
+
+The L<Catalyst::Request> object uses L<HTTP::Body> to populate 'classic' HTML
+form parameters and URL search query fields.  However it has become common
+for various alternative content types to be PUT or POSTed to your controllers
+and actions.  People working on RESTful APIs, or using AJAX often use JSON,
+XML and other content types when communicating with an application server.  In
+order to better support this use case, L<Catalyst> defines a global configuration
+option, C<data_handlers>, which lets you associate a content type with a coderef
+that parses that content type into something Perl can readily access.
+
+    package MyApp::Web;
+    use Catalyst;
+    use JSON::Maybe;
+    __PACKAGE__->config(
+      data_handlers => {
+        'application/json' => sub { local $/; decode_json $_->getline },
+      },
+      ## Any other configuration.
+    );
+    __PACKAGE__->setup;
+
+By default L<Catalyst> comes with a generic JSON data handler similar to the
+example given above, which uses L<JSON::Maybe> to provide either L<JSON::PP>
+(a pure Perl, dependency free JSON parser) or L<Cpanel::JSON::XS> if you have
+it installed (if you want the faster XS parser, add it to you project Makefile.PL
+or dist.ini, cpanfile, etc.)
+
+The C<data_handlers> configuration is a hashref whose keys are HTTP Content-Types
+(matched against the incoming request type using a regexp such as to be case
+insensitive) and whose values are coderefs that receive a localized version of
+C<$_> which is a filehandle object pointing to received body.
+
+This feature is considered an early access release and we reserve the right
+to alter the interface in order to provide a performant and secure solution to
+alternative request body content.  Your reports welcomed!
+
+=head1 PSGI MIDDLEWARE
+
+You can define middleware, defined as L<Plack::Middleware> or a compatible
+interface in configuration.  Your middleware definitions are in the form of an
+arrayref under the configuration key C<psgi_middleware>.  Here's an example
+with details to follow:
+
+    package MyApp::Web;
+    use Catalyst;
+    use Plack::Middleware::StackTrace;
+    my $stacktrace_middleware = Plack::Middleware::StackTrace->new;
+    __PACKAGE__->config(
+      'psgi_middleware', [
+        'Debug',
+        '+MyApp::Custom',
+        $stacktrace_middleware,
+        'Session' => {store => 'File'},
+        sub {
+          my $app = shift;
+          return sub {
+            my $env = shift;
+            $env->{myapp.customkey} = 'helloworld';
+            $app->($env);
+          },
+        },
+      ],
+    );
+    __PACKAGE__->setup;
+
+So the general form is:
+
+    __PACKAGE__->config(psgi_middleware => \@middleware_definitions);
+
+Where C<@middleware> is one or more of the following, applied in the REVERSE of
+the order listed (to make it function similarly to L<Plack::Builder>:
+
+Alternatively, you may also define middleware by calling the L</setup_middleware>
+package method:
+
+    package MyApp::Web;
+
+    use Catalyst;
+
+    __PACKAGE__->setup_middleware( \@middleware_definitions);
+    __PACKAGE__->setup;
+
+In the case where you do both (use 'setup_middleware' and configuration) the
+package call to setup_middleware will be applied earlier (in other words its
+middleware will wrap closer to the application).  Keep this in mind since in
+some cases the order of middleware is important.
+
+The two approaches are not exclusive.
+=over 4
+=item Middleware Object
+An already initialized object that conforms to the L<Plack::Middleware>
+specification:
+    my $stacktrace_middleware = Plack::Middleware::StackTrace->new;
+    __PACKAGE__->config(
+      'psgi_middleware', [
+        $stacktrace_middleware,
+      ]);
+=item coderef
+A coderef that is an inlined middleware:
+    __PACKAGE__->config(
+      'psgi_middleware', [
+        sub {
+          my $app = shift;
+          return sub {
+            my $env = shift;
+            if($env->{PATH_INFO} =~m/forced/) {
+              Plack::App::File
+                ->new(file=>TestApp->path_to(qw/share static forced.txt/))
+                ->call($env);
+            } else {
+              return $app->($env);
+            }
+         },
+      },
+    ]);
+=item a scalar
+We assume the scalar refers to a namespace after normalizing it using the
+following rules:
+
+(1) If the scalar is prefixed with a "+" (as in C<+MyApp::Foo>) then the full string
+is assumed to be 'as is', and we just install and use the middleware.
+
+(2) If the scalar begins with "Plack::Middleware" or your application namespace
+(the package name of your Catalyst application subclass), we also assume then
+that it is a full namespace, and use it.
+
+(3) Lastly, we then assume that the scalar is a partial namespace, and attempt to
+resolve it first by looking for it under your application namespace (for example
+if you application is "MyApp::Web" and the scalar is "MyMiddleware", we'd look
+under "MyApp::Web::Middleware::MyMiddleware") and if we don't find it there, we
+will then look under the regular L<Plack::Middleware> namespace (i.e. for the
+previous we'd try "Plack::Middleware::MyMiddleware").  We look under your application
+namespace first to let you 'override' common L<Plack::Middleware> locally, should
+you find that a good idea.
+
+Examples:
+
+    package MyApp::Web;
+
+    __PACKAGE__->config(
+      'psgi_middleware', [
+        'Debug',  ## MyAppWeb::Middleware::Debug->wrap or Plack::Middleware::Debug->wrap
+        'Plack::Middleware::Stacktrace', ## Plack::Middleware::Stacktrace->wrap
+        '+MyApp::Custom',  ## MyApp::Custom->wrap
+      ],
+    );
+=item a scalar followed by a hashref
+Just like the previous, except the following C<HashRef> is used as arguments
+to initialize the middleware object.
+    __PACKAGE__->config(
+      'psgi_middleware', [
+         'Session' => {store => 'File'},
+    ]);
+
+=back
+
+Please see L<PSGI> for more on middleware.
+
+=head1 ENCODING
+
+Starting in L<Catalyst> version 5.90080 encoding is automatically enabled
+and set to encode all body responses to UTF8 when possible and applicable.
+Following is documentation on this process.  If you are using an older
+version of L<Catalyst> you should review documentation for that version since
+a lot has changed.
+
+By default encoding is now 'UTF-8'.  You may turn it off by setting
+the encoding configuration to undef.
+
+    MyApp->config(encoding => undef);
+
+This is recommended for temporary backwards compatibility only.
+
+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$/
+
+Encoding is set on the application, but it is copied to the context object
+so that you can override it on a request basis.
+
+Be default we don't automatically encode 'application/json' since the most
+common approaches to generating this type of response (Either via L<Catalyst::View::JSON>
+or L<Catalyst::Action::REST>) will do so already and we want to avoid double
+encoding issues.
+
+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 necessary encoding yourself, since
+we cannot encode the gzipped contents.  If you use a plugin like
+L<Catalyst::Plugin::Compress> you need to update to a modern version in order
+to have this function correctly  with the new UTF8 encoding code, or you
+can use L<Plack::Middleware::Deflater> or (probably best) do your compression on
+a front end proxy.
+
+=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:
@@ -3101,6 +4770,8 @@ acme: Leon Brocard <leon@astray.com>
 
 abraxxa: Alexander Hartmaier <abraxxa@cpan.org>
 
+andrewalker: AndrĂ© Walker <andre@cpan.org>
+
 Andrew Bramble
 
 Andrew Ford E<lt>A.Ford@ford-mason.co.ukE<gt>
@@ -3123,6 +4794,8 @@ Chisel Wright C<pause@herlpacker.co.uk>
 
 Danijel Milicevic C<me@danijel.de>
 
+davewood: David Schmidt <davewood@cpan.org>
+
 David Kamholz E<lt>dkamholz@cpan.orgE<gt>
 
 David Naughton, C<naughton@umn.edu>
@@ -3179,6 +4852,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
@@ -3217,13 +4892,15 @@ t0m: Tomas Doran <bobtfish@bobtfish.net>
 
 Ulf Edvinsson
 
+vanstyn: Henry Van Styn <vanstyn@cpan.org>
+
 Viljo Marrandi C<vilts@yahoo.com>
 
 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>
 
@@ -3231,9 +4908,13 @@ rainboxx: Matthias Dietrich, C<perl@rainboxx.de>
 
 dd070: Dhaval Dhanani <dhaval070@gmail.com>
 
+Upasana <me@upasana.me>
+
+John Napiorkowski (jnap) <jjnapiork@cpan.org>
+
 =head1 COPYRIGHT
 
-Copyright (c) 2005, the above named PROJECT FOUNDER and CONTRIBUTORS.
+Copyright (c) 2005-2015, the above named PROJECT FOUNDER and CONTRIBUTORS.
 
 =head1 LICENSE