The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Catalyst-Runtime-5.90061/t/lib/TestContentNegotiation/share/file.txt 500
Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static/forced.txt 10
Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static2/message2.txt 10
Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static3/message3.txt 10
Changes 074
MANIFEST 123
META.yml 3131
Makefile.PL 10
lib/Catalyst/ActionChain.pm 27
lib/Catalyst/Delta.pod 1533
lib/Catalyst/Engine.pm 01
lib/Catalyst/Log.pm 027
lib/Catalyst/Middleware/Stash.pm 0119
lib/Catalyst/Plugin/Unicode/Encoding.pm 1933
lib/Catalyst/Response.pm 079
lib/Catalyst/Runtime.pm 11
lib/Catalyst/Script/Server.pm 02
lib/Catalyst/Utils.pm 1022
lib/Catalyst.pm 45248
t/aggregate/live_engine_request_env.t 2119
t/aggregate/live_engine_response_headers.t 156
t/aggregate/live_plugin_loaded.t 10
t/aggregate/unit_core_component_layers.t 14
t/aggregate/unit_core_log.t 28
t/aggregate/unit_core_log_autoflush.t 066
t/aggregate/unit_core_mvc.t 1010
t/aggregate/unit_core_plugin.t 10
t/aggregate/unit_core_script_server.t 11
t/author/spelling.t 15
t/head_middleware.t 049
t/http_exceptions.t 216
t/lib/PluginTestApp/Controller/Root.pm 10
t/lib/PluginTestApp.pm 10
t/lib/TestApp/Controller/ContextClosure.pm 05
t/lib/TestApp/Controller/Dump.pm 60
t/lib/TestApp/Controller/Engine/Response/Headers.pm 11
t/lib/TestApp/Controller/Log.pm 05
t/lib/TestApp/View/Dump/Env.pm 01
t/lib/TestLogger.pm 07
t/live_component_controller_context_closure.t 210
t/psgi-log.t 69
t/psgi_file_testapp_engine_plackup_compat.t 410
t/psgi_file_testapp_engine_psgi_compat.t 400
t/psgi_utils.t 783
44 files changed (This is a version diff) 523955
@@ -1,50 +0,0 @@
-package TestContentNegotiation::Controller::Root;
-
-use Moose;
-use MooseX::MethodAttributes;
-
-extends 'Catalyst::Controller';
-
-sub start :Chained(/) PathPrefix CaptureArgs(0) { }
-
-    sub is_json       : Chained('start') PathPart('') Consumes('application/json') Args(0) { pop->res->body('is_json') }
-    sub is_urlencoded : Chained('start') PathPart('') Consumes('application/x-www-form-urlencoded') Args(0) { pop->res->body('is_urlencoded') }
-    sub is_multipart  : Chained('start') PathPart('') Consumes('multipart/form-data') Args(0) { pop->res->body('is_multipart') }
-      
-    sub under :Chained('start') CaptureArgs(0) { }
-
-      sub is_json_under       : Chained('under') PathPart('') Consumes(JSON) Args(0) { pop->res->body('is_json') }
-      sub is_urlencoded_under : Chained('under') PathPart('') Consumes(UrlEncoded) Args(0) { pop->res->body('is_urlencoded') }
-      sub is_multipart_under  : Chained('under') PathPart('') Consumes(Multipart) Args(0) { pop->res->body('is_multipart') }
-
-      ## Or allow more than one type
-    
-    sub multi :Chained('start') CaptureArgs(0) { }
-      
-    sub is_more_than_one_1
-      : Chained('multi') PathPart('')
-      : Consumes('application/x-www-form-urlencoded')
-      : Consumes('multipart/form-data')
-      : Args(0)
-    {
-      pop->res->body('formdata1');
-    }
-
-    sub is_more_than_one_2
-      : Chained('multi') PathPart('')
-      : Consumes('HTMLForm')
-      : Args(0)
-    {
-      pop->res->body('formdata2');
-    }
-
-    sub is_more_than_one_3
-      : Chained('multi') PathPart('')
-      : Consumes('application/x-www-form-urlencoded,multipart/form-data')
-      : Args(0)
-    {
-      pop->res->body('formdata3');
-    }
-
-
-__PACKAGE__->meta->make_immutable;
@@ -1,5 +1,79 @@
 # This file documents the revision history for Perl extension Catalyst.
 
+5.90071 - 2014-08-10
+  - Travis config now performs basic reverse dependency testing.
+  - Restored deprecated 'env' code in Engine.pm b/c it is still being used out
+    in the wild (Catalyst-Plugin-Authentication-0.10023) - (removed in 5.90070)
+  - Reverted changes to debug log/handling (5.90069_003) to fix
+    rev dep Catalyst-Plugin-Static-Simple-0.32 test suite.
+  - Added italian translation of default error.
+
+5.90070 - 2014-08-07
+  - Retagged previous release as stable; no changes
+
+5.90069_004
+  - Fixed typo in middleware stash that was causing older Perls to fail
+    certain tests.  No other changes.
+
+5.90069_003
+  - The default log level is now 'info', not 'debug'.
+  - Finished merging all the encoding plugin code to core code.  The encoding
+    plugin is now just an empty package.  Also tried to improve encoding docs
+    a bit.
+  - Some additional changes to the stash middleware that should not break
+    anything new.
+  - Documentation around using Sendfile type http headers with a filehandle
+    type response.
+  - Merged from master branch to pick up some additional fixes and documentation
+    improvements.
+
+5.90069_002
+  - Catalyst stash functionality has been moved to Middleware.  It should
+    work entirely the same when used as a context method, please report
+    questions or problems!
+  - Removed code related to supporting the long deprecated stand alone
+    PSGI Engine.  If you are still using this you code is now broken.
+    Luckily you can just stop using it and likely everything will work
+    under the new PSGI support built into Catalyst for several years.
+  - 'abort_chain_on_error_fix' now defaults to true.  If this behavior
+    causes you issues, you can explicitly turn it off by setting it to a 
+    non true defined value (0 is a good option here).
+  - When throwing an http style exception, make sure we properly flush the
+    existing log and report other errors in the error stack.
+
+5.90069_001
+  - Set encoding on STDERR when encoding is set in config
+  - documentation and test fixes
+
+5.90065 - 2014-06-04
+  - The Catalyst::Log object now has 'autoflush' (which defaults to true) and
+    causes log messages to be written out in real-time. This is helpful for the
+    test/dev server to be able to see messages during startup as well as before
+    the end of the request when the log is flushed.
+  - Fix spelling, grammar and structural errors in POD
+  - Remove redundant ->setup call in t/head_middleware.t RT#95361
+  - Fix test failures when running under CATALYST_DEBUG. RT#95358
+
+5.90064 - 2014-05-05
+  - Fix for mindless broken tests on Win32 (Haarg++).
+  - Happy Cinco de Mayo!
+
+5.90063 - 2014-05-01
+  - 'end' and other special actions won't catch HTTP style exceptions anymore.
+  - Fix bug where Catalyst did not properly detect the terminal width when in
+    debug mode and thus making the debug output narrow and hard to read.
+  - Documentation corrections for Util methods around localized PSGI $env.
+  - Improvements to auto detection of terminal width.
+  - Updating deprecation list to include Class::Load and ensure_class_loaded
+  - Added a few docs around middleware and corrected the order that middleware
+    is loaded when registering it via ->setup_middleware instead of via
+    configuration.
+  - Added a test case to make sure default middleware order is correct.
+s
+5.90062 - 2014-04-14
+  - HTTP::Exception objects were not properly bubbled up to middleware since
+    there was some code in Catalyst that was triggering stringification.
+
 5.90061 - 2014-03-10
   - Reverted a change related to how plugins get initialized that was
     introduced by a change in December.
@@ -1,13 +1,3 @@
-Catalyst-Runtime-5.90061/t/lib/TestAppEncodingSetInConfig/testappencodingsetinconfig.json
-Catalyst-Runtime-5.90061/t/lib/TestContentNegotiation/share/file.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddleware/share/static/forced.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddleware/share/static/message.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddleware/share/static2/message2.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddleware/share/static3/message3.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static/forced.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static/message.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static2/message2.txt
-Catalyst-Runtime-5.90061/t/lib/TestMiddlewareFromConfig/share/static3/message3.txt
 Changes
 inc/Module/AutoInstall.pm
 inc/Module/Install.pm
@@ -53,6 +43,7 @@ lib/Catalyst/Exception/Detach.pm
 lib/Catalyst/Exception/Go.pm
 lib/Catalyst/Exception/Interface.pm
 lib/Catalyst/Log.pm
+lib/Catalyst/Middleware/Stash.pm
 lib/Catalyst/Model.pm
 lib/Catalyst/Plugin/Unicode/Encoding.pm
 lib/Catalyst/PSGI.pod
@@ -164,6 +155,7 @@ t/aggregate/unit_core_engine-prepare_path.t
 t/aggregate/unit_core_engine_fixenv-iis6.t
 t/aggregate/unit_core_engine_fixenv-lighttpd.t
 t/aggregate/unit_core_log.t
+t/aggregate/unit_core_log_autoflush.t
 t/aggregate/unit_core_merge_config_hashes.t
 t/aggregate/unit_core_mvc.t
 t/aggregate/unit_core_path_to.t
@@ -216,6 +208,7 @@ t/deprecated.t
 t/deprecated_appclass_action_warnings.t
 t/encoding_set_in_app.t
 t/encoding_set_in_config.t
+t/head_middleware.t
 t/http_exceptions.t
 t/http_method.t
 t/lib/ACLTestApp.pm
@@ -449,8 +442,6 @@ t/plack-middleware.t
 t/plugin_new_method_backcompat.t
 t/psgi-log.t
 t/psgi_file_testapp.t
-t/psgi_file_testapp_engine_plackup_compat.t
-t/psgi_file_testapp_engine_psgi_compat.t
 t/psgi_utils.t
 t/remove_redundant_body.t
 t/something/Makefile.PL
@@ -10,7 +10,7 @@ build_requires:
   IO::Scalar: 0
   JSON::MaybeXS: 0
   Test::Fatal: 0
-  Test::More: '0.88'
+  Test::More: 0.88
 configure_requires:
   ExtUtils::MakeMaker: 6.59
 distribution_type: module
@@ -26,64 +26,64 @@ no_index:
     - inc
     - t
 requires:
-  CGI::Simple::Cookie: '1.109'
+  CGI::Simple::Cookie: 1.109
   CGI::Struct: 0
   Carp: 0
-  Class::C3::Adopt::NEXT: '0.07'
+  Class::C3::Adopt::NEXT: 0.07
   Class::Data::Inheritable: 0
-  Class::Load: '0.12'
+  Class::Load: 0.12
   Data::Dump: 0
   Data::OptList: 0
   Devel::InnerPackage: 0
-  Encode: '2.49'
+  Encode: 2.49
   HTML::Entities: 0
   HTML::HeadParser: 0
-  HTTP::Body: '1.06'
-  HTTP::Headers: '1.64'
-  HTTP::Request: '5.814'
-  HTTP::Request::AsCGI: '1.0'
-  HTTP::Response: '5.813'
+  HTTP::Body: 1.06
+  HTTP::Headers: 1.64
+  HTTP::Request: 5.814
+  HTTP::Request::AsCGI: 1.0
+  HTTP::Response: 5.813
   Hash::MultiValue: 0
-  JSON::MaybeXS: '1.000000'
-  LWP: '5.837'
+  JSON::MaybeXS: 1.000000
+  LWP: 5.837
   List::MoreUtils: 0
   MRO::Compat: 0
-  Module::Pluggable: '4.7'
-  Moose: '1.03'
-  MooseX::Emulate::Class::Accessor::Fast: '0.00903'
-  MooseX::Getopt: '0.48'
-  MooseX::MethodAttributes::Role::AttrContainer::Inheritable: '0.24'
-  MooseX::Role::WithOverloading: '0.09'
-  Path::Class: '0.09'
-  Plack: '0.9991'
+  Module::Pluggable: 4.7
+  Moose: 1.03
+  MooseX::Emulate::Class::Accessor::Fast: 0.00903
+  MooseX::Getopt: 0.48
+  MooseX::MethodAttributes::Role::AttrContainer::Inheritable: 0.24
+  MooseX::Role::WithOverloading: 0.09
+  Path::Class: 0.09
+  Plack: 0.9991
   Plack::Middleware::Conditional: 0
   Plack::Middleware::ContentLength: 0
-  Plack::Middleware::FixMissingBodyInRedirect: '0.09'
+  Plack::Middleware::FixMissingBodyInRedirect: 0.09
   Plack::Middleware::HTTPExceptions: 0
   Plack::Middleware::Head: 0
   Plack::Middleware::IIS6ScriptNameFix: 0
   Plack::Middleware::IIS7KeepAliveFix: 0
   Plack::Middleware::LighttpdScriptNameFix: 0
   Plack::Middleware::MethodOverride: 0
-  Plack::Middleware::RemoveRedundantBody: '0.03'
-  Plack::Middleware::ReverseProxy: '0.04'
+  Plack::Middleware::RemoveRedundantBody: 0.03
+  Plack::Middleware::ReverseProxy: 0.04
   Plack::Request::Upload: 0
   Plack::Test::ExternalServer: 0
   Safe::Isa: 0
   Scalar::Util: 0
   Stream::Buffered: 0
-  String::RewritePrefix: '0.004'
+  String::RewritePrefix: 0.004
   Sub::Exporter: 0
   Task::Weaken: 0
   Text::Balanced: 0
-  Text::SimpleTable: '0.03'
+  Text::SimpleTable: 0.03
   Time::HiRes: 0
-  Tree::Simple: '1.15'
+  Tree::Simple: 1.15
   Tree::Simple::Visitor::FindByPath: 0
-  Try::Tiny: '0.17'
-  URI: '1.36'
-  namespace::autoclean: '0.09'
-  namespace::clean: '0.23'
+  Try::Tiny: 0.17
+  URI: 1.36
+  namespace::autoclean: 0.09
+  namespace::clean: 0.23
   perl: 5.8.3
 resources:
   IRC: irc://irc.perl.org/#catalyst
@@ -91,5 +91,5 @@ resources:
   homepage: http://dev.catalyst.perl.org/
   license: http://dev.perl.org/licenses/
   repository: git://git.shadowcat.co.uk/catagits/Catalyst-Runtime.git
-version: '5.90061'
+version: 5.90071
 x_authority: cpan:MSTROUT
@@ -119,7 +119,6 @@ author_requires(
   @author_requires,
   map {; $_ => 0 } qw(
   File::Copy::Recursive
-  Catalyst::Engine::PSGI
   Test::Without::Module
   Starman
   MooseX::Daemonize
@@ -35,8 +35,13 @@ sub dispatch {
         local $c->request->{arguments} = \@args;
         $action->dispatch( $c );
 
-        # break the chain if exception occurs in the middle of chain
-        return if (@{$c->error} && $c->config->{abort_chain_on_error_fix});
+        # break the chain if exception occurs in the middle of chain.  We
+        # check the global config flag 'abort_chain_on_error_fix', but this
+        # is now considered true by default, so unless someone explictly sets
+        # it to false we default it to true (if its not defined).
+        my $abort = defined($c->config->{abort_chain_on_error_fix}) ?
+          $c->config->{abort_chain_on_error_fix} : 1;
+        return if ($c->has_errors && $abort);
     }
     $last->dispatch( $c );
 }
@@ -9,6 +9,24 @@ Catalyst releases.
 
 =head2 VERSION 5.90060+
 
+=head3 Catalyst::Log object autoflush on by default
+
+Starting in 5.90065, the Catalyst::Log object has 'autoflush' which is on
+by default. This causes all messages to be written to the log immediately
+instead of at the end of startup and then at the end of each request. In
+order to access the old behavior, you must now call:
+
+  $c->log->autoflush(0);
+
+=head3 Deprecate Catalyst::Utils::ensure_class_loaded
+
+Going forward we recommend you use L<Module::Runtime>.  In fact we will
+be converting all uses of L<Class::Load> to L<Module::Runtime>.  We will
+also convert L<Catalyst::Utils\ensure_class_loaded> to be based on
+L<Module::Runtime> to allow some time for you to update code, however at
+some future point this method will be removed so you should stop
+using it now.
+
 =head3 Support passing Body filehandles directly to your Plack server.
 
 We changed the way we return body content (from response) to whatever
@@ -17,7 +35,7 @@ always use the streaming interface for the cases when the body is a
 simple scalar, object or filehandle like.  In those cases we now just
 pass the simple response on to the plack handler.  This might lead to
 some minor differences in how streaming is handled.  For example, you
-might notice that streaming starts properly supportubg chunked encoding when
+might notice that streaming starts properly supporting chunked encoding when
 on a server that supports that, or that previously missing headers
 (possible content-length) might appear suddenly correct.  Also, if you
 are using middleware like L<Plack::Middleware::XSendfile> and are using
@@ -36,7 +54,7 @@ using one server but deploying using a different one, differences in
 what those server do with streaming should be noted.
 
 Please see note below about changes to filehandle support and existing
-Plack middleware to aid in back compatibility.
+Plack middleware to aid in backwards compatibility.
 
 =head3 Distinguish between body null versus undef.
 
@@ -59,7 +77,7 @@ so we benefit from better collaboration with developers outside Catalyst, 3)
 In the future you'll be able to change or trim the middleware stack to get
 additional performance when you don't need all the checks and constraints.
 
-=head3 Deprecation of Filehandle like objects that do read but not getline
+=head3 Deprecate Filehandle like objects that do read but not getline
 
 We also deprecated setting the response body to an object that does 'read'
 but not 'getline'.  If you are using a custom IO-Handle like object for
@@ -70,31 +88,31 @@ will issue a warning.  You also may run into this issue with L<MogileFS::Client>
 which does read but not getline.  For now we will just warn when encountering
 such an object and fallback to the previous behavior (where L<Catalyst::Engine>
 itself unrolls the filehandle and performs blocking streams).  However
-this backcompat will be removed in an upcoming release so you should either
+this backwards compatibility will be removed in an upcoming release so you should either
 rewrite your custom filehandle objects to support getline or start using the 
 middleware that adapts read for getline L<Plack::Middleware::AdaptFilehandleRead>.
 
-=head3 Response->headers become readonly after finalizing
+=head3 Response->headers become read-only after finalizing
 
 Once the response headers are finalized, trying to change them is not allowed
 (in the past you could change them and this would lead to unexpected results).
 
-=head3 Offically deprecation of L<Catalyst::Engine::PSGI>
+=head3 Officially deprecate L<Catalyst::Engine::PSGI>
 
 L<Catalyst::Engine::PSGI> is also officially no longer supported.  We will
-no long run test cases against this and can remove backcompat code for it
-as deemed necessary for the evolution of the platform.  You should simple
-discontinue use of this engine, as L<Catalyst> has been PSGI at the core
-for several years.
+no long run test cases against this and can remove backwards compatibility code for it
+as deemed necessary for the evolution of the platform.  You should simply
+discontinue use of this engine, as L<Catalyst> has been PSGI at the core for
+several years.
 
-=head2 Officially deprecate finding the PSGI $env anyplace other than Request
+=head3 Officially deprecate finding the PSGI $env anyplace other than Request
 
 A few early releases of Cataplack had the PSGI $env in L<Catalyst::Engine>.
-Code has been maintained here for backcompat reasons.  This is no longer
-supported and will be removed in upcoming release, so you should update
+Code has been maintained here for backwards compatibility reasons.  This is no
+longer supported and will be removed in upcoming release, so you should update
 your code and / or upgrade to a newer version of L<Catalyst>
 
-=head2 Deprecate setting Response->body after using write/write_fh
+=head3 Deprecate setting Response->body after using write/write_fh
 
 Setting $c->res->body to a filehandle after using $c->res->write or
 $c->res->write_fh is no longer considered allowed, since we can't send
@@ -232,7 +250,7 @@ Below is a brief list of features which have been deprecated in this release:
 
 =item MyApp->plugin method is deprecated, use L<Catalyst::Model::Adaptor> instead.
 
-=item __PACKAGE__->mk_accessors() is supported for backward compatibility only, use Moose attributes instead in new code.
+=item __PACKAGE__->mk_accessors() is supported for backwards compatibility only, use Moose attributes instead in new code.
 
 =item Use of Catalyst::Base now warns
 
@@ -305,6 +305,7 @@ sub finalize_error {
 (pt) Por favor volte mais tarde
 (ru) Попробуйте еще раз позже
 (ua) Спробуйте ще раз пізніше
+(it) Per favore riprova più tardi
 </pre>
 
         $name = '';
@@ -13,6 +13,7 @@ our %LEVEL_MATCH = (); # Stored as additive, thus debug = 31, warn = 30 etc
 has level => (is => 'rw');
 has _body => (is => 'rw');
 has abort => (is => 'rw');
+has autoflush => (is => 'rw', default => sub {1});
 has _psgi_logger => (is => 'rw', predicate => '_has_psgi_logger', clearer => '_clear_psgi_logger');
 has _psgi_errors => (is => 'rw', predicate => '_has_psgi_errors', clearer => '_clear_psgi_errors');
 
@@ -118,6 +119,10 @@ sub _log {
         $body .= sprintf( "[%s] %s", $level, $message );
         $self->_body($body);
     }
+    if( $self->autoflush && !$self->abort ) {
+      $self->_flush;
+    }
+    return 1;
 }
 
 sub _flush {
@@ -284,6 +289,28 @@ to use Log4Perl or another logger, you should call it like this:
 
     $c->log->abort(1) if $c->log->can('abort');
 
+=head2 autoflush
+
+When enabled (default), messages are written to the log immediately instead 
+of queued until the end of the request. 
+
+This option, as well as C<abort>, is provided for modules such as 
+L<Catalyst::Plugin::Static::Simple> to be able to programmatically 
+suppress the output of log messages. By turning off C<autoflush> (application-wide
+setting) and then setting the C<abort> flag within a given request, all log 
+messages for the given request will be suppressed. C<abort> can still be set
+independently of turning off C<autoflush>, however. It just means any messages 
+sent to the log up until that point in the request will obviously still be emitted, 
+since C<autoflush> means they are written in real-time.
+
+If you need to turn off autoflush you should do it like this (in your main app 
+class):
+
+    after setup_finalize => sub {
+      my $c = shift;
+      $c->log->autoflush(0) if $c->log->can('autoflush');
+    };
+
 =head2 _send_to_log
 
  $log->_send_to_log( @messages );
@@ -0,0 +1,119 @@
+use strict;
+use warnings;
+
+package Catalyst::Middleware::Stash;
+
+use base 'Plack::Middleware';
+use Exporter 'import';
+use Carp 'croak';
+
+our @EXPORT_OK = qw(stash get_stash);
+
+sub PSGI_KEY { 'Catalyst.Stash.v1' };
+
+sub get_stash {
+  my $env = shift;
+  return $env->{&PSGI_KEY} ||
+    _init_stash_in($env);
+}
+
+sub stash {
+  my ($host, @args) = @_;
+  return get_stash($host->env)
+    ->(@args);
+}
+
+sub _create_stash {
+  my $stash = shift || +{};
+  return sub {
+    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};
+      }
+    }
+    $stash;
+  };
+}
+
+sub _init_stash_in {
+  my ($env) = @_;
+  return $env->{&PSGI_KEY} ||=
+    _create_stash;
+}
+
+sub call {
+  my ($self, $env) = @_;
+  _init_stash_in($env);
+  return $self->app->($env);
+}
+
+=head1 TITLE
+
+Catalyst::Middleware::Stash - The Catalyst stash - in middleware
+
+=head1 DESCRIPTION
+
+We've moved the L<Catalyst> stash to middleware.  Please don't use this
+directly since it is likely to move off the Catalyst namespace into a stand
+alone distribution
+
+We store a coderef under the C<PSGI_KEY> which can be dereferenced with
+key values or nothing to access the underly hashref.
+
+=head1 SUBROUTINES
+
+This class defines the following subroutines.
+
+=head2 PSGI_KEY
+
+Returns the hash key where we store the stash.  You should not assume
+the string value here will never change!  Also, its better to use
+L</get_stash> or L</stash>.
+
+=head2 get_stash
+
+Expect: $psgi_env.
+
+Exportable subroutine.
+
+Get the stash out of the C<$env>.
+
+=head2 stash
+
+Expects: An object that does C<env> and arguments
+
+Exportable subroutine.
+
+Given an object with a method C<env> get or set stash values, either
+as a method or via hashref modification.  This stash is automatically
+reset for each request (it is not persistent or shared across connected
+clients.  Stash key / value are stored in memory.
+
+    use Plack::Request;
+    use Catalyst::Middleware::Stash 'stash';
+
+    my $app = sub {
+      my $env = shift;
+      my $req = Plack::Request->new($env);
+      my $stashed = $req->stash->{in_the_stash};  # Assume the stash was previously populated.
+
+      return [200, ['Content-Type' => 'text/plain'],
+        ["I found $stashed in the stash!"]];
+    };
+
+If the stash does not yet exist, we initialize one and return that.
+
+=head1 METHODS
+
+This class defines the following methods.
+
+=head2 call
+
+Used by plack to call the middleware
+
+=cut
+
+1;
@@ -1,207 +1,17 @@
 package Catalyst::Plugin::Unicode::Encoding;
 
-use strict;
-use base 'Class::Data::Inheritable';
-
-use Carp ();
-use MRO::Compat;
-use Try::Tiny;
-
-use Encode 2.21 ();
-our $CHECK = Encode::FB_CROAK | Encode::LEAVE_SRC;
-
-our $VERSION = '2.1';
-
-__PACKAGE__->mk_classdata('_encoding');
-
-sub encoding {
-    my $c = shift;
-    my $encoding;
-
-    if ( scalar @_ ) {
-        # Let it be set to undef
-        if (my $wanted = shift)  {
-            $encoding = Encode::find_encoding($wanted)
-              or Carp::croak( qq/Unknown encoding '$wanted'/ );
-        }
-
-        $encoding = ref $c
-                  ? $c->{encoding} = $encoding
-                  : $c->_encoding($encoding);
-    } else {
-      $encoding = ref $c && exists $c->{encoding}
-                ? $c->{encoding}
-                : $c->_encoding;
-    }
-
-    return $encoding;
-}
-
-sub finalize_headers {
-    my $c = shift;
-
-    my $body = $c->response->body;
-
-    return $c->next::method(@_)
-      unless defined($body);
-
-    my $enc = $c->encoding;
-
-    return $c->next::method(@_)
-      unless $enc;
-
-    my ($ct, $ct_enc) = $c->response->content_type;
-
-    # Only touch 'text-like' contents
-    return $c->next::method(@_)
-      unless $c->response->content_type =~ /^text|xml$|javascript$/;
-
-    if ($ct_enc && $ct_enc =~ /charset=([^;]*)/) {
-        if (uc($1) ne uc($enc->mime_name)) {
-            $c->log->debug("Unicode::Encoding is set to encode in '" .
-                           $enc->mime_name .
-                           "', content type is '$1', not encoding ");
-            return $c->next::method(@_);
-        }
-    } else {
-        $c->res->content_type($c->res->content_type . "; charset=" . $enc->mime_name);
-    }
-
-    # Encode expects plain scalars (IV, NV or PV) and segfaults on ref's
-    $c->response->body( $c->encoding->encode( $body, $CHECK ) )
-        if ref(\$body) eq 'SCALAR';
-
-    $c->next::method(@_);
-}
-
-# Note we have to hook here as uploads also add to the request parameters
-sub prepare_uploads {
-    my $c = shift;
-
-    $c->next::method(@_);
-
-    my $enc = $c->encoding;
-    return unless $enc;
-
-    for my $key (qw/ parameters query_parameters body_parameters /) {
-        for my $value ( values %{ $c->request->{$key} } ) {
-            # N.B. Check if already a character string and if so do not try to double decode.
-            #      http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg02350.html
-            #      this avoids exception if we have already decoded content, and is _not_ the
-            #      same as not encoding on output which is bad news (as it does the wrong thing
-            #      for latin1 chars for example)..
-            $value = $c->_handle_unicode_decoding($value);
-        }
-    }
-    for my $value ( values %{ $c->request->uploads } ) {
-        # skip if it fails for uploads, as we don't usually want uploads touched
-        # in any way
-        for my $inner_value ( ref($value) eq 'ARRAY' ? @{$value} : $value ) {
-            $inner_value->{filename} = try {
-                $enc->decode( $inner_value->{filename}, $CHECK )
-            } catch {
-                $c->handle_unicode_encoding_exception({
-                    param_value => $inner_value->{filename},
-                    error_msg => $_,
-                    encoding_step => 'uploads',
-                });
-            };
-        }
-    }
-}
-
-sub prepare_action {
-    my $c = shift;
-
-    my $ret = $c->next::method(@_);
-
-    my $enc = $c->encoding;
-    return $ret unless $enc;
-
-    foreach (@{$c->req->arguments}, @{$c->req->captures}) {
-      $_ = $c->_handle_param_unicode_decoding($_);
-    }
-
-    return $ret;
-}
-
-sub setup {
-    my $self = shift;
-
-    my $conf = $self->config;
-
-    # Allow an explicit undef encoding to disable default of utf-8
-    my $enc = delete $conf->{encoding};
-    $self->encoding( $enc );
-
-    return $self->next::method(@_)
-      unless $self->setup_finished; ## hack to stop possibly meaningless test fail... (jnap)
-}
-
-sub _handle_unicode_decoding {
-    my ( $self, $value ) = @_;
-
-    return unless defined $value;
-
-    if ( ref $value eq 'ARRAY' ) {
-        foreach ( @$value ) {
-            $_ = $self->_handle_unicode_decoding($_);
-        }
-        return $value;
-    }
-    elsif ( ref $value eq 'HASH' ) {
-        foreach ( values %$value ) {
-            $_ = $self->_handle_unicode_decoding($_);
-        }
-        return $value;
-    }
-    else {
-        return $self->_handle_param_unicode_decoding($value);
-    }
-}
-
-sub _handle_param_unicode_decoding {
-    my ( $self, $value ) = @_;
-    my $enc = $self->encoding;
-    return try {
-        Encode::is_utf8( $value ) ?
-            $value
-        : $enc->decode( $value, $CHECK );
-    }
-    catch {
-        $self->handle_unicode_encoding_exception({
-            param_value => $value,
-            error_msg => $_,
-            encoding_step => 'params',
-        });
-    };
-}
-
-sub handle_unicode_encoding_exception {
-    my ( $self, $exception_ctx ) = @_;
-    die $exception_ctx->{error_msg};
-}
+our $VERSION = '99.0'; # set high so we always overwrite
 
 1;
 
-__END__
-
 =head1 NAME
 
 Catalyst::Plugin::Unicode::Encoding - Unicode aware Catalyst
 
-=head1 SYNOPSIS
-
-    use Catalyst;
-
-    MyApp->config( encoding => 'UTF-8' ); # A valid Encode encoding
-
-
 =head1 DESCRIPTION
 
-This plugin is automatically loaded by apps. Even though is not a core component
-yet, it will vanish as soon as the code is fully integrated. For more
-information, please refer to L<Catalyst/ENCODING>.
+This plugin has been merged into core.  This package only exists to clean out
+any existing versions on your installed system.
 
 =head1 AUTHORS
 
@@ -183,6 +183,85 @@ for you to determine the content length of your handle object,
 it is recommended that you set the content length in the response headers
 yourself, which will be respected and sent by Catalyst in the response.
 
+Please note that the object needs to implement C<getline>, not just
+C<read>.
+
+Starting from version 5.90060, when using an L<IO::Handle> object, you
+may want to use L<Plack::Middleware::XSendfile>, to delegate the
+actual serving to the frontend server. To do so, you need to pass to
+C<body> an IO object with a C<path> method. This can be achieved in
+two ways.
+
+Either using L<Plack::Util>:
+
+  my $fh = IO::File->new($file, 'r');
+  Plack::Util::set_io_path($fh, $file);
+
+Or using L<IO::File::WithPath>
+
+  my $fh = IO::File::WithPath->new($file, 'r');
+
+And then passing the filehandle to body and setting headers, if needed.
+
+  $c->response->body($fh);
+  $c->response->headers->content_type('text/plain');
+  $c->response->headers->content_length(-s $file);
+  $c->response->headers->last_modified((stat($file))[9]);
+
+L<Plack::Middleware::XSendfile> can be loaded in the application so:
+
+ __PACKAGE__->config(
+     psgi_middleware => [
+         'XSendfile',
+         # other middlewares here...
+        ],
+ );
+
+B<Beware> that loading the middleware without configuring the
+webserver to set the request header C<X-Sendfile-Type> to a supported
+type (C<X-Accel-Redirect> for nginx, C<X-Sendfile> for Apache and
+Lighttpd), could lead to the disclosure of private paths to malicious
+clients setting that header.
+
+Nginx needs the additional X-Accel-Mapping header to be set in the
+webserver configuration, so the middleware will replace the absolute
+path of the IO object with the internal nginx path. This is also
+useful to prevent a buggy app to server random files from the
+filesystem, as it's an internal redirect.
+
+An nginx configuration for FastCGI could look so:
+
+ server {
+     server_name example.com;
+     root /my/app/root;
+     location /private/repo/ {
+         internal;
+         alias /my/app/repo/;
+     }
+     location /private/staging/ {
+         internal;
+         alias /my/app/staging/;
+     }
+     location @proxy {
+         include /etc/nginx/fastcgi_params;
+         fastcgi_param SCRIPT_NAME '';
+         fastcgi_param PATH_INFO   $fastcgi_script_name;
+         fastcgi_param HTTP_X_SENDFILE_TYPE X-Accel-Redirect;
+         fastcgi_param HTTP_X_ACCEL_MAPPING /my/app=/private;
+         fastcgi_pass  unix:/my/app/run/app.sock;
+    }
+ }
+
+In the example above, passing filehandles with a local path matching
+/my/app/staging or /my/app/repo will be served by nginx. Passing paths
+with other locations will lead to an internal server error.
+
+Setting the body to a filehandle without the C<path> method bypasses
+the middleware completely.
+
+For Apache and Lighttpd, the mapping doesn't apply and setting the
+X-Sendfile-Type is enough.
+
 =head2 $res->has_body
 
 Predicate which returns true when a body has been set.
@@ -7,7 +7,7 @@ BEGIN { require 5.008003; }
 
 # Remember to update this in Catalyst as well!
 
-our $VERSION = '5.90061';
+our $VERSION = '5.90071';
 
 =head1 NAME
 
@@ -37,6 +37,7 @@ has port => (
     cmd_aliases   => 'p',
     isa           => 'Int',
     is            => 'ro',
+    lazy          => 1,
     default       => sub {
         Catalyst::Utils::env_value(shift->application_name, 'port') || 3000
     },
@@ -107,6 +108,7 @@ has restart => (
     cmd_aliases   => 'r',
     isa           => 'Bool',
     is            => 'ro',
+    lazy          => 1,
     default       => sub {
         Catalyst::Utils::env_value(shift->application_name, 'reload') || 0;
     },
@@ -393,17 +393,24 @@ sub term_width {
 
     my $width;
     eval '
-        require Term::Size::Any;
-        my ($columns, $rows) = Term::Size::Any::chars;
-        $width = $columns;
-        1;
+      use Term::Size::Any;
+      ($width) = Term::Size::Any::chars;
+      1;
     ' or do {
+          if($@ =~m[Can't locate Term/Size/Any.pm]) {
+            warn "Term::Size::Any is not installed, can't autodetect terminal column width\n";
+          } else {
+            warn "There was an error trying to detect your terminal size: $@\n";
+          }
+        warn 'Trouble trying to detect your terminal size, looking at $ENV{COLUMNS}'."\n";
         $width = $ENV{COLUMNS}
             if exists($ENV{COLUMNS})
             && $ENV{COLUMNS} =~ m/^\d+$/;
     };
 
-    $width = 80 unless ($width && $width >= 80);
+    do {
+      warn "Cannot determine desired terminal width, using default of 80 columns\n";
+      $width = 80 } unless ($width && $width >= 80);
     return $_term_width = $width;
 }
 
@@ -505,7 +512,7 @@ Localize C<$env> under the current controller path prefix:
       my $env = $c->Catalyst::Utils::env_at_path_prefix;
     }
 
-Assuming you have a requst like GET /user/name:
+Assuming you have a request like GET /user/name:
 
 In the example case C<$env> will have PATH_INFO of '/name' instead of
 '/user/name' and SCRIPT_NAME will now be '/user'.
@@ -530,7 +537,7 @@ sub env_at_path_prefix {
 
 =head2 env_at_action
 
-Localize C<$env> under the current controller path prefix:
+Localize C<$env> under the current action namespace.
 
     package MyApp::Controller::User;
 
@@ -543,11 +550,16 @@ Localize C<$env> under the current controller path prefix:
       my $env = $c->Catalyst::Utils::env_at_action;
     }
 
-Assuming you have a requst like GET /user/name:
+Assuming you have a request like GET /user/name:
 
 In the example case C<$env> will have PATH_INFO of '/' instead of
 '/user/name' and SCRIPT_NAME will now be '/user/name'.
 
+Alternatively, assuming you have a request like GET /user/name/foo:
+
+In this example case C<$env> will have PATH_INFO of '/foo' instead of
+'/user/name/foo' and SCRIPT_NAME will now be '/user/name'.
+
 This is probably a common case where you want to mount a PSGI application
 under an action but let the Args fall through to the PSGI app.
 
@@ -575,7 +587,7 @@ sub env_at_action {
 
 =head2 env_at_request_uri
 
-Localize C<$env> under the current controller path prefix:
+Localize C<$env> under the current request URI:
 
     package MyApp::Controller::User;
 
@@ -588,7 +600,7 @@ Localize C<$env> under the current controller path prefix:
       my $env = $c->Catalyst::Utils::env_at_request_uri
     }
 
-Assuming you have a requst like GET /user/name/hello:
+Assuming you have a request like GET /user/name/hello:
 
 In the example case C<$env> will have PATH_INFO of '/' instead of
 '/user/name' and SCRIPT_NAME will now be '/user/name/hello'.
@@ -47,13 +47,14 @@ 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 ();
 
 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');
@@ -117,16 +118,16 @@ __PACKAGE__->mk_classdata($_)
   for qw/components arguments dispatcher engine log dispatcher_class
   engine_loader context_class request_class response_class stats_class
   setup_finished _psgi_app loading_psgi_file run_options _psgi_middleware
-  _data_handlers/;
+  _data_handlers _encoding _encode_check/;
 
 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
 __PACKAGE__->request_class('Catalyst::Request');
 __PACKAGE__->response_class('Catalyst::Response');
 __PACKAGE__->stats_class('Catalyst::Stats');
+__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
 
 # Remember to update this in Catalyst::Runtime as well!
-
-our $VERSION = '5.90061';
+our $VERSION = '5.90071';
 
 sub import {
     my ( $class, @arguments ) = @_;
@@ -496,21 +497,10 @@ Catalyst).
 
 =cut
 
-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};
-        }
-    }
-
-    return $stash;
-};
-
+sub stash {
+  my $c = shift;
+  return Catalyst::Middleware::Stash::get_stash($c->req->env)->(@_);
+}
 
 =head2 $c->error
 
@@ -564,6 +554,14 @@ 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 }
+
 sub _comp_search_prefixes {
     my $c = shift;
     return map $c->components->{ $_ }, $c->_comp_names_search_prefixes(@_);
@@ -1000,6 +998,38 @@ And later:
 Your log class should implement the methods described in
 L<Catalyst::Log>.
 
+=head2 encoding
+
+Sets or gets the application encoding.
+
+=cut
+
+sub encoding {
+    my $c = shift;
+    my $encoding;
+
+    if ( scalar @_ ) {
+        # 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
 
@@ -1173,6 +1203,11 @@ EOF
         $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
@@ -1252,9 +1287,10 @@ EOF
     }
 
     $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 $class || 1; # Just in case someone named their Application 0...
 }
 
@@ -1738,6 +1774,16 @@ sub execute {
     my $last = pop( @{ $c->stack } );
 
     if ( my $error = $@ ) {
+        #rethow if this can be handled by middleware
+        if(blessed $error && ($error->can('as_psgi') || $error->can('code'))) {
+            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;
         }
@@ -1862,8 +1908,8 @@ sub finalize {
             $c->finalize_error;
         }
 
+        $c->finalize_encoding;
         $c->finalize_headers unless $c->response->finalized_headers;
-
         $c->finalize_body;
     }
 
@@ -1917,7 +1963,6 @@ sub finalize_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;
-            croak $error;
         } else {
             $c->engine->finalize_error( $c, @_ )
         }
@@ -1955,6 +2000,46 @@ sub finalize_headers {
     $response->finalized_headers(1);
 }
 
+=head2 $c->finalize_encoding
+
+Make sure your headers and body are encoded properly IF you set an encoding.
+See L</ENCODING>.
+
+=cut
+
+sub finalize_encoding {
+    my $c = shift;
+
+    my $body = $c->response->body;
+
+    return unless defined($body);
+
+    my $enc = $c->encoding;
+
+    return unless $enc;
+
+    my ($ct, $ct_enc) = $c->response->content_type;
+
+    # Only touch 'text-like' contents
+    return unless $c->response->content_type =~ /^text|xml$|javascript$/;
+
+    if ($ct_enc && $ct_enc =~ /charset=([^;]*)/) {
+        if (uc($1) ne uc($enc->mime_name)) {
+            $c->log->debug("Unicode::Encoding is set to encode in '" .
+                           $enc->mime_name .
+                           "', content type is '$1', not encoding ");
+            return;
+        }
+    } else {
+        $c->res->content_type($c->res->content_type . "; charset=" . $enc->mime_name);
+    }
+
+    # Oh my, I wonder what filehandle responses and streams do... - jnap.
+    # Encode expects plain scalars (IV, NV or PV) and segfaults on ref's
+    $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) )
+        if ref(\$body) eq 'SCALAR';
+}
+
 =head2 $c->finalize_output
 
 An alias for finalize_body.
@@ -2015,12 +2100,12 @@ sub handle_request {
         $c->dispatch;
         $status = $c->finalize;
     } catch {
-        chomp(my $error = $_);
-        $class->log->error(qq/Caught exception in engine "$error"/);
         #rethow if this can be handled by middleware
-        if(blessed $error && ($error->can('as_psgi') || $error->can('code'))) {
-            $error->can('rethrow') ? $error->rethrow : croak $error;
+        if(blessed $_ && ($_->can('as_psgi') || $_->can('code'))) {
+            $_->can('rethrow') ? $_->rethrow : croak $_;
         }
+        chomp(my $error = $_);
+        $class->log->error(qq/Caught exception in engine "$error"/);
     };
 
     $COUNT++;
@@ -2114,7 +2199,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
 
@@ -2165,9 +2262,7 @@ Prepares connection.
 
 sub prepare_connection {
     my $c = shift;
-    # XXX - This is called on the engine (not the request) to maintain
-    #       Engine::PSGI back compat.
-    $c->engine->prepare_connection($c);
+    $c->request->prepare_connection($c);
 }
 
 =head2 $c->prepare_cookies
@@ -2434,8 +2529,38 @@ Prepares uploads.
 
 sub prepare_uploads {
     my $c = shift;
-
     $c->engine->prepare_uploads( $c, @_ );
+
+    my $enc = $c->encoding;
+    return unless $enc;
+
+    # Uggg we hook prepare uploads to do the encoding crap on post and query
+    # parameters!  Sorry -jnap
+    for my $key (qw/ parameters query_parameters body_parameters /) {
+        for my $value ( values %{ $c->request->{$key} } ) {
+            # N.B. Check if already a character string and if so do not try to double decode.
+            #      http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg02350.html
+            #      this avoids exception if we have already decoded content, and is _not_ the
+            #      same as not encoding on output which is bad news (as it does the wrong thing
+            #      for latin1 chars for example)..
+            $value = $c->_handle_unicode_decoding($value);
+        }
+    }
+    for my $value ( values %{ $c->request->uploads } ) {
+        # skip if it fails for uploads, as we don't usually want uploads touched
+        # in any way
+        for my $inner_value ( ref($value) eq 'ARRAY' ? @{$value} : $value ) {
+            $inner_value->{filename} = try {
+                $enc->decode( $inner_value->{filename}, $c->_encode_check )
+            } catch {
+                $c->handle_unicode_encoding_exception({
+                    param_value => $inner_value->{filename},
+                    error_msg => $_,
+                    encoding_step => 'uploads',
+                });
+            };
+        }
+    }
 }
 
 =head2 $c->prepare_write
@@ -2589,18 +2714,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;
 }
@@ -2910,6 +3032,79 @@ sub setup_home {
     }
 }
 
+=head2 $c->setup_encoding
+
+Sets up the input/output encoding.  See L<ENCODING>
+
+=cut
+
+sub setup_encoding {
+    my $c = shift;
+    my $enc = delete $c->config->{encoding};
+    $c->encoding( $enc ) if defined $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;
+
+    if ( ref $value eq 'ARRAY' ) {
+        foreach ( @$value ) {
+            $_ = $self->_handle_unicode_decoding($_);
+        }
+        return $value;
+    }
+    elsif ( ref $value eq 'HASH' ) {
+        foreach ( values %$value ) {
+            $_ = $self->_handle_unicode_decoding($_);
+        }
+        return $value;
+    }
+    else {
+        return $self->_handle_param_unicode_decoding($value);
+    }
+}
+
+sub _handle_param_unicode_decoding {
+    my ( $self, $value ) = @_;
+    my $enc = $self->encoding;
+    return try {
+        Encode::is_utf8( $value ) ?
+            $value
+        : $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
@@ -3020,7 +3215,7 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
         return $class;
     }
 
-    sub _default_plugins { return qw(Unicode::Encoding) }
+    sub _default_plugins { return qw() }
 
     sub setup_plugins {
         my ( $class, $plugins ) = @_;
@@ -3103,12 +3298,17 @@ 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) {
         return (
+          Catalyst::Middleware::Stash->new,
           Plack::Middleware::HTTPExceptions->new,
           Plack::Middleware::RemoveRedundantBody->new,
           Plack::Middleware::FixMissingBodyInRedirect->new,
@@ -3124,7 +3324,7 @@ sub registered_middlewares {
 sub setup_middleware {
     my $class = shift;
     my @middleware_definitions = @_ ? 
-      @_ : reverse(@{$class->config->{'psgi_middleware'}||[]});
+      reverse(@_) : reverse(@{$class->config->{'psgi_middleware'}||[]});
 
     my @middleware = ();
     while(my $next = shift(@middleware_definitions)) {
@@ -3190,7 +3390,8 @@ sub registered_data_handlers {
     if(my $data_handlers = $class->_data_handlers) {
         return %$data_handlers;
     } else {
-        die "You cannot call ->registered_data_handlers until data_handers has been setup";
+        $class->setup_data_handlers;
+        return $class->registered_data_handlers;
     }
 }
 
@@ -3579,7 +3780,7 @@ example given above, which uses L<JSON::Maybe> to provide either L<JSON::PP>
 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> configuation is a hashref whose keys are HTTP Content-Types
+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.
@@ -3944,6 +4145,8 @@ 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>
@@ -21,28 +21,26 @@ use Catalyst::Request;
 use HTTP::Headers;
 use HTTP::Request::Common;
 
-foreach my $path (qw/ env env_on_engine /) {
-    my $response = request("http://localhost/dump/${path}", {
-        extra_env => { $EXPECTED_ENV_VAR => $EXPECTED_ENV_VAL },
-    });
-
-    ok( $response, 'Request' );
-    ok( $response->is_success, 'Response Successful 2xx' );
-    is( $response->content_type, 'text/plain', 'Response Content-Type' );
-
-    my $env;
-    ok( eval '$env = ' . $response->content, 'Unserialize Catalyst::Request' );
-    is ref($env), 'HASH';
-    ok exists($env->{PATH_INFO}), 'Have a PATH_INFO env var for ' . $path;
-
-    SKIP:
-    {
-        if ( $ENV{CATALYST_SERVER} ) {
-            skip 'Using remote server', 1;
-        }
-        is $env->{$EXPECTED_ENV_VAR}, $EXPECTED_ENV_VAL,
-            'Value we set as expected for ' . $path;
+my $response = request("http://localhost/dump/env", {
+    extra_env => { $EXPECTED_ENV_VAR => $EXPECTED_ENV_VAL },
+});
+
+ok( $response, 'Request' );
+ok( $response->is_success, 'Response Successful 2xx' );
+is( $response->content_type, 'text/plain', 'Response Content-Type' );
+
+my $env;
+ok( eval '$env = ' . $response->content, 'Unserialize Catalyst::Request' );
+is ref($env), 'HASH';
+ok exists($env->{PATH_INFO}), 'Have a PATH_INFO env var for dump/env';
+
+SKIP:
+{
+    if ( $ENV{CATALYST_SERVER} ) {
+        skip 'Using remote server', 1;
     }
+    is $env->{$EXPECTED_ENV_VAR}, $EXPECTED_ENV_VAL,
+        'Value we set as expected for /dump/env'
 }
 
 done_testing;
@@ -37,20 +37,11 @@ foreach my $method (qw(HEAD GET)) {
             'HEAD method content is empty' );
     }
     elsif ( $method eq 'GET' ) {
-        # method name is echo'd back in content-body, which
-        # accounts for difference in content length.  In normal
-        # cases the Content-Length should be the same regardless
-        # of whether it's a GET or HEAD request.
-        SKIP:
-        {
-            if ( $ENV{CATALYST_SERVER} ) {
-                skip "Using remote server", 2;
-            }
-            is( $response->header('Content-Length'),
-                $content_length - 1, 'Response Header Content-Length' );
-            is( length($response->content),
-                $response->header('Content-Length'),
-                'GET method content' );
-        }
+        is( $response->header('Content-Length'),
+            $content_length, 'Response Header Content-Length' )
+            or diag $response->content;
+        is( length($response->content),
+            $response->header('Content-Length'),
+            'GET method content' );
     }
 }
@@ -13,7 +13,6 @@ my @expected = qw[
   Catalyst::Plugin::Test::Inline
   Catalyst::Plugin::Test::MangleDollarUnderScore
   Catalyst::Plugin::Test::Plugin
-  Catalyst::Plugin::Unicode::Encoding
   TestApp::Plugin::AddDispatchTypes
   TestApp::Plugin::FullyQualified
 ];
@@ -20,7 +20,10 @@ my $model_foo_bar = $model_foo->bar;
 can_ok($model_foo_bar, 'model_foo_bar_method_from_foo');
 can_ok($model_foo_bar, 'model_foo_bar_method_from_foo_bar');
 
-TestApp->setup;
+# I commented out this line since we seem to just massively
+# fail on the 'you already did setup.  I have no idea why its
+# here - jnap
+#TestApp->setup;
 
 is($model_foo->model_quux_method, 'chunkybacon', 'Model method getting $self->{quux} from config');
 
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 22;
+use Test::More tests => 24;
 
 use Catalyst::Log;
 
@@ -21,6 +21,9 @@ can_ok $LOG, 'new';
 ok my $log = $LOG->new, '... and creating a new log object should succeed';
 isa_ok $log, $LOG, '... and the object it returns';
 
+can_ok $log, "autoflush";
+$log->autoflush(0);
+
 can_ok $log, 'is_info';
 ok $log->is_info, '... and the default behavior is to allow info messages';
 
@@ -50,10 +53,13 @@ like $MESSAGES[0], qr/^\[info\] hello there!$/,
 my $SUBCLASS = 'Catalyst::Log::Subclass';
 can_ok $SUBCLASS, 'new';
 ok $log = Catalyst::Log::Subclass->new,
-    '... and the log subclass constructor shoudl return a new object';
+    '... and the log subclass constructor should return a new object';
 isa_ok $log, $SUBCLASS, '... and the object it returns';
 isa_ok $log, $LOG,      '... and it also';
 
+can_ok $log, "autoflush";
+$log->autoflush(0);
+
 can_ok $log, 'info';
 ok $log->info('hi there!'),
     '... passing it an info message should succeed';
@@ -0,0 +1,66 @@
+use strict;
+use warnings;
+
+use Test::More tests => 20;
+
+use Catalyst::Log;
+
+local *Catalyst::Log::_send_to_log;
+local our @MESSAGES;
+{
+    no warnings 'redefine';
+    *Catalyst::Log::_send_to_log = sub {
+        my $self = shift;
+        push @MESSAGES, @_;
+    };
+}
+
+my $LOG = 'Catalyst::Log';
+
+can_ok $LOG, 'new';
+ok my $log = $LOG->new, '... and creating a new log object should succeed';
+isa_ok $log, $LOG, '... and the object it returns';
+
+can_ok $log, 'is_info';
+ok $log->is_info, '... and the default behavior is to allow info messages';
+
+can_ok $log, 'info';
+ok $log->info('hello there!'),
+    '... passing it an info message should succeed';
+
+ok @MESSAGES, '... and immediately flush the log';
+is scalar @MESSAGES, 1, '... with one log message';
+like $MESSAGES[0], qr/^\[info\] hello there!$/,
+    '... which should match the format we expect';
+
+{
+
+    package Catalyst::Log::Subclass;
+    use base qw/Catalyst::Log/;
+
+    sub _send_to_log {
+        my $self = shift;
+        push @MESSAGES, '---';
+        push @MESSAGES, @_;
+    }
+}
+
+@MESSAGES = (); # clear the message log
+
+my $SUBCLASS = 'Catalyst::Log::Subclass';
+can_ok $SUBCLASS, 'new';
+ok $log = Catalyst::Log::Subclass->new,
+    '... and the log subclass constructor should return a new object';
+isa_ok $log, $SUBCLASS, '... and the object it returns';
+isa_ok $log, $LOG,      '... and it also';
+
+can_ok $log, 'info';
+ok $log->info('hi there!'),
+    '... passing it an info message should succeed';
+
+ok @MESSAGES, '... and immediately flush the log';
+is scalar @MESSAGES, 2, '... with two log messages';
+is $MESSAGES[0], '---', '... with the first one being our new data';
+like $MESSAGES[1], qr/^\[info\] hi there!$/,
+    '... which should match the format we expect';
+
@@ -75,13 +75,13 @@ is_deeply( [ sort MyMVCTestApp->models ],
     ok( $warnings, 'view() w/o a default is random, warnings thrown' );
 }
 
-is ( bless ({stash=>{current_view=>'V'}}, 'MyMVCTestApp')->view , 'MyMVCTestApp::View::V', 'current_view ok');
+#is ( bless ({stash=>{current_view=>'V'}}, 'MyMVCTestApp')->view , 'MyMVCTestApp::View::V', 'current_view ok');
 
 my $view = bless {} , 'MyMVCTestApp::View::V';
-is ( bless ({stash=>{current_view_instance=> $view }}, 'MyMVCTestApp')->view , $view, 'current_view_instance ok');
+#is ( bless ({stash=>{current_view_instance=> $view }}, 'MyMVCTestApp')->view , $view, 'current_view_instance ok');
 
-is ( bless ({stash=>{current_view_instance=> $view, current_view=>'MyMVCTestApp::V::View' }}, 'MyMVCTestApp')->view , $view,
-  'current_view_instance precedes current_view ok');
+#is ( bless ({stash=>{current_view_instance=> $view, current_view=>'MyMVCTestApp::V::View' }}, 'MyMVCTestApp')->view , $view,
+#  'current_view_instance precedes current_view ok');
 
 {
     my $warnings = 0;
@@ -97,20 +97,20 @@ is ( bless ({stash=>{current_view_instance=> $view, current_view=>'MyMVCTestApp:
     ok( $warnings, 'model() w/o a default is random, warnings thrown' );
 }
 
-is ( bless ({stash=>{current_model=>'M'}}, 'MyMVCTestApp')->model , 'MyMVCTestApp::Model::M', 'current_model ok');
+#is ( bless ({stash=>{current_model=>'M'}}, 'MyMVCTestApp')->model , 'MyMVCTestApp::Model::M', 'current_model ok');
 
 my $model = bless {} , 'MyMVCTestApp::Model::M';
-is ( bless ({stash=>{current_model_instance=> $model }}, 'MyMVCTestApp')->model , $model, 'current_model_instance ok');
+#is ( bless ({stash=>{current_model_instance=> $model }}, 'MyMVCTestApp')->model , $model, 'current_model_instance ok');
 
-is ( bless ({stash=>{current_model_instance=> $model, current_model=>'MyMVCTestApp::M::Model' }}, 'MyMVCTestApp')->model , $model,
-  'current_model_instance precedes current_model ok');
+#is ( bless ({stash=>{current_model_instance=> $model, current_model=>'MyMVCTestApp::M::Model' }}, 'MyMVCTestApp')->model , $model,
+#  'current_model_instance precedes current_model ok');
 
 MyMVCTestApp->config->{default_view} = 'V';
-is ( bless ({stash=>{}}, 'MyMVCTestApp')->view , 'MyMVCTestApp::View::V', 'default_view ok');
+#is ( bless ({stash=>{}}, 'MyMVCTestApp')->view , 'MyMVCTestApp::View::V', 'default_view ok');
 is ( MyMVCTestApp->view , 'MyMVCTestApp::View::V', 'default_view in class method ok');
 
 MyMVCTestApp->config->{default_model} = 'M';
-is ( bless ({stash=>{}}, 'MyMVCTestApp')->model , 'MyMVCTestApp::Model::M', 'default_model ok');
+#is ( bless ({stash=>{}}, 'MyMVCTestApp')->model , 'MyMVCTestApp::Model::M', 'default_model ok');
 is ( MyMVCTestApp->model , 'MyMVCTestApp::Model::M', 'default_model in class method ok');
 
 # regexp behavior tests
@@ -51,7 +51,6 @@ my @expected = qw(
   Catalyst::Plugin::Test::Inline
   Catalyst::Plugin::Test::MangleDollarUnderScore
   Catalyst::Plugin::Test::Plugin
-  Catalyst::Plugin::Unicode::Encoding
   TestApp::Plugin::AddDispatchTypes
   TestApp::Plugin::FullyQualified
 );
@@ -151,7 +151,7 @@ sub testBackgroundOptionWithFork {
 
     ## Check a few args
     is_deeply $app->{ARGV}, $argstring;
-    is $app->{port}, '3000';
+    is $app->port, '3000';
     is($app->{background}, 1);
 }
 
@@ -20,8 +20,9 @@ add_stopwords(qw(
     FastCGI Stringifies Rethrows DispatchType Wishlist Refactor ROADMAP HTTPS Unescapes Restarter Nginx Refactored
     ActionClass LocalRegex LocalRegexp MyAction metadata cometd io psgix websockets
     UTF async codebase dev filenames params MyMiddleware
-    JSON POSTed RESTful configuation performant subref actionrole
+    JSON POSTed RESTful performant subref actionrole
     chunked chunking codewise distingush equivilent plack Javascript
+    ConfigLoader getline
     Andreas
     Ashton
     Axel
@@ -76,9 +77,11 @@ add_stopwords(qw(
     Sedlacek
     Sheidlower
     SpiceMan
+    Styn
     Szilakszi
     Tatsuhiko
     Ulf
+    Upasana
     Vilain
     Viljo
     Wardley
@@ -120,6 +123,7 @@ add_stopwords(qw(
     rainboxx
     sri
     szbalint
+    vanstyn
     willert
     wreis
 ));
@@ -0,0 +1,49 @@
+use warnings;
+use strict;
+use Test::More;
+use HTTP::Request::Common;
+use Plack::Test;
+
+# Test to make sure we the order of some middleware is correct.  Basically
+# we want to make sure that if the request is a HEAD we properly remove the
+# body BUT not so quickly that we fail to calculate the length.  This test
+# exists mainly to prevent regressions.
+
+{
+  package MyApp::Controller::Root;
+  $INC{'MyApp/Controller/Root.pm'} = __FILE__;
+
+  use base 'Catalyst::Controller';
+
+  sub test :Local {
+    my ($self, $c) = @_;
+    $c->response->body("This is the body");
+  }
+
+  package MyApp;
+  use Catalyst;
+
+  Test::More::ok(MyApp->setup, 'setup app');
+}
+
+
+
+ok my $psgi = MyApp->psgi_app, 'build psgi app';
+
+test_psgi $psgi, sub {
+    my $cb = shift;
+    my $res = $cb->(GET "/root/test");
+    is $res->code, 200, 'OK';
+    is $res->content, 'This is the body', 'correct body';
+    is $res->content_length, 16, 'correct length';
+};
+
+test_psgi $psgi, sub {
+    my $cb = shift;
+    my $res = $cb->(HEAD "/root/test");
+    is $res->code, 200, 'OK';
+    is $res->content, '', 'correct body';
+    is $res->content_length, 16, 'correct length';    
+};
+
+done_testing;
@@ -12,6 +12,10 @@ use Plack::Test;
 {
   package MyApp::Exception;
 
+  use overload
+    # Use the overloading thet HTTP::Exception uses
+    bool => sub { 1 }, '""' => 'as_string', fallback => 1;
+
   sub new {
     my ($class, $code, $headers, $body) = @_;
     return bless +{res => [$code, $headers, $body]}, $class;
@@ -30,6 +34,8 @@ use Plack::Test;
       $responder->([$code, $headers, $body]);
     };
   }
+
+  sub as_string { 'bad stringy bad' }
   
   package MyApp::Controller::Root;
 
@@ -64,15 +70,19 @@ use Plack::Test;
     die "I'm not dead yet";
   }
 
+  sub end :Private { die "We should never hit end for HTTPExceptions" }
+
   package MyApp;
   use Catalyst;
 
+  MyApp->config(abort_chain_on_error_fix=>1);
+
   sub debug { 1 }
 
   MyApp->setup_log('fatal');
 }
 
-$INC{'MyApp/Controller/Root.pm'} = '1'; # sorry...
+$INC{'MyApp/Controller/Root.pm'} = __FILE__; # sorry...
 MyApp->setup_log('error');
 
 Test::More::ok(MyApp->setup);
@@ -84,6 +94,7 @@ test_psgi $psgi, sub {
     my $res = $cb->(GET "/root/from_psgi_app");
     is $res->code, 404;
     is $res->content, 'Not Found', 'NOT FOUND';
+    unlike $res->content, qr'HTTPExceptions', 'HTTPExceptions';
 };
 
 test_psgi $psgi, sub {
@@ -91,6 +102,7 @@ test_psgi $psgi, sub {
     my $res = $cb->(GET "/root/from_catalyst");
     is $res->code, 403;
     is $res->content, 'Forbidden', 'Forbidden';
+    unlike $res->content, qr'HTTPExceptions', 'HTTPExceptions';
 };
 
 test_psgi $psgi, sub {
@@ -98,6 +110,7 @@ test_psgi $psgi, sub {
     my $res = $cb->(GET "/root/classic_error");
     is $res->code, 500;
     like $res->content, qr'Ex Parrot', 'Ex Parrot';
+    like $res->content, qr'HTTPExceptions', 'HTTPExceptions';
 };
 
 test_psgi $psgi, sub {
@@ -105,6 +118,7 @@ test_psgi $psgi, sub {
     my $res = $cb->(GET "/root/just_die");
     is $res->code, 500;
     like $res->content, qr'not dead yet', 'not dead yet';
+    like $res->content, qr'HTTPExceptions', 'HTTPExceptions';
 };
 
 
@@ -113,5 +127,5 @@ test_psgi $psgi, sub {
 # in the callbacks might never get run (thus all ran tests pass but not all
 # required tests run).
 
-done_testing(10);
+done_testing(14);
 
@@ -49,7 +49,6 @@ sub run_time_plugins : Local {
     is_deeply [ $c->registered_plugins ],
     [
         qw/Catalyst::Plugin::Test::Plugin
-        Catalyst::Plugin::Unicode::Encoding
         Faux::Plugin
         TestApp::Plugin::FullyQualified/
         ],
@@ -14,7 +14,6 @@ sub _test_plugins {
     is_deeply [ $c->registered_plugins ],
     [
         qw/Catalyst::Plugin::Test::Plugin
-        Catalyst::Plugin::Unicode::Encoding
         TestApp::Plugin::FullyQualified/
     ],
     '... and it should report the correct plugins';
@@ -24,6 +24,11 @@ sub context_closure : Local {
     $ctx->response->body('stashed context closure');
 }
 
+sub non_closure : Local {
+    my ($self, $ctx) = @_;
+    $ctx->stash(no_closure => "not a closure");
+}
+
 __PACKAGE__->meta->make_immutable;
 
 1;
@@ -14,12 +14,6 @@ sub env : Action Relative {
     $c->forward('TestApp::View::Dump::Env');
 }
 
-sub env_on_engine : Action Relative {
-    my ( $self, $c ) = @_;
-    $c->stash(env => $c->engine->env);
-    $c->forward('TestApp::View::Dump::Env');
-}
-
 sub request : Action Relative {
     my ( $self, $c ) = @_;
     $c->req->params(undef); # Should be a no-op, and be ignored.
@@ -8,7 +8,7 @@ sub one : Relative {
     $c->res->header( 'X-Header-Catalyst' => 'Cool' );
     $c->res->header( 'X-Header-Cool'     => 'Catalyst' );
     $c->res->header( 'X-Header-Numbers'  => join ', ', 1 .. 10 );
-    $c->forward('TestApp::View::Dump::Request');
+    $c->forward('TestApp::View::Dump', [ { some => [qw(fixed content)] } ]);
 }
 
 1;
@@ -9,6 +9,11 @@ sub debug :Local  {
     $c->res->body( 'logged' );
 }
 
+sub info :Local  {
+    my ( $self, $c ) = @_;
+    $c->log->info('info');
+    $c->res->body( 'logged' );
+}
 
 1;
 
@@ -9,6 +9,7 @@ sub process {
     return $self->SUPER::process($c, {
         map { ($_ => $env->{$_}) }
         grep { $_ ne 'psgi.input' }
+        grep { $_ !~/^Catalyst/ }
         keys %{ $env },
     });
 }
@@ -3,6 +3,7 @@ use strict;
 use warnings;
 
 our @LOGS;
+our @ILOGS;
 our @ELOGS;
 
 sub new {
@@ -14,10 +15,16 @@ sub debug {
     push(@LOGS, shift());
 }
 
+sub info {
+    shift;
+    push(@ILOGS, shift());
+}
+
 sub warn {
     shift;
     push(@ELOGS, shift());
 }
 
+sub error { die "Got unexpected error; $_[1]" }
 1;
 
@@ -7,7 +7,7 @@ BEGIN {
         plan skip_all => 'CatalystX::LeakChecker 0.05 required for this test';
     }
 
-    plan tests => 4;
+    plan tests => 6;
 }
 
 use FindBin;
@@ -20,7 +20,9 @@ use Catalyst::Test 'TestApp';
 {
     my ($resp, $ctx) = ctx_request('/contextclosure/normal_closure');
     ok($resp->is_success);
-    is($ctx->count_leaks, 1);
+    #is($ctx->count_leaks, 1);
+    # FIXME: find out why this changed from 1 to 2 after 52af51596d
+    is($ctx->count_leaks, 2);
 }
 
 {
@@ -28,3 +30,9 @@ use Catalyst::Test 'TestApp';
     ok($resp->is_success);
     is($ctx->count_leaks, 0);
 }
+
+{
+    my ($resp, $ctx) = ctx_request('/contextclosure/non_closure');
+    ok($resp->is_success);
+    is($ctx->count_leaks, 0);
+}
@@ -46,6 +46,8 @@ use HTTP::Request::Common;
     no Moose;
 }
 
+my $cmp = TestApp->debug ? '>=' : '==';
+
 #subtest "psgi.errors" => sub
 {
 
@@ -67,10 +69,10 @@ use HTTP::Request::Common;
 
     test_psgi $app, sub {
         my $cb = shift;
-        my $res = $cb->(GET "/log/debug");
+        my $res = $cb->(GET "/log/info");
         my @logs = $handle->logs;
-        is(scalar(@logs), 1, "psgi.errors: one event output");
-        like($logs[0], qr/debug$/, "psgi.errors: event matches test data");
+        cmp_ok(scalar(@logs), $cmp, 1, "psgi.errors: one event output");
+        like($logs[0], qr/info$/m, "psgi.errors: event matches test data");
     };
 };
 
@@ -95,9 +97,10 @@ use HTTP::Request::Common;
 
     test_psgi $app, sub {
         my $cb = shift;
-        my $res = $cb->(GET "/log/debug");
-        is(scalar(@logs), 1, "psgix.logger: one event logged");
-        is_deeply($logs[0], { level => 'debug', message => "debug" }, "psgix.logger: right stuff");
+        my $res = $cb->(GET "/log/info");
+        cmp_ok(scalar(@logs), $cmp, 1, "psgix.logger: one event logged");
+        is(scalar(grep { $_->{level} eq 'info' and $_->{message} eq 'info' } @logs),
+           1, "psgix.logger: right stuff");
     };
 };
 
@@ -1,41 +0,0 @@
-use strict;
-use warnings;
-use FindBin qw/$Bin/;
-use lib "$Bin/lib";
-
-use Test::More;
-use Test::Fatal;
-use Plack::Test;
-use TestApp;
-use HTTP::Request::Common;
-
-plan skip_all => "Catalyst::Engine::PSGI required for this test"
-    unless eval { local $SIG{__WARN__} = sub{}; require Catalyst::Engine::PSGI; 1; };
-
-my $warning;
-local $SIG{__WARN__} = sub { $warning = $_[0] };
-
-TestApp->setup_engine('PSGI');
-my $app = sub { TestApp->run(@_) };
-
-like $warning, qr/You are running Catalyst\:\:Engine\:\:PSGI/,
-  'got deprecation alert warning';
-
-test_psgi $app, sub {
-    my $cb = shift;
-    is exception {
-        my $TIMEOUT_IN_SECONDS = 5;
-        local $SIG{ALRM} = sub { die "alarm\n" };
-        alarm($TIMEOUT_IN_SECONDS);
-
-        my $res = $cb->(GET "/");
-        is $res->content, "root index", 'got expected content';
-        like $warning, qr/env as a writer/, 'got deprecation alert warning';
-
-        alarm(0);
-        1
-    }, undef, q{app didn't die or timeout};
-};
-
-done_testing;
-
@@ -1,40 +0,0 @@
-use strict;
-use warnings;
-no warnings 'once';
-use FindBin qw/$Bin/;
-use lib "$Bin/lib";
-
-use Test::More;
-
-use File::Spec;
-use File::Temp qw/ tempdir /;
-
-my $temp;
-BEGIN {
-    $temp = tempdir( CLEANUP => 1 );
-
-    $ENV{CATALYST_HOME} = $temp;
-    open(my $psgi, '>', File::Spec->catfile($temp, 'testapp.psgi')) or die;
-    print $psgi q{
-        use strict;
-        use TestApp;
-
-        $main::have_loaded_psgi = 1;
-        TestApp->setup_engine('PSGI');
-        my $app = sub { TestApp->run(@_) };
-    };
-    close($psgi);
-}
-use Catalyst::Test qw/ TestApp /;
-
-ok !$main::have_loaded_psgi, 'legacy psgi file got ignored';
-
-like do {
-    my $warning;
-    local $SIG{__WARN__} = sub { $warning = $_[0] };
-    ok request('/');
-    $warning;
-}, qr/ignored/, 'legacy psgi files raise a warning';
-
-done_testing;
-
@@ -3,17 +3,40 @@ use strict;
 
 # Make it easier to mount PSGI apps under catalyst
 
+my $psgi_app = sub {
+  my $req = Plack::Request->new(shift);
+  return [200,[],[$req->path]];
+};
+
 {
-  package MyApp::Controller::User;
+  package MyApp::Controller::Docs;
+  $INC{'MyApp/Controller/Docs.pm'} = __FILE__;
 
   use base 'Catalyst::Controller';
   use Plack::Request;
   use Catalyst::Utils;
 
-  my $psgi_app = sub {
-    my $req = Plack::Request->new(shift);
-    return [200,[],[$req->path]];
-  };
+  sub name :Local {
+    my ($self, $c) = @_;
+    my $env = $c->Catalyst::Utils::env_at_action;
+    $c->res->from_psgi_response(
+      $psgi_app->($env));
+
+  }
+
+  sub name_args :Local Args(1) {
+    my ($self, $c, $arg) = @_;
+    my $env = $c->Catalyst::Utils::env_at_action;
+    $c->res->from_psgi_response(
+      $psgi_app->($env));
+  }
+
+  package MyApp::Controller::User;
+  $INC{'MyApp/Controller/User.pm'} = __FILE__;
+
+  use base 'Catalyst::Controller';
+  use Plack::Request;
+  use Catalyst::Utils;
 
   sub local_example :Local {
     my ($self, $c) = @_;
@@ -54,6 +77,27 @@ use strict;
         $c->res->from_psgi_response(
           $psgi_app->($env));
       }
+
+  sub mounted :Local Args(1) {
+    my ($self, $c, $arg) = @_;
+    our $app ||= ref($c)->psgi_app;
+    my $env = $self->get_env($c);
+    $c->res->from_psgi_response(
+      $app->($env));
+  }
+
+  sub mount_arg :Path(/mounted) Arg(1) {
+    my ($self, $c, $arg) = @_;
+    my $uri =  $c->uri_for( $self->action_for('local_example_args1'),$arg);
+    $c->res->body("$uri");
+  }
+
+  sub mount_noarg :Path(/mounted_no_arg)  {
+    my ($self, $c) = @_;
+    my $uri =  $c->uri_for( $self->action_for('local_example_args1'),444);
+    $c->res->body("$uri");
+  }
+
   
   sub get_env {
     my ($self, $c) = @_;
@@ -68,8 +112,6 @@ use strict;
     }
   }
 
-  $INC{'MyApp/Controller/User.pm'} = __FILE__;
-
   package MyApp;
   use Catalyst;
   MyApp->setup;
@@ -79,6 +121,20 @@ use strict;
 use Test::More;
 use Catalyst::Test 'MyApp';
 
+{
+  my ($res, $c) = ctx_request('/user/mounted/111?path_prefix=1');
+  is $c->action, 'user/mounted';
+  is $res->content, 'http://localhost/user/user/local_example_args1/111';
+  is_deeply $c->req->args, [111];
+}
+
+{
+  my ($res, $c) = ctx_request('/user/mounted/mounted_no_arg?env_path=1');
+  is $c->action, 'user/mounted';
+  is $res->content, 'http://localhost/user/mounted/user/local_example_args1/444';
+  is_deeply $c->req->args, ['mounted_no_arg'];
+}
+
 # BEGIN [user/local_example]
 {
   my ($res, $c) = ctx_request('/user/local_example');
@@ -289,6 +345,26 @@ use Catalyst::Test 'MyApp';
   is_deeply $c->req->args, [444];
 }
 
+{
+  my ($res, $c) = ctx_request('/docs/name');
+  is $c->action, 'docs/name';
+  is $res->content, '/';
+  is_deeply $c->req->args, [];
+}
+
+{
+  my ($res, $c) = ctx_request('/docs/name/111/222');
+  is $c->action, 'docs/name';
+  is $res->content, '/111/222';
+  is_deeply $c->req->args, [111,222];
+}
+
+{
+  my ($res, $c) = ctx_request('/docs/name_args/111');
+  is $c->action, 'docs/name_args';
+  is $res->content, '/111';
+  is_deeply $c->req->args, [111];
+}
 
 done_testing();