[libcatalyst-perl] 01/01: Imported Upstream version 5.90050

Damyan Ivanov dmn at moszumanska.debian.org
Wed Nov 12 08:04:48 UTC 2014


This is an automated email from the git hooks/post-receive script.

dmn pushed a commit to annotated tag upstream/5.90050
in repository libcatalyst-perl.

commit 292b5254efb671a0cd2983241895284754f873c2
Author: Damyan Ivanov <dmn at debian.org>
Date:   Wed Nov 6 14:20:00 2013 +0000

    Imported Upstream version 5.90050
---
 Changes                                            |  93 +++++
 MANIFEST                                           |  21 +-
 META.yml                                           |  17 +-
 Makefile.PL                                        |  22 +-
 lib/Catalyst.pm                                    | 399 ++++++++++++++++++++-
 lib/Catalyst/ActionRole/ConsumesContent.pm         | 164 +++++++++
 lib/Catalyst/Component.pm                          |   6 +-
 lib/Catalyst/Controller.pm                         |  74 +++-
 lib/Catalyst/Delta.pod                             |   2 +-
 lib/Catalyst/DispatchType/Chained.pm               |  15 +-
 lib/Catalyst/Dispatcher.pm                         |   9 +-
 lib/Catalyst/Engine.pm                             |  22 +-
 lib/Catalyst/Engine/HTTP.pm                        |   2 +-
 lib/Catalyst/Log.pm                                |   4 +-
 lib/Catalyst/Plugin/Unicode/Encoding.pm            |   6 +-
 lib/Catalyst/Request.pm                            | 159 +++++---
 lib/Catalyst/Response.pm                           |  63 +++-
 lib/Catalyst/Runtime.pm                            |   2 +-
 lib/Catalyst/Script/Create.pm                      |   3 +-
 lib/Catalyst/Script/Server.pm                      |  22 +-
 lib/Catalyst/ScriptRole.pm                         |   3 +-
 lib/Catalyst/Test.pm                               |   7 +-
 lib/Catalyst/Upgrading.pod                         |   2 +-
 lib/Catalyst/Utils.pm                              |  78 +++-
 t/aggregate.t                                      |   2 -
 t/aggregate/c3_appclass_bug.t                      |   6 +-
 t/aggregate/caf_backcompat.t                       |   5 +-
 ...ve_component_controller_action_auto_doublebug.t |   2 -
 t/aggregate/custom_live_path_bug.t                 |   2 -
 t/aggregate/error_page_dump.t                      |   8 +-
 .../live_component_controller_action_action.t      |   2 -
 .../live_component_controller_action_auto.t        |   2 -
 .../live_component_controller_action_begin.t       |   2 -
 .../live_component_controller_action_chained.t     |   2 -
 .../live_component_controller_action_default.t     |   2 -
 .../live_component_controller_action_detach.t      |   2 -
 .../live_component_controller_action_die_in_end.t  |   2 -
 t/aggregate/live_component_controller_action_end.t |   2 -
 .../live_component_controller_action_forward.t     |   2 -
 .../live_component_controller_action_global.t      |   2 -
 t/aggregate/live_component_controller_action_go.t  |   2 -
 .../live_component_controller_action_index.t       |   2 -
 ..._component_controller_action_index_or_default.t |   2 -
 .../live_component_controller_action_inheritance.t |   2 -
 .../live_component_controller_action_local.t       |   2 -
 .../live_component_controller_action_multipath.t   |   2 -
 .../live_component_controller_action_path.t        |   2 -
 ..._component_controller_action_path_matchsingle.t |   2 -
 .../live_component_controller_action_private.t     |   2 -
 .../live_component_controller_action_streaming.t   |   2 -
 .../live_component_controller_action_visit.t       |   2 -
 t/aggregate/live_component_controller_args.t       |   2 -
 t/aggregate/live_component_controller_attributes.t |   2 -
 t/aggregate/live_component_view_single.t           |   2 -
 t/aggregate/live_engine_request_auth.t             |   2 -
 t/aggregate/live_engine_request_body.t             |   1 -
 t/aggregate/live_engine_request_body_demand.t      |   2 -
 t/aggregate/live_engine_request_cookies.t          |   2 -
 t/aggregate/live_engine_request_env.t              |   2 -
 t/aggregate/live_engine_request_escaped_path.t     |   1 -
 t/aggregate/live_engine_request_headers.t          |   2 -
 t/aggregate/live_engine_request_parameters.t       |   2 -
 .../live_engine_request_prepare_parameters.t       |   2 -
 t/aggregate/live_engine_request_remote_user.t      |   2 -
 t/aggregate/live_engine_request_uploads.t          |  10 +-
 t/aggregate/live_engine_response_body.t            |   2 -
 t/aggregate/live_engine_response_cookies.t         |   2 -
 t/aggregate/live_engine_response_emptybody.t       |   2 -
 t/aggregate/live_engine_response_errors.t          |   2 -
 t/aggregate/live_engine_response_headers.t         |   2 -
 t/aggregate/live_engine_response_large.t           |   2 -
 t/aggregate/live_engine_response_print.t           |   2 -
 t/aggregate/live_engine_response_redirect.t        |   2 -
 t/aggregate/live_engine_response_status.t          |   2 -
 t/aggregate/live_engine_setup_basics.t             |   2 -
 t/aggregate/live_engine_setup_plugins.t            |   2 -
 t/aggregate/live_loop.t                            |   2 -
 t/aggregate/live_plugin_loaded.t                   |   2 -
 t/aggregate/live_priorities.t                      |   2 -
 t/aggregate/meta_method_unneeded.t                 |   1 -
 t/aggregate/unit_core_action_for.t                 |   2 -
 t/aggregate/unit_core_classdata.t                  |   2 -
 t/aggregate/unit_core_engine_fixenv-iis6.t         |   2 -
 t/aggregate/unit_core_engine_fixenv-lighttpd.t     |   2 -
 t/aggregate/unit_core_plugin.t                     |   2 -
 t/aggregate/unit_core_script_cgi.t                 |   7 +-
 t/aggregate/unit_core_script_create.t              |  15 +-
 t/aggregate/unit_core_script_fastcgi.t             |   6 +-
 t/aggregate/unit_core_script_help.t                |   7 +-
 .../unit_core_script_server-without_modules.t      |   4 +-
 t/aggregate/unit_core_script_server.t              |   4 +-
 t/aggregate/unit_core_scriptrunner.t               |   6 +-
 t/aggregate/unit_core_setup_log.t                  |   1 -
 t/aggregate/unit_core_uri_for_action.t             |   2 -
 t/aggregate/unit_load_catalyst_test.t              |  12 +-
 ..._metaclass_compat_extend_non_moose_controller.t |   6 +-
 t/aggregate/unit_metaclass_compat_non_moose.t      |   1 -
 .../unit_metaclass_compat_non_moose_controller.t   |   6 +-
 t/aggregate/unit_utils_prefix.t                    |   2 -
 t/author/http-server.t                             |   3 +-
 t/author/spelling.t                                |   3 +-
 t/author/unicode_plugin_nested_params.t            |   2 -
 t/content_negotiation.t                            | 130 +++++++
 t/custom_exception_class_simple.t                  |  12 +-
 t/data_handler.t                                   |  34 ++
 t/dead_load_bad_args.t                             |   2 -
 t/dead_load_multiple_chained_attributes.t          |   2 -
 t/dead_no_unknown_error.t                          |   2 -
 t/dead_recursive_chained_attributes.t              |   2 -
 t/deprecated.t                                     |   2 -
 .../Catalyst/Plugin/Test/MangleDollarUnderScore.pm |   5 +-
 t/lib/TestApp.pm                                   |   3 +-
 t/lib/TestApp/Controller/Fork.pm                   |   1 -
 t/lib/TestApp/View/Dump.pm                         |   4 +
 t/lib/TestApp/View/Dump/Request.pm                 |   2 +-
 t/lib/TestAppPluginWithConstructor.pm              |   6 +-
 t/lib/TestContentNegotiation.pm                    |  13 +
 t/lib/TestContentNegotiation/Controller/Root.pm    |  50 +++
 t/lib/TestContentNegotiation/share/file.txt        |  50 +++
 t/lib/TestDataHandlers.pm                          |   9 +
 t/lib/TestDataHandlers/Controller/Root.pm          |  15 +
 t/lib/TestFromPSGI.pm                              |  12 +
 t/lib/TestFromPSGI/Controller/Root.pm              |  56 +++
 t/lib/TestMiddleware.pm                            |  38 ++
 t/lib/TestMiddleware/Controller/Root.pm            |  13 +
 t/lib/TestMiddleware/Custom.pm                     |   8 +
 t/lib/TestMiddleware/share/static/forced.txt       |   1 +
 t/lib/TestMiddleware/share/static/message.txt      |   1 +
 t/lib/TestMiddleware/share/static2/message2.txt    |   1 +
 t/lib/TestMiddleware/share/static3/message3.txt    |   1 +
 t/live_fork.t                                      |   1 -
 t/live_stats.t                                     |   2 -
 t/more-psgi-compat.t                               |  53 +++
 t/optional_apache-cgi-rewrite.pl                   |   2 -
 t/optional_apache-cgi.pl                           |   2 -
 t/optional_apache-fastcgi-non-root.pl              |   2 -
 t/optional_apache-fastcgi.pl                       |   2 -
 t/optional_lighttpd-fastcgi-non-root.t             |   2 -
 t/optional_lighttpd-fastcgi.t                      |   2 -
 t/optional_memleak.t                               |   2 -
 t/optional_stress.t                                |   2 -
 t/optional_threads.t                               |   2 -
 t/plack-middleware.t                               |  57 +++
 t/plugin_new_method_backcompat.t                   |   1 -
 t/psgi_file_testapp_engine_plackup_compat.t        |   6 +-
 t/unicode_plugin_config.t                          |   2 -
 t/unicode_plugin_live.t                            |   2 -
 t/unicode_plugin_no_encoding.t                     |   2 -
 t/unicode_plugin_request_decode.t                  |   2 -
 t/unit_core_script_test.t                          |   6 +-
 t/unit_stats.t                                     |   2 -
 t/unit_utils_load_class.t                          |  12 +-
 152 files changed, 1698 insertions(+), 365 deletions(-)

diff --git a/Changes b/Changes
index 0a1b682..851ff40 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,98 @@
 # This file documents the revision history for Perl extension Catalyst.
 
+5.90050 - 2013-11-05
+  - Previously public predicates on the following attributes are now considered
+    private and their method names have been changed to follow Perl convention
+    for internal methods:
+
+      -- Catalyst::Request->has_io_fh ==> _has_io_fh
+      -- Catalyst::Request->has_env ==> _has_env
+      -- Catalyst::Response->has_write_fh ==> _has_write_fh
+
+    These are breaking changes but these methods were never documented and serve
+    no use for external code.  If you are using thing, you need to make the noted
+    change (but please consider finding another way to do what you are trying to
+    do).  t0m++ for code review of Hamburg branch.
+
+5.90049_006 - 2013-11-04
+  - Fixed case where test could fail when Starman was partly installed (n0body++)
+  - Fixed missing date information in previous release
+
+5.90049_005 - 2013-10-31
+  - NEW FEATURE:  New Controller action attribute 'Consumes', which allows you
+    to specify the content type of the incoming request.  This makes it easier
+    to create actions that only handle certain content type POST or PUT, such
+    as actions that only handle JSON or actions that only understand classic
+    HTML forms.
+  - NEW FEATURE: Request->body_data is now also populated from classic HTML 
+    Forms using CGI::Struct to support nested data.  For non nested data you
+    should use the classic ->body_parameters method.
+  - Removed PSGI $env keys that are added on the 'plack.request.*' namespace
+    since after discussion it was clear those keys are not part of the public
+    API.  Keys removed: 'plack.request.query', 'plack.request.body', 
+    'plack.request.merged' and 'plack.request.http.body'. Altered some test
+    cases to reflect this change.
+
+5.90049_004 - 2013-10-18
+  - JSON Data handler looks for both JSON::MaybeXS and JSON, and uses
+    whichever is first (prefering to find JSON::MaybeXS).  This should
+    improve compatibility as you likely already have one installed.
+  - Fixed a warning in the server script (bokutin++)
+  - We now populate various Plack $env keys in order to play nice with
+    downstream middleware or plack apps (and to reduce processing if
+    those keys already exist).  Keys added:
+      - plack.request.query
+      - plack.request.body
+      - plack.request.merged
+      - plack.request.http.body
+    (NOTE: REMOVED IN 5.90049_005)
+  - If incoming input (from a POST or PUT) is not buffered, create the
+    buffer and set the correct psgi env keys to note this for downstream
+    psgi apps / middleware.  This should solve some issues where Catalyst
+    sucks up the body input but its not buffered so downstream apps can't
+    read it (for example FCGI does not buffer).  We now also try to make
+    sure the body content input is reset to the start of the filehandle
+    so that we are polite to downstream middleware /apps.
+  - NEW FEATURE: Catalyst::Response can now pull response from a PSGI
+    specification response.  This makes it easier to host external Plack
+    applications under Catalyst.  See Catalyst::Response->from_psgi_response
+  - NEW FEATURE: New configuration option 'use_hash_multivalue_in_request'
+    will populate $request methods 'parameters', 'body_parameters' and
+    'query_parameters' with an instance of Hash::MultiValue instead of a
+    HashRef.  This is used by Plack and is intended to reduce the need to
+    write defensive logic since you are never sure if an incoming parameter
+    is a scalar or arrayref.
+  - NEW FEATURE: We now experimentally support Net::Async::HTTP::Server
+    and IO-Async based event loops.  Examples will follow.
+
+5.90049_003 - 2013-09-20
+  - Documented the new body_data method added in the previous release
+  - Merged from master many important bugfixes and forward compatiblity
+    updates, including:
+    - Use modern preferred method for Moose metaclass access and many other
+      small changes to how we use Moose for better forward compat (ether++)
+    - Killed some evil use of $@ (ether++)
+    - spelling fixes and documentation updates (ether++), (gerda++)
+    - use Test::Fatal over Test::Exception (ether++)
+    - Misc. test case fixes to modernize code (ether++)
+    - Added a first pass cpanfile, to try and make it easier to bootstrap
+      a development setup (ether++)
+
+5.90049_002 - 2013-08-20
+  - Fixed loading middleware from project directory
+  - Fixed some pointless warnings when middleware class lacked VERSION
+  - NEW FEATURE: Declare global 'data_handlers' for parsing HTTP POST/PUT
+    alternative content, and created default JSON handler.  Yes, now Catalyst
+    handles JSON request content out of the box!  More docs eventually but
+    for now see the DATA HANDLERS section in Catalyst.pm (or review the test
+    case t/data_handler.t
+
+5.90049_001 - 2013-07-26
+  - Declare PSGI compliant Middleware as part of your Catalyst Application via
+    a new configuration key, "psgi_middleware".
+  - Increased lowest allowed module version for Module::Pluggable to be 4.7 (up
+    from 3.4) to solve the fact this is no longer bundled with Perl in v5.18.
+
 5.90042 - 2013-06-14
   - Removed more places where an optional dependency shows up in the test
     suite. Hopefully really fixed the unicode regression introduced in 5.90040
diff --git a/MANIFEST b/MANIFEST
index ef95165..80873fc 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -19,6 +19,7 @@ lib/Catalyst.pm
 lib/Catalyst/Action.pm
 lib/Catalyst/ActionChain.pm
 lib/Catalyst/ActionContainer.pm
+lib/Catalyst/ActionRole/ConsumesContent.pm
 lib/Catalyst/ActionRole/HTTPMethods.pm
 lib/Catalyst/Base.pm
 lib/Catalyst/ClassData.pm
@@ -192,7 +193,9 @@ t/author/spelling.t
 t/author/unicode_plugin_nested_params.t
 t/catalyst_130pix.gif
 t/conf/extra.conf.in
+t/content_negotiation.t
 t/custom_exception_class_simple.t
+t/data_handler.t
 t/dead_load_bad_args.t
 t/dead_load_multiple_chained_attributes.t
 t/dead_no_unknown_error.t
@@ -347,9 +350,9 @@ t/lib/TestAppEncoding.pm
 t/lib/TestAppEncoding/Controller/Root.pm
 t/lib/TestAppEncodingSetInApp.pm
 t/lib/TestAppEncodingSetInApp/Controller/Root.pm
-t/lib/TestAppEncodingSetInConfig/testappencodingsetinconfig.json
 t/lib/TestAppEncodingSetInConfig.pm
 t/lib/TestAppEncodingSetInConfig/Controller/Root.pm
+t/lib/TestAppEncodingSetInConfig/testappencodingsetinconfig.json
 t/lib/TestAppIndexDefault.pm
 t/lib/TestAppIndexDefault/Controller/Default.pm
 t/lib/TestAppIndexDefault/Controller/IndexChained.pm
@@ -385,7 +388,21 @@ t/lib/TestAppWithMeta.pm
 t/lib/TestAppWithMeta/Controller/Root.pm
 t/lib/TestAppWithoutUnicode.pm
 t/lib/TestAppWithoutUnicode/Controller/Root.pm
+t/lib/TestContentNegotiation.pm
+t/lib/TestContentNegotiation/Controller/Root.pm
+t/lib/TestContentNegotiation/share/file.txt
+t/lib/TestDataHandlers.pm
+t/lib/TestDataHandlers/Controller/Root.pm
+t/lib/TestFromPSGI.pm
+t/lib/TestFromPSGI/Controller/Root.pm
 t/lib/TestLogger.pm
+t/lib/TestMiddleware.pm
+t/lib/TestMiddleware/Controller/Root.pm
+t/lib/TestMiddleware/Custom.pm
+t/lib/TestMiddleware/share/static/forced.txt
+t/lib/TestMiddleware/share/static/message.txt
+t/lib/TestMiddleware/share/static2/message2.txt
+t/lib/TestMiddleware/share/static3/message3.txt
 t/lib/TestPluginWithConstructor.pm
 t/live_catalyst_test.t
 t/live_component_controller_context_closure.t
@@ -393,6 +410,7 @@ t/live_fork.t
 t/live_redirect_body.t
 t/live_show_internal_actions_warnings.t
 t/live_stats.t
+t/more-psgi-compat.t
 t/optional_apache-cgi-rewrite.pl
 t/optional_apache-cgi.pl
 t/optional_apache-fastcgi-non-root.pl
@@ -404,6 +422,7 @@ t/optional_memleak.t
 t/optional_stress.t
 t/optional_stress.yml
 t/optional_threads.t
+t/plack-middleware.t
 t/plugin_new_method_backcompat.t
 t/psgi-log.t
 t/psgi_file_testapp.t
diff --git a/META.yml b/META.yml
index 2b6bc8d..7c07723 100644
--- a/META.yml
+++ b/META.yml
@@ -8,7 +8,8 @@ build_requires:
   HTTP::Request::Common: 0
   HTTP::Status: 0
   IO::Scalar: 0
-  Test::Exception: 0
+  JSON::MaybeXS: 0
+  Test::Fatal: 0
   Test::More: 0.88
 configure_requires:
   ExtUtils::MakeMaker: 6.59
@@ -26,12 +27,12 @@ no_index:
     - t
 requires:
   CGI::Simple::Cookie: 1.109
+  CGI::Struct: 0
   Carp: 0
   Catalyst::DispatchType::Regex: 5.90021
   Class::C3::Adopt::NEXT: 0.07
   Class::Data::Inheritable: 0
   Class::Load: 0.12
-  Class::MOP: 0.95
   Data::Dump: 0
   Data::OptList: 0
   Devel::InnerPackage: 0
@@ -43,21 +44,25 @@ requires:
   HTTP::Request: 5.814
   HTTP::Request::AsCGI: 1.0
   HTTP::Response: 5.813
+  Hash::MultiValue: 0
+  JSON::MaybeXS: 1.000000
   LWP: 5.837
   List::MoreUtils: 0
   MRO::Compat: 0
-  Module::Pluggable: 3.9
+  Module::Pluggable: 4.7
   Moose: 1.03
   MooseX::Emulate::Class::Accessor::Fast: 0.00903
   MooseX::Getopt: 0.48
-  MooseX::MethodAttributes::Inheritable: 0.24
+  MooseX::MethodAttributes::Role::AttrContainer::Inheritable: 0.24
   MooseX::Role::WithOverloading: 0.09
   Path::Class: 0.09
   Plack: 0.9991
   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
   Sub::Exporter: 0
   Task::Weaken: 0
@@ -66,7 +71,7 @@ requires:
   Time::HiRes: 0
   Tree::Simple: 1.15
   Tree::Simple::Visitor::FindByPath: 0
-  Try::Tiny: 0
+  Try::Tiny: 0.17
   URI: 1.36
   namespace::autoclean: 0.09
   namespace::clean: 0.23
@@ -77,5 +82,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.90042
+version: 5.90050
 x_authority: cpan:MSTROUT
diff --git a/Makefile.PL b/Makefile.PL
index fd8412a..33a73a6 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -31,10 +31,9 @@ requires 'namespace::autoclean' => '0.09';
 requires 'namespace::clean' => '0.23';
 requires 'MooseX::Emulate::Class::Accessor::Fast' => '0.00903';
 requires 'Class::Load' => '0.12';
-requires 'Class::MOP' => '0.95';
 requires 'Data::OptList';
 requires 'Moose' => '1.03';
-requires 'MooseX::MethodAttributes::Inheritable' => '0.24';
+requires 'MooseX::MethodAttributes::Role::AttrContainer::Inheritable' => '0.24';
 requires 'MooseX::Role::WithOverloading' => '0.09';
 requires 'Carp';
 requires 'Class::C3::Adopt::NEXT' => '0.07';
@@ -48,7 +47,7 @@ requires 'HTTP::Headers' => '1.64';
 requires 'HTTP::Request' => '5.814';
 requires 'HTTP::Response' => '5.813';
 requires 'HTTP::Request::AsCGI' => '1.0';
-requires 'Module::Pluggable' => '3.9';
+requires 'Module::Pluggable' => '4.7';
 requires 'Path::Class' => '0.09';
 requires 'Scalar::Util';
 requires 'Sub::Exporter';
@@ -56,7 +55,7 @@ requires 'Text::SimpleTable' => '0.03';
 requires 'Time::HiRes';
 requires 'Tree::Simple' => '1.15';
 requires 'Tree::Simple::Visitor::FindByPath';
-requires 'Try::Tiny';
+requires 'Try::Tiny' => '0.17';
 requires 'Safe::Isa';
 requires 'Task::Weaken';
 requires 'Text::Balanced'; # core in 5.8.x but mentioned for completeness
@@ -71,17 +70,26 @@ requires 'Class::Data::Inheritable';
 requires 'Encode' => '2.49';
 requires 'LWP' => '5.837'; # LWP had unicode fail in 5.8.26
 requires 'URI' => '1.36';
+requires 'JSON::MaybeXS' => '1.000000';
+requires 'Stream::Buffered';
+requires 'Hash::MultiValue';
+requires 'Plack::Request::Upload';
+requires 'CGI::Struct';
 
 # Install the standalone Regex dispatch modules in order to ease the
-# depreciation transition
+# deprecation transition
 requires 'Catalyst::DispatchType::Regex' => '5.90021';
 
-test_requires 'Test::Exception';
+test_requires 'Test::Fatal';
 test_requires 'Test::More' => '0.88';
 test_requires 'Data::Dump';
 test_requires 'HTTP::Request::Common';
 test_requires 'IO::Scalar';
 test_requires 'HTTP::Status';
+test_requires 'JSON::MaybeXS';
+
+# see also cpanfile for authordeps -- install via
+# cpanm --installdeps --with-develop .
 
 # aggregate tests if AGGREGATE_TESTS is set and a recent Test::Aggregate and a Test::Simple it works with is available
 my @author_requires;
@@ -98,7 +106,7 @@ else {
 push(@author_requires, 'CatalystX::LeakChecker', '0.05');
 push(@author_requires, 'Catalyst::Devel', '1.0'); # For http server test
 push(@author_requires, 'Test::WWW::Mechanize::Catalyst', '0.51');
-push(@author_requires, 'Test::TCP', '1.27'); # ditto, ships Net::EmptyPort
+push(@author_requires, 'Test::TCP', '2.00'); # ditto, ships Net::EmptyPort
 
 author_tests('t/author');
 author_requires(
diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm
index 9e7d156..6007f3a 100644
--- a/lib/Catalyst.pm
+++ b/lib/Catalyst.pm
@@ -35,11 +35,14 @@ use utf8;
 use Carp qw/croak carp shortmess/;
 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::Util;
+use Class::Load 'load_class';
 
 BEGIN { require 5.008003; }
 
@@ -61,6 +64,9 @@ 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;
 }
 
@@ -104,7 +110,8 @@ our $GO        = Catalyst::Exception::Go->new;
 __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/;
+  setup_finished _psgi_app loading_psgi_file run_options _psgi_middleware
+  _data_handlers/;
 
 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
 __PACKAGE__->request_class('Catalyst::Request');
@@ -113,7 +120,7 @@ __PACKAGE__->stats_class('Catalyst::Stats');
 
 # Remember to update this in Catalyst::Runtime as well!
 
-our $VERSION = '5.90042';
+our $VERSION = '5.90050';
 
 sub import {
     my ( $class, @arguments ) = @_;
@@ -322,7 +329,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,
@@ -1108,6 +1126,8 @@ sub setup {
 
     $class->setup_log( delete $flags->{log} );
     $class->setup_plugins( delete $flags->{plugins} );
+    $class->setup_middleware();
+    $class->setup_data_handlers();
     $class->setup_dispatcher( delete $flags->{dispatcher} );
     if (my $engine = delete $flags->{engine}) {
         $class->log->warn("Specifying the engine in ->setup is no longer supported, see Catalyst::Upgrading");
@@ -1149,6 +1169,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};
@@ -1796,7 +1837,7 @@ sub finalize {
     # Support skipping finalize for psgix.io style 'jailbreak'.  Used to support
     # stuff like cometd and websockets
     
-    if($c->request->has_io_fh) {
+    if($c->request->_has_io_fh) {
       $c->log_response;
       return;
     }
@@ -2461,7 +2502,7 @@ sub run {
 
 sub _make_immutable_if_needed {
     my $class = shift;
-    my $meta = Class::MOP::get_metaclass_by_name($class);
+    my $meta = find_meta($class);
     my $isa_ca = $class->isa('Class::Accessor::Fast') || $class->isa('Class::Accessor');
     if (
         $meta->is_immutable
@@ -2652,7 +2693,7 @@ sub setup_dispatcher {
         $dispatcher = $class->dispatcher_class;
     }
 
-    Class::MOP::load_class($dispatcher);
+    load_class($dispatcher);
 
     # dispatcher instance
     $class->dispatcher( $dispatcher->new );
@@ -2702,7 +2743,7 @@ sub setup_engine {
     # Don't really setup_engine -- see _setup_psgi_app for explanation.
     return if $class->loading_psgi_file;
 
-    Class::MOP::load_class($engine);
+    load_class($engine);
 
     if ($ENV{MOD_PERL}) {
         my $apache = $class->engine_loader->auto;
@@ -2726,6 +2767,11 @@ sub setup_engine {
     return;
 }
 
+## 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).
+
 sub _finalized_psgi_app {
     my ($app) = @_;
 
@@ -2737,6 +2783,12 @@ sub _finalized_psgi_app {
     return $app->_psgi_app;
 }
 
+## 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 ).
+
 sub _setup_psgi_app {
     my ($app) = @_;
 
@@ -2847,7 +2899,8 @@ reference of your Catalyst application for use in F<.psgi> files.
 
 sub psgi_app {
     my ($app) = @_;
-    return $app->engine->build_psgi_app($app);
+    my $psgi = $app->engine->build_psgi_app($app);
+    return $app->Catalyst::Utils::apply_registered_middleware($psgi);
 }
 
 =head2 $c->setup_home
@@ -2966,7 +3019,7 @@ 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' );
         my $plugin_meta = Moose::Meta::Class->create($plugin);
@@ -3014,7 +3067,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');
 
@@ -3031,6 +3084,139 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
             $class => @roles
         ) if @roles;
     }
+}    
+
+=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.
+
+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)
+
+=cut
+
+sub registered_middlewares {
+    my $class = shift;
+    if(my $middleware = $class->_psgi_middleware) {
+        return @$middleware;
+    } else {
+        die "You cannot call ->registered_middlewares until middleware has been setup";
+    }
+}
+
+sub setup_middleware {
+    my ($class, @middleware_definitions) = @_;
+    push @middleware_definitions, reverse(
+      @{$class->config->{'psgi_middleware'}||[]});
+
+    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;
+        }
+    }
+
+    $class->_psgi_middleware(\@middleware);
+}
+
+=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 {
+        die "You cannot call ->registered_data_handlers until data_handers has been setup";
+    }
+}
+
+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 {
+          Class::Load::load_first_existing_class('JSON::MaybeXS', 'JSON')
+            ->can('decode_json')->(do { local $/; $_->getline });
+      },
+    };
 }
 
 =head2 $c->stack
@@ -3220,6 +3406,34 @@ use like:
 
 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<psgi_middleware> - See L<PSGI MIDDLEWARE>.
+
+=item *
+
+C<data_handlers> - See L<DATA HANDLERS>.
+
 =back
 
 =head1 INTERNAL ACTIONS
@@ -3311,6 +3525,171 @@ 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> configuation 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>:
+ 
+=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
 
 On request, decodes all params from encoding into a sequence of
diff --git a/lib/Catalyst/ActionRole/ConsumesContent.pm b/lib/Catalyst/ActionRole/ConsumesContent.pm
new file mode 100644
index 0000000..07315c8
--- /dev/null
+++ b/lib/Catalyst/ActionRole/ConsumesContent.pm
@@ -0,0 +1,164 @@
+package Catalyst::ActionRole::ConsumesContent;
+
+use Moose::Role;
+
+requires 'match', 'match_captures', 'list_extra_info';
+
+has allowed_content_types => (
+  is=>'ro',
+  required=>1,
+  lazy=>1,
+  isa=>'ArrayRef',
+  builder=>'_build_allowed_content_types');
+
+has normalized => (
+  is=>'ro',
+  required=>1,
+  lazy=>1,
+  isa=>'HashRef',
+  builder=>'_build_normalized');
+
+
+sub _build_normalized {
+  return +{
+    JSON => 'application/json',
+    JS => 'application/javascript',
+    PERL => 'application/perl',
+    HTML => 'text/html',
+    XML => 'text/XML',
+    Plain => 'text/plain',
+    UrlEncoded => 'application/x-www-form-urlencoded',
+    Multipart => 'multipart/form-data',
+    HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
+  };
+}
+
+sub _build_allowed_content_types {
+    my $self = shift;
+    my @proto = map {split ',', $_ } @{$self->attributes->{Consumes}};
+    my @converted = map {
+      if(my $normalized = $self->normalized->{$_}) {
+        ref $normalized ? @$normalized : ($normalized);
+      } else {
+        $_;
+      }
+    } @proto;
+
+    return \@converted;
+}
+
+around ['match','match_captures'] => sub {
+    my ($orig, $self, $ctx, @args) = @_;
+    if(my $content_type = $ctx->req->content_type) {
+        return 0 unless $self->can_consume($content_type);
+    }
+    return $self->$orig($ctx, @args);
+};
+
+sub can_consume {
+    my ($self, $request_content_type) = @_;
+    my @matches = grep { lc($_) eq lc($request_content_type) }
+      @{$self->allowed_content_types};
+    return @matches ? 1:0;
+}
+
+around 'list_extra_info' => sub {
+  my ($orig, $self, @args) = @_;
+  return {
+    %{ $self->$orig(@args) }, 
+    CONSUMES => $self->allowed_content_types,
+  };
+};
+
+1;
+
+=head1 NAME
+
+Catalyst::ActionRole::ConsumesContent - Match on HTTP Request Content-Type
+
+=head1 SYNOPSIS
+
+    package MyApp::Web::Controller::MyController;
+
+    use base 'Catalyst::Controller';
+
+    sub start : POST Chained('/') CaptureArg(0) { ... }
+
+      sub is_json       : Chained('start') Consumes('application/json') { ... }
+      sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
+      sub is_multipart  : Chained('start') Consumes('multipart/form-data') { ... }
+      
+      ## Alternatively, for common types...
+
+      sub is_json       : Chained('start') Consume(JSON) { ... }
+      sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
+      sub is_multipart  : Chained('start') Consumes(Multipart) { ... }
+
+      ## Or allow more than one type
+      
+      sub is_more_than_one
+        : Chained('start')
+        : Consumes('application/x-www-form-urlencoded')
+        : Consumes('multipart/form-data')
+      {
+        ## ... 
+      }
+
+      1;
+
+=head1 DESCRIPTION
+
+This is an action role that lets your L<Catalyst::Action> match on the content
+type of the incoming request.  
+
+Generally when there's a PUT or POST request, there's a request content body
+with a matching MIME content type.  Commonly this will be one of the types
+used with classic HTML forms ('application/x-www-form-urlencoded' for example)
+but there's nothing stopping you specifying any valid content type.
+
+For matching purposes, we match strings but the casing is insensitive.
+
+=head1 REQUIRES
+
+This role requires the following methods in the consuming class.
+
+=head2 match
+
+=head2 match_captures
+
+Returns 1 if the action matches the existing request and zero if not.
+
+=head1 METHODS
+
+This role defines the following methods
+
+=head2 match
+
+=head2 match_captures
+
+Around method modifier that return 1 if the request content type matches one of the
+allowed content types (see L</http_methods>) and zero otherwise.
+
+=head2 allowed_content_types
+
+An array of strings that are the allowed content types for matching this action.
+
+=head2 can_consume
+
+Boolean.  Does the current request match content type with what this actionrole
+can consume?
+
+=head2 list_extra_info
+
+Add the accepted content type to the debug screen.
+
+=head1 AUTHORS
+
+Catalyst Contributors, see Catalyst.pm
+
+=head1 COPYRIGHT
+
+This library is free software. You can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=cut
diff --git a/lib/Catalyst/Component.pm b/lib/Catalyst/Component.pm
index f747099..13c9323 100644
--- a/lib/Catalyst/Component.pm
+++ b/lib/Catalyst/Component.pm
@@ -9,6 +9,8 @@ use Devel::InnerPackage ();
 use MRO::Compat;
 use mro 'c3';
 use Scalar::Util 'blessed';
+use Class::Load 'is_class_loaded';
+use Moose::Util 'find_meta';
 use namespace::clean -except => 'meta';
 
 with 'MooseX::Emulate::Class::Accessor::Fast';
@@ -93,7 +95,7 @@ sub BUILDARGS {
     } elsif (@_ == 2) { # is it ($app, $args) or foo => 'bar' ?
         if (blessed($_[0])) {
             $args = $_[1] if ref($_[1]) eq 'HASH';
-        } elsif (Class::MOP::is_class_loaded($_[0]) &&
+        } elsif (is_class_loaded($_[0]) &&
                 $_[0]->isa('Catalyst') && ref($_[1]) eq 'HASH') {
             $args = $_[1];
         } else {
@@ -137,7 +139,7 @@ sub config {
         # work in a subclass.
         # TODO maybe this should be a ClassData option?
         my $class = blessed($self) || $self;
-        my $meta = Class::MOP::get_metaclass_by_name($class);
+        my $meta = find_meta($class);
         unless (${ $meta->get_or_add_package_symbol('$_config') }) {
             # Call merge_hashes to ensure we deep copy the parent
             # config onto the subclass
diff --git a/lib/Catalyst/Controller.pm b/lib/Catalyst/Controller.pm
index 99c2893..02db77a 100644
--- a/lib/Catalyst/Controller.pm
+++ b/lib/Catalyst/Controller.pm
@@ -9,7 +9,10 @@ use List::Util qw/first/;
 use List::MoreUtils qw/uniq/;
 use namespace::clean -except => 'meta';
 
-BEGIN { extends qw/Catalyst::Component MooseX::MethodAttributes::Inheritable/; }
+BEGIN {
+    extends qw/Catalyst::Component/;
+    with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
+}
 
 use MooseX::MethodAttributes;
 use Catalyst::Exception;
@@ -117,7 +120,7 @@ for more info about how Catalyst dispatches to actions.
 =cut
 
 #I think both of these could be attributes. doesn't really seem like they need
-#to ble class data. i think that attributes +default would work just fine
+#to be class data. i think that attributes +default would work just fine
 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
 
 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
@@ -317,7 +320,7 @@ sub action_class {
         ? $args{attributes}{ActionClass}[0]
         : $self->_action_class);
 
-    Class::MOP::load_class($class);
+    load_class($class);
     return $class;
 }
 
@@ -365,7 +368,11 @@ sub gather_default_action_roles {
   my @roles = ();
   push @roles, 'Catalyst::ActionRole::HTTPMethods'
     if $args{attributes}->{Method};
-  return @roles;
+
+  push @roles, 'Catalyst::ActionRole::ConsumesContent'
+    if $args{attributes}->{Consumes};
+
+    return @roles;
 }
 
 sub _parse_attrs {
@@ -705,7 +712,7 @@ similar to how annotations work in other languages you might have heard of.
 Generally L<Catalyst> uses these to influence how the dispatcher sees your
 action and when it will run it in response to an incoming request.  They can
 also be used for other things.  Here's a summary, but you should refer to the
-liked manual page for additional help.
+linked manual page for additional help.
 
 =head2 Global
 
@@ -744,7 +751,7 @@ Handle various types of paths:
     sub myaction2 :Path('/bar') { ... } # -> /bar
   }
 
-This is a general toolbox for attaching your action to a give path.
+This is a general toolbox for attaching your action to a given path.
 
 
 =head2 Regex
@@ -827,6 +834,61 @@ When used with L</Path> indicates the number of arguments expected in
 the path.  However if no Args value is set, assumed to 'slurp' all
 remaining path pars under this namespace.
 
+=head2 Consumes('...')
+
+Matches the current action against the content-type of the request.  Typically
+this is used when the request is a POST or PUT and you want to restrict the
+submitted content type.  For example, you might have an HTML for that either
+returns classic url encoded form data, or JSON when Javascript is enabled.  In
+this case you may wish to match either incoming type to one of two different
+actions, for properly processing.
+
+Examples:
+
+    sub is_json       : Chained('start') Consumes('application/json') { ... }
+    sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
+    sub is_multipart  : Chained('start') Consumes('multipart/form-data') { ... }
+
+To reduce boilerplate, we include the following content type shortcuts:
+
+Examples
+
+      sub is_json       : Chained('start') Consume(JSON) { ... }
+      sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
+      sub is_multipart  : Chained('start') Consumes(Multipart) { ... }
+
+You may specify more than one match:
+
+      sub is_more_than_one
+        : Chained('start')
+        : Consumes('application/x-www-form-urlencoded')
+        : Consumes('multipart/form-data')
+
+      sub is_more_than_one
+        : Chained('start')
+        : Consumes(UrlEncoded)
+        : Consumes(Multipart)
+
+Since it is a common case the shortcut C<HTMLForm> matches both
+'application/x-www-form-urlencoded' and 'multipart/form-data'.  Here's the full
+list of available shortcuts:
+
+    JSON => 'application/json',
+    JS => 'application/javascript',
+    PERL => 'application/perl',
+    HTML => 'text/html',
+    XML => 'text/XML',
+    Plain => 'text/plain',
+    UrlEncoded => 'application/x-www-form-urlencoded',
+    Multipart => 'multipart/form-data',
+    HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
+
+Please keep in mind that when dispatching, L<Catalyst> will match the first most
+relevant case, so if you use the C<Consumes> attribute, you should place your
+most accurate matches early in the Chain, and your 'catchall' actions last.
+
+See L<Catalyst::ActionRole::ConsumesContent> for more.
+
 =head1 OPTIONAL METHODS
 
 =head2 _parse_[$name]_attr
diff --git a/lib/Catalyst/Delta.pod b/lib/Catalyst/Delta.pod
index 81cd319..8b5caf2 100755
--- a/lib/Catalyst/Delta.pod
+++ b/lib/Catalyst/Delta.pod
@@ -167,7 +167,7 @@ classes are better implemented as Moose roles.
 
 =item *
 
-L<MooseX::MethodAttributes::Inheritable> is used to contain action
+L<MooseX::MethodAttributes::Role::AttrContainer::Inheritable> is used to contain action
 attributes. This means that attributes are represented in the MOP, and
 decouples action creation from attributes.
 
diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm
index 33e23d2..05fc514 100644
--- a/lib/Catalyst/DispatchType/Chained.pm
+++ b/lib/Catalyst/DispatchType/Chained.pm
@@ -101,6 +101,7 @@ sub list {
         my @parents = ();
         my $parent = "DUMMY";
         my $extra  = $self->_list_extra_http_methods($endpoint);
+        my $consumes = $self->_list_extra_consumes($endpoint);
         my $curr = $endpoint;
         while ($curr) {
             if (my $cap = $curr->list_extra_info->{CaptureArgs}) {
@@ -129,12 +130,16 @@ sub list {
             if (defined(my $cap = $p->list_extra_info->{CaptureArgs})) {
                 $name .= ' ('.$cap.')';
             }
+            if (defined(my $ct = $p->list_extra_info->{Consumes})) {
+                $name .= ' :'.$ct;
+            }
+
             unless ($p eq $parents[0]) {
                 $name = "-> ${name}";
             }
             push(@rows, [ '', $name ]);
         }
-        push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : '')."/${endpoint}" ]);
+        push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : '')."/${endpoint}". ($consumes ? " :$consumes":"" ) ]);
         $rows[0][0] = join('/', '', @parts) || '/';
         $paths->row(@$_) for @rows;
     }
@@ -148,8 +153,16 @@ sub _list_extra_http_methods {
     my ( $self, $action ) = @_;
     return unless defined $action->list_extra_info->{HTTP_METHODS};
     return join(', ', @{$action->list_extra_info->{HTTP_METHODS}});
+
 }
 
+sub _list_extra_consumes {
+    my ( $self, $action ) = @_;
+    return unless defined $action->list_extra_info->{CONSUMES};
+    return join(', ', @{$action->list_extra_info->{CONSUMES}});
+}
+
+
 =head2 $self->match( $c, $path )
 
 Calls C<recurse_match> to see if a chain matches the C<$path>.
diff --git a/lib/Catalyst/Dispatcher.pm b/lib/Catalyst/Dispatcher.pm
index d9fe5b3..6fde402 100644
--- a/lib/Catalyst/Dispatcher.pm
+++ b/lib/Catalyst/Dispatcher.pm
@@ -14,6 +14,7 @@ use Catalyst::Utils;
 use Text::SimpleTable;
 use Tree::Simple;
 use Tree::Simple::Visitor::FindByPath;
+use Class::Load qw(load_class try_load_class);
 
 use namespace::clean -except => 'meta';
 
@@ -516,7 +517,8 @@ sub register {
         unless ( $registered->{$class} ) {
             # FIXME - Some error checking and re-throwing needed here, as
             #         we eat exceptions loading dispatch types.
-            eval { Class::MOP::load_class($class) };
+            # see also try_load_class
+            eval { load_class($class) };
             my $load_failed = $@;
             $self->_check_deprecated_dispatch_type( $key, $load_failed );
             push( @{ $self->dispatch_types }, $class->new ) unless $load_failed;
@@ -660,9 +662,8 @@ sub _load_dispatch_types {
         # first param is undef because we cannot get the appclass
         my $class = Catalyst::Utils::resolve_namespace(undef, 'Catalyst::DispatchType', $type);
 
-        eval { Class::MOP::load_class($class) };
-        Catalyst::Exception->throw( message => qq/Couldn't load "$class"/ )
-          if $@;
+        my ($success, $error) = try_load_class($class);
+        Catalyst::Exception->throw( message => $error ) if not $success;
         push @{ $self->dispatch_types }, $class->new;
 
         push @loaded, $class;
diff --git a/lib/Catalyst/Engine.pm b/lib/Catalyst/Engine.pm
index fc55db7..b7c8cd3 100644
--- a/lib/Catalyst/Engine.pm
+++ b/lib/Catalyst/Engine.pm
@@ -13,6 +13,8 @@ use URI::QueryParam;
 use Plack::Loader;
 use Catalyst::EngineLoader;
 use Encode ();
+use Plack::Request::Upload;
+use Hash::MultiValue;
 use utf8;
 
 use namespace::clean -except => 'meta';
@@ -66,7 +68,7 @@ See L<Catalyst::Response\write> and L<Catalyst::Response\write_fh> for more.
 
 sub finalize_body {
     my ( $self, $c ) = @_;
-    return if $c->response->has_write_fh;
+    return if $c->response->_has_write_fh;
 
     my $body = $c->response->body;
     no warnings 'uninitialized';
@@ -487,8 +489,16 @@ process the query string and extract query parameters.
 
 sub prepare_query_parameters {
     my ($self, $c) = @_;
-
     my $env = $c->request->env;
+
+    if(my $query_obj = $env->{'plack.request.query'}) {
+         $c->request->query_parameters(
+           $c->request->_use_hash_multivalue ?
+              $query_obj->clone :
+              $query_obj->as_hashref_mixed);
+         return;
+    }
+
     my $query_string = exists $env->{QUERY_STRING}
         ? $env->{QUERY_STRING}
         : '';
@@ -496,7 +506,7 @@ sub prepare_query_parameters {
     # Check for keywords (no = signs)
     # (yes, index() is faster than a regex :))
     if ( index( $query_string, '=' ) < 0 ) {
-        $c->request->query_keywords( $self->unescape_uri($query_string) );
+        $c->request->query_keywords($self->unescape_uri($query_string));
         return;
     }
 
@@ -527,7 +537,11 @@ sub prepare_query_parameters {
             $query{$param} = $value;
         }
     }
-    $c->request->query_parameters( \%query );
+
+    $c->request->query_parameters( 
+      $c->request->_use_hash_multivalue ?
+        Hash::MultiValue->from_mixed(\%query) :
+        \%query);
 }
 
 =head2 $self->prepare_read($c)
diff --git a/lib/Catalyst/Engine/HTTP.pm b/lib/Catalyst/Engine/HTTP.pm
index 7b506e6..cf43c0d 100644
--- a/lib/Catalyst/Engine/HTTP.pm
+++ b/lib/Catalyst/Engine/HTTP.pm
@@ -22,7 +22,7 @@ __END__
 
 =head1 NAME
 
-Catalyst::Engine::HTTP
+Catalyst::Engine::HTTP - removed module
 
 =head1 SYNOPSIS
 
diff --git a/lib/Catalyst/Log.pm b/lib/Catalyst/Log.pm
index d72ee16..b834a79 100644
--- a/lib/Catalyst/Log.pm
+++ b/lib/Catalyst/Log.pm
@@ -4,7 +4,7 @@ use Moose;
 with 'MooseX::Emulate::Class::Accessor::Fast';
 
 use Data::Dump;
-use Class::MOP ();
+use Moose::Util 'find_meta';
 use Carp qw/ cluck /;
 
 our %LEVELS = (); # Levels stored as bit field, ergo debug = 1, warn = 2 etc
@@ -33,7 +33,7 @@ sub psgienv {
 {
     my @levels = qw[ debug info warn error fatal ];
 
-    my $meta = Class::MOP::get_metaclass_by_name(__PACKAGE__);
+    my $meta = find_meta(__PACKAGE__);
     my $summed_level = 0;
     for ( my $i = $#levels ; $i >= 0 ; $i-- ) {
 
diff --git a/lib/Catalyst/Plugin/Unicode/Encoding.pm b/lib/Catalyst/Plugin/Unicode/Encoding.pm
index a689f2c..7c61530 100644
--- a/lib/Catalyst/Plugin/Unicode/Encoding.pm
+++ b/lib/Catalyst/Plugin/Unicode/Encoding.pm
@@ -130,12 +130,12 @@ sub setup {
 
     my $conf = $self->config;
 
-    # Allow an explict undef encoding to disable default of utf-8
+    # 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 possibily meaningless test fail... (jnap)
+      unless $self->setup_finished; ## hack to stop possibly meaningless test fail... (jnap)
 }
 
 sub _handle_unicode_decoding {
@@ -201,7 +201,7 @@ Catalyst::Plugin::Unicode::Encoding - Unicode aware Catalyst
 
 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 C<ENCODING> section at L<Catalyst>.
+information, please refer to L<Catalyst/ENCODING>.
 
 =head1 AUTHORS
 
diff --git a/lib/Catalyst/Request.pm b/lib/Catalyst/Request.pm
index f75319b..69ddd69 100644
--- a/lib/Catalyst/Request.pm
+++ b/lib/Catalyst/Request.pm
@@ -7,6 +7,9 @@ use URI::http;
 use URI::https;
 use URI::QueryParam;
 use HTTP::Headers;
+use Stream::Buffered;
+use Hash::MultiValue;
+use Scalar::Util;
 
 use Moose;
 
@@ -14,7 +17,7 @@ use namespace::clean -except => 'meta';
 
 with 'MooseX::Emulate::Class::Accessor::Fast';
 
-has env => (is => 'ro', writer => '_set_env');
+has env => (is => 'ro', writer => '_set_env', predicate => '_has_env');
 # XXX Deprecated crap here - warn?
 has action => (is => 'rw');
 # XXX: Deprecated in docs ages ago (2006), deprecated with warning in 5.8000 due
@@ -57,7 +60,7 @@ has query_keywords => (is => 'rw');
 has match => (is => 'rw');
 has method => (is => 'rw');
 has protocol => (is => 'rw');
-has query_parameters  => (is => 'rw', default => sub { {} });
+has query_parameters  => (is => 'rw', lazy=>1, default => sub { shift->_use_hash_multivalue ? Hash::MultiValue->new : +{} });
 has secure => (is => 'rw', default => 0);
 has captures => (is => 'rw', default => sub { [] });
 has uri => (is => 'rw', predicate => 'has_uri');
@@ -92,27 +95,46 @@ has _log => (
 );
 
 has io_fh => (
-  is=>'ro',
-  predicate=>'has_io_fh',
-  lazy=>1,
-  builder=>'_build_io_fh');
+    is=>'ro',
+    predicate=>'_has_io_fh',
+    lazy=>1,
+    builder=>'_build_io_fh');
 
 sub _build_io_fh {
     my $self = shift;
     return $self->env->{'psgix.io'}
+      || (
+        $self->env->{'net.async.http.server.req'} &&
+        $self->env->{'net.async.http.server.req'}->stream)   ## Until I can make ioasync cabal see the value of supportin psgix.io (jnap)
       || die "Your Server does not support psgix.io";
 };
 
-has body_fh => (
-  is=>'ro',
-  predicate=>'has_body_fh',
-  lazy=>1,
-  builder=>'_build_body_fh');
+has data_handlers => ( is=>'ro', isa=>'HashRef', default=>sub { +{} } );
 
-sub _build_body_fh {
-    (my $input_fh = shift->env->{'psgi.input'})->seek(0, 0);
-    return $input_fh;
-};
+has body_data => (
+    is=>'ro',
+    lazy=>1,
+    builder=>'_build_body_data');
+
+sub _build_body_data {
+    my ($self) = @_;
+    my $content_type = $self->content_type;
+    my ($match) = grep { $content_type =~/$_/i }
+      keys(%{$self->data_handlers});
+
+    if($match) {
+      my $fh = $self->body;
+      local $_ = $fh;
+      return $self->data_handlers->{$match}->($fh, $self);
+    } else { 
+      return undef;
+    }
+}
+
+has _use_hash_multivalue => (
+    is=>'ro', 
+    required=>1, 
+    default=> sub {0});
 
 # Amount of data to read from input on each pass
 our $CHUNKSIZE = 64 * 1024;
@@ -182,13 +204,16 @@ sub prepare_parameters {
     return $self->parameters;
 }
 
-
-
 sub _build_parameters {
     my ( $self ) = @_;
     my $parameters = {};
     my $body_parameters = $self->body_parameters;
     my $query_parameters = $self->query_parameters;
+
+    if($self->_use_hash_multivalue) {
+        return Hash::MultiValue->new($query_parameters->flatten, $body_parameters->flatten);
+    }
+
     # We copy, no references
     foreach my $name (keys %$query_parameters) {
         my $param = $query_parameters->{$name};
@@ -215,30 +240,68 @@ has _uploadtmp => (
 sub prepare_body {
     my ( $self ) = @_;
 
-    if ( my $length = $self->_read_length ) {
-        unless ( $self->_body ) {
-            my $type = $self->header('Content-Type');
-            $self->_body(HTTP::Body->new( $type, $length ));
-            $self->_body->cleanup(1); # Make extra sure!
-            $self->_body->tmpdir( $self->_uploadtmp )
-              if $self->_has_uploadtmp;
-        }
+    # If previously applied middleware created the HTTP::Body object, then we
+    # just use that one.  
 
-        # Check for definedness as you could read '0'
-        while ( defined ( my $buffer = $self->read() ) ) {
-            $self->prepare_body_chunk($buffer);
-        }
+    if(my $plack_body = $self->env->{'plack.request.http.body'}) {
+        $self->_body($plack_body);
+        $self->_body->cleanup(1);
+        return;
+    }
 
-        # paranoia against wrong Content-Length header
-        my $remaining = $length - $self->_read_position;
-        if ( $remaining > 0 ) {
-            Catalyst::Exception->throw(
-                "Wrong Content-Length value: $length" );
-        }
+    # If there is nothing to read, set body to naught and return.  This
+    # will cause all body code to be skipped
+
+    return $self->_body(0) unless my $length = $self->_read_length;
+
+    # Unless the body has already been set, create it.  Not sure about this
+    # code, how else might it be set, but this was existing logic.
+
+    unless ($self->_body) {
+        my $type = $self->header('Content-Type');
+        $self->_body(HTTP::Body->new( $type, $length ));
+        $self->_body->cleanup(1);
+
+        # JNAP: I'm not sure this is doing what we expect, but it also doesn't
+        # seem to be hurting (seems ->_has_uploadtmp is true more than I would
+        # expect.
+
+        $self->_body->tmpdir( $self->_uploadtmp )
+          if $self->_has_uploadtmp;
     }
-    else {
-        # Defined but will cause all body code to be skipped
-        $self->_body(0);
+
+    # Ok if we get this far, we have to read psgi.input into the new body
+    # object.  Lets play nice with any plack app or other downstream, so
+    # we create a buffer unless one exists.
+     
+    my $stream_buffer;
+    if ($self->env->{'psgix.input.buffered'}) {
+        # Be paranoid about previous psgi middleware or apps that read the
+        # input but didn't return the buffer to the start.
+        $self->env->{'psgi.input'}->seek(0, 0);
+    } else {
+        $stream_buffer = Stream::Buffered->new($length);
+    }
+
+    # Check for definedness as you could read '0'
+    while ( defined ( my $chunk = $self->read() ) ) {
+        $self->prepare_body_chunk($chunk);
+        $stream_buffer->print($chunk) if $stream_buffer;
+    }
+
+    # Ok, we read the body.  Lets play nice for any PSGI app down the pipe
+
+    if ($stream_buffer) {
+        $self->env->{'psgix.input.buffered'} = 1;
+        $self->env->{'psgi.input'} = $stream_buffer->rewind;
+    } else {
+        $self->env->{'psgi.input'}->seek(0, 0); # Reset the buffer for downstream middleware or apps
+    }
+
+    # paranoia against wrong Content-Length header
+    my $remaining = $length - $self->_read_position;
+    if ( $remaining > 0 ) {
+        Catalyst::Exception->throw("Wrong Content-Length value: $length" );
     }
 }
 
@@ -252,9 +315,14 @@ sub prepare_body_parameters {
     my ( $self ) = @_;
 
     $self->prepare_body if ! $self->_has_body;
-    return {} unless $self->_body;
 
-    return $self->_body->param;
+    unless($self->_body) {
+      return $self->_use_hash_multivalue ? Hash::MultiValue->new : {};
+    }
+
+    return $self->_use_hash_multivalue ?
+        Hash::MultiValue->from_mixed($self->_body->param) :
+        $self->_body->param;
 }
 
 sub prepare_connection {
@@ -304,7 +372,7 @@ has _body => (
 #             and provide a custom reader..
 sub body {
   my $self = shift;
-  $self->prepare_body unless ! $self->_has_body;
+  $self->prepare_body unless $self->_has_body;
   croak 'body is a reader' if scalar @_;
   return blessed $self->_body ? $self->_body->body : $self->_body;
 }
@@ -342,6 +410,7 @@ Catalyst::Request - provides information about the current client request
     $req->args;
     $req->base;
     $req->body;
+    $req->body_data;
     $req->body_parameters;
     $req->content_encoding;
     $req->content_length;
@@ -424,6 +493,14 @@ Returns the message body of the request, as returned by L<HTTP::Body>: a string,
 unless Content-Type is C<application/x-www-form-urlencoded>, C<text/xml>, or
 C<multipart/form-data>, in which case a L<File::Temp> object is returned.
 
+=head2 $req->body_data
+
+Returns a Perl representation of POST/PUT body data that is not classic HTML
+form data, such as JSON, XML, etc.  By default, Catalyst will parse incoming
+data of the type 'application/json' and return access to that data via this
+method.  You may define addition data_handlers via a global configuration
+setting.  See L<Catalyst\DATA HANDLERS> for more information.
+
 =head2 $req->body_parameters
 
 Returns a reference to a hash containing body (POST) parameters. Values can
diff --git a/lib/Catalyst/Response.pm b/lib/Catalyst/Response.pm
index 1db5666..b57f84c 100644
--- a/lib/Catalyst/Response.pm
+++ b/lib/Catalyst/Response.pm
@@ -28,7 +28,7 @@ has _writer => (
 
 has write_fh => (
   is=>'ro',
-  predicate=>'has_write_fh',
+  predicate=>'_has_write_fh',
   lazy=>1,
   builder=>'_build_write_fh',
 );
@@ -42,7 +42,7 @@ sub _build_write_fh {
 
 sub DEMOLISH {
   my $self = shift;
-  return if $self->has_write_fh;
+  return if $self->_has_write_fh;
   if($self->_has_writer) {
     $self->_writer->close
   }
@@ -112,6 +112,38 @@ sub finalize_headers {
     return;
 }
 
+sub from_psgi_response {
+    my ($self, $psgi_res) = @_;
+    if(ref $psgi_res eq 'ARRAY') {
+        my ($status, $headers, $body) = @$psgi_res;
+        $self->status($status);
+        $self->headers(HTTP::Headers->new(@$headers));
+        if(ref $body eq 'ARRAY') {
+          $self->body(join '', grep defined, @$body);
+        } else {
+          $self->body($body);
+        }
+    } elsif(ref $psgi_res eq 'CODE') {
+        $psgi_res->(sub {
+            my $response = shift;
+            my ($status, $headers, $maybe_body) = @$response;
+            $self->status($status);
+            $self->headers(HTTP::Headers->new(@$headers));
+            if($maybe_body) {
+                if(ref $maybe_body eq 'ARRAY') {
+                  $self->body(join '', grep defined, @$maybe_body);
+                } else {
+                  $self->body($maybe_body);
+                }
+            } else {
+                return $self->write_fh;
+            }
+        });  
+     } else {
+        die "You can't set a Catalyst response from that, expect a valid PSGI response";
+    }
+}
+
 =head1 NAME
 
 Catalyst::Response - stores output responding to the current client request
@@ -309,6 +341,33 @@ the response object to functions that want to write to an L<IO::Handle>.
 
 Writes headers to response if not already written
 
+=head2 from_psgi_response
+
+Given a PSGI response (either three element ARRAY reference OR coderef expecting
+a $responder) set the response from it.
+
+Properly supports streaming and delayed response and / or async IO if running
+under an expected event loop.
+
+Example:
+
+    package MyApp::Web::Controller::Test;
+
+    use base 'Catalyst::Controller';
+    use Plack::App::Directory;
+
+
+    my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
+      ->to_app;
+
+    sub myaction :Local Args {
+      my ($self, $c) = @_;
+      $c->res->from_psgi_response($app->($self->env));
+    }
+
+Please note this does not attempt to map or nest your PSGI application under
+the Controller and Action namespace or path.  
+
 =head2 DEMOLISH
 
 Ensures that the response is flushed and closed at the end of the
diff --git a/lib/Catalyst/Runtime.pm b/lib/Catalyst/Runtime.pm
index 867ecf8..3da2731 100644
--- a/lib/Catalyst/Runtime.pm
+++ b/lib/Catalyst/Runtime.pm
@@ -7,7 +7,7 @@ BEGIN { require 5.008003; }
 
 # Remember to update this in Catalyst as well!
 
-our $VERSION = '5.90042';
+our $VERSION = '5.90050';
 
 =head1 NAME
 
diff --git a/lib/Catalyst/Script/Create.pm b/lib/Catalyst/Script/Create.pm
index 593323d..a74653b 100644
--- a/lib/Catalyst/Script/Create.pm
+++ b/lib/Catalyst/Script/Create.pm
@@ -1,5 +1,6 @@
 package Catalyst::Script::Create;
 use Moose;
+use Class::Load 'load_class';
 use namespace::autoclean;
 
 with 'Catalyst::ScriptRole';
@@ -42,7 +43,7 @@ sub run {
     $self->print_usage_text if !$self->ARGV->[0];
 
     my $helper_class = $self->helper_class;
-    Class::MOP::load_class($helper_class);
+    load_class($helper_class);
     my $helper = $helper_class->new( { '.newfiles' => !$self->force, mech => $self->mechanize } );
 
     $self->print_usage_text unless $helper->mk_component( $self->application_name, @{$self->extra_argv} );
diff --git a/lib/Catalyst/Script/Server.pm b/lib/Catalyst/Script/Server.pm
index 270490e..5f0ac06 100644
--- a/lib/Catalyst/Script/Server.pm
+++ b/lib/Catalyst/Script/Server.pm
@@ -1,7 +1,7 @@
 package Catalyst::Script::Server;
 use Moose;
 use Catalyst::Utils;
-use Try::Tiny;
+use Class::Load qw(try_load_class load_class);
 use namespace::autoclean;
 
 with 'Catalyst::ScriptRole';
@@ -49,11 +49,9 @@ subtype 'Catalyst::Script::Server::Types::Pidfile',
     as 'MooseX::Daemonize::Pid::File';
 
 coerce 'Catalyst::Script::Server::Types::Pidfile', from 'Str', via {
-    try { Class::MOP::load_class("MooseX::Daemonize::Pid::File") }
-    catch {
-        warn("Could not load MooseX::Daemonize::Pid::File, needed for --pid option\n");
-        exit 1;
-    };
+    my ($success, $error) = try_load_class("MooseX::Daemonize::Pid::File");
+    warn("Could not load MooseX::Daemonize::Pid::File, needed for --pid option: $error\n"),
+        exit 1 if not $success;
     MooseX::Daemonize::Pid::File->new( file => $_ );
 };
 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
@@ -76,11 +74,11 @@ sub BUILD {
 
     if ($self->background) {
         # FIXME - This is evil. Should we just add MX::Daemonize to the deps?
-        try { Class::MOP::load_class('MooseX::Daemonize::Core'); Class::MOP::load_class('POSIX') }
-        catch {
-            warn("MooseX::Daemonize is needed for the --background option\n");
-            exit 1;
-        };
+        my ($success, $error) = try_load_class("MooseX::Daemonize::Core");
+        warn("MooseX::Daemonize is needed for the --background option: $error\n"),
+            exit 1 if not $success;
+        ($success, $error) = try_load_class("POSIX");
+        warn("$error\n"), exit 1 if not $success;
         MooseX::Daemonize::Core->meta->apply($self);
         POSIX::close($_) foreach (0..2);
     }
@@ -229,7 +227,7 @@ sub run {
 
             return 1 unless $self->is_daemon;
 
-            Class::MOP::load_class($self->application_name);
+            load_class($self->application_name);
 
             $self->daemon_detach;
         }
diff --git a/lib/Catalyst/ScriptRole.pm b/lib/Catalyst/ScriptRole.pm
index 4bab785..f8a12da 100644
--- a/lib/Catalyst/ScriptRole.pm
+++ b/lib/Catalyst/ScriptRole.pm
@@ -5,6 +5,7 @@ use MooseX::Getopt;
 use Catalyst::EngineLoader;
 use Moose::Util::TypeConstraints;
 use Catalyst::Utils qw/ ensure_class_loaded /;
+use Class::Load 'load_class';
 use namespace::autoclean;
 
 subtype 'Catalyst::ScriptRole::LoadableClass',
@@ -87,7 +88,7 @@ sub _plack_engine_name {}
 sub _run_application {
     my $self = shift;
     my $app = $self->application_name;
-    Class::MOP::load_class($app);
+    load_class($app);
     my $server;
     if (my $e = $self->_plack_engine_name ) {
         $server = $self->load_engine($e, $self->_plack_loader_args);
diff --git a/lib/Catalyst/Test.pm b/lib/Catalyst/Test.pm
index 53c16a2..e121b35 100644
--- a/lib/Catalyst/Test.pm
+++ b/lib/Catalyst/Test.pm
@@ -7,8 +7,9 @@ use Test::More ();
 use Plack::Test;
 use Catalyst::Exception;
 use Catalyst::Utils;
-use Class::MOP;
+use Class::Load qw(load_class is_class_loaded);
 use Sub::Exporter;
+use Moose::Util 'find_meta';
 use Carp 'croak', 'carp';
 
 sub _build_request_export {
@@ -25,7 +26,7 @@ sub _build_request_export {
     return sub { croak "Must specify a test app: use Catalyst::Test 'TestApp'" }
         unless $class;
 
-    Class::MOP::load_class($class) unless Class::MOP::is_class_loaded($class);
+    load_class($class) unless is_class_loaded($class);
     $class->import;
 
     return sub { _local_request( $class, @_ ) };
@@ -58,7 +59,7 @@ sub _build_ctx_request_export {
 
         # hook into 'dispatch' -- the function gets called after all plugins
         # have done their work, and it's an easy place to capture $c.
-        my $meta = Class::MOP::get_metaclass_by_name($class);
+        my $meta = find_meta($class);
         $meta->make_mutable;
         $meta->add_after_method_modifier( "dispatch", sub {
             $ctx_closed_over = shift;
diff --git a/lib/Catalyst/Upgrading.pod b/lib/Catalyst/Upgrading.pod
index 3e2d9d0..03a24ab 100644
--- a/lib/Catalyst/Upgrading.pod
+++ b/lib/Catalyst/Upgrading.pod
@@ -102,7 +102,7 @@ to use L<Catalyst::Script::FastCGI>.
 The engines that are built upon the various iterations of mod_perl,
 L<Catalyst::Engine::Apache::MP13> (for mod_perl 1, and Apache 1.x) and
 L<Catalyst::Engine::Apache2::MP20> (for mod_perl 2, and Apache 2.x),
-should be seamless upgrades and will work using using L<Plack::Handler::Apache1>
+should be seamless upgrades and will work using L<Plack::Handler::Apache1>
 or L<Plack::Handler::Apache2> as required.
 
 L<Catalyst::Engine::Apache2::MP19>, however, is no longer supported, as
diff --git a/lib/Catalyst/Utils.pm b/lib/Catalyst/Utils.pm
index 245c789..fffa048 100644
--- a/lib/Catalyst/Utils.pm
+++ b/lib/Catalyst/Utils.pm
@@ -7,8 +7,9 @@ use Path::Class;
 use URI;
 use Carp qw/croak/;
 use Cwd;
-use Class::MOP;
+use Class::Load 'is_class_loaded';
 use String::RewritePrefix;
+use Class::Load ();
 
 use namespace::clean;
 
@@ -136,9 +137,8 @@ sub class2tempdir {
 
     if ( $create && !-e $tmpdir ) {
 
-        eval { $tmpdir->mkpath };
-
-        if ($@) {
+        eval { $tmpdir->mkpath; 1 }
+        or do {
             # don't load Catalyst::Exception as a BEGIN in Utils,
             # because Utils often gets loaded before MyApp.pm, and if
             # Catalyst::Exception is loaded before MyApp.pm, it does
@@ -223,7 +223,7 @@ sub home {
             ( my $path = $inc_entry) =~ s/\.pm$//;
             my $home = dir($path)->absolute->cleanup;
 
-            # return if if it's a valid directory
+            # return if it's a valid directory
             return $home->stringify if -d $home;
         }
     }
@@ -297,7 +297,7 @@ sub ensure_class_loaded {
     # if it already has symbol table entries. This is to support things like Schema::Loader, which
     # part-generate classes in memory, but then also load some of their contents from disk.
     return if !$opts->{ ignore_loaded }
-        && Class::MOP::is_class_loaded($class); # if a symbol entry exists we don't load again
+        && is_class_loaded($class); # if a symbol entry exists we don't load again
 
     # this hack is so we don't overwrite $@ if the load did not generate an error
     my $error;
@@ -312,7 +312,7 @@ sub ensure_class_loaded {
     die $error if $error;
 
     warn "require $class was successful but the package is not defined."
-        unless Class::MOP::is_class_loaded($class);
+        unless is_class_loaded($class);
 
     return 1;
 }
@@ -391,17 +391,17 @@ my $_term_width;
 sub term_width {
     return $_term_width if $_term_width;
 
-    my $width = eval '
-        use Term::Size::Any;
+    my $width;
+    eval '
+        require Term::Size::Any;
         my ($columns, $rows) = Term::Size::Any::chars;
-        return $columns;
-    ';
-
-    if ($@) {
+        $width = $columns;
+        1;
+    ' or do {
         $width = $ENV{COLUMNS}
             if exists($ENV{COLUMNS})
             && $ENV{COLUMNS} =~ m/^\d+$/;
-    }
+    };
 
     $width = 80 unless ($width && $width >= 80);
     return $_term_width = $width;
@@ -433,6 +433,56 @@ sub resolve_namespace {
     }, @classes);
 }
 
+=head2 build_middleware (@args)
+
+Internal application that converts a single middleware definition (see
+L<Catalyst/psgi_middleware>) into an actual instance of middleware.
+
+=cut
+
+sub build_middleware {
+    my ($class, $namespace, @init_args) = @_;
+
+    if(
+      $namespace =~s/^\+// ||
+      $namespace =~/^Plack::Middleware/ ||
+      $namespace =~/^$class/
+    ) {  ## the string is a full namespace
+        return Class::Load::try_load_class($namespace) ?
+          $namespace->new(@init_args) :
+            die "Can't load class $namespace";
+    } else { ## the string is a partial namespace
+      if(Class::Load::try_load_class($class .'::Middleware::'. $namespace)) { ## Load Middleware from Project namespace
+          my $ns = $class .'::Middleware::'. $namespace;
+          return $ns->new(@init_args);
+        } elsif(Class::Load::try_load_class("Plack::Middleware::$namespace")) { ## Act like Plack::Builder
+          return "Plack::Middleware::$namespace"->new(@init_args);
+        }
+    }
+
+    return; ## be sure we can count on a proper return when valid
+}
+
+=head2 apply_registered_middleware ($psgi)
+
+Given a $psgi reference, wrap all the L<Catalyst/registered_middlewares>
+around it and return the wrapped version.
+
+This exists to deal with the fact Catalyst registered middleware can be
+either an object with a wrap method or a coderef.
+
+=cut
+
+sub apply_registered_middleware {
+    my ($class, $psgi) = @_;
+    my $new_psgi = $psgi;
+    foreach my $middleware ($class->registered_middlewares) {
+        $new_psgi = Scalar::Util::blessed $middleware ?
+          $middleware->wrap($new_psgi) :
+            $middleware->($new_psgi);
+    }
+    return $new_psgi;
+}
 
 =head1 AUTHORS
 
diff --git a/t/aggregate.t b/t/aggregate.t
index 543fe02..e071379 100644
--- a/t/aggregate.t
+++ b/t/aggregate.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/c3_appclass_bug.t b/t/aggregate/c3_appclass_bug.t
index 0e5f7ed..e7b44a4 100644
--- a/t/aggregate/c3_appclass_bug.t
+++ b/t/aggregate/c3_appclass_bug.t
@@ -21,10 +21,10 @@ use Test::More tests => 1;
     /;
 }
 
-use Test::Exception;
-lives_ok {
+use Test::Fatal;
+is exception {
     TestAppC3ErrorUseMoose->setup();
-} 'No C3 error';
+}, undef, 'No C3 error';
 
 1;
 
diff --git a/t/aggregate/caf_backcompat.t b/t/aggregate/caf_backcompat.t
index 27d8fa9..ddff5f6 100644
--- a/t/aggregate/caf_backcompat.t
+++ b/t/aggregate/caf_backcompat.t
@@ -1,8 +1,7 @@
 use strict;
 use warnings;
 use Test::More;
-use Test::Exception;
-use Class::MOP ();
+use Class::Load 'load_class';
 use Moose::Util ();
 
 # List of everything which used Class::Accessor::Fast in 5.70.
@@ -22,7 +21,7 @@ my @modules = qw/
 plan tests => scalar @modules;
 
 foreach my $module (@modules) {
-    Class::MOP::load_class($module);
+    load_class($module);
     ok Moose::Util::does_role($module => 'MooseX::Emulate::Class::Accessor::Fast'),
         "$module has Class::Accessor::Fast back-compat";
 }
diff --git a/t/aggregate/custom_live_component_controller_action_auto_doublebug.t b/t/aggregate/custom_live_component_controller_action_auto_doublebug.t
index 1b657e6..4bb1c57 100644
--- a/t/aggregate/custom_live_component_controller_action_auto_doublebug.t
+++ b/t/aggregate/custom_live_component_controller_action_auto_doublebug.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/custom_live_path_bug.t b/t/aggregate/custom_live_path_bug.t
index a6081c4..af2e3be 100644
--- a/t/aggregate/custom_live_path_bug.t
+++ b/t/aggregate/custom_live_path_bug.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/error_page_dump.t b/t/aggregate/error_page_dump.t
index 099f8da..6cec423 100644
--- a/t/aggregate/error_page_dump.t
+++ b/t/aggregate/error_page_dump.t
@@ -1,15 +1,15 @@
 use strict;
 use warnings;
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 
 use Catalyst::Engine;
 
 my $m = sub { Catalyst::Engine->_dump_error_page_element(@_) };
 
-lives_ok { $m->('Scalar' => ['foo' => 'bar']) };
-lives_ok { $m->('Array' => ['foo' => []]) };
-lives_ok { $m->('Hash' => ['foo' => {}]) }; 
+is exception { $m->('Scalar' => ['foo' => 'bar']) }, undef;
+is exception { $m->('Array' => ['foo' => []]) }, undef;
+is exception { $m->('Hash' => ['foo' => {}]) }, undef;
 
 done_testing;
 
diff --git a/t/aggregate/live_component_controller_action_action.t b/t/aggregate/live_component_controller_action_action.t
index eebfe48..41e2b16 100644
--- a/t/aggregate/live_component_controller_action_action.t
+++ b/t/aggregate/live_component_controller_action_action.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_auto.t b/t/aggregate/live_component_controller_action_auto.t
index 853bb8f..0720329 100644
--- a/t/aggregate/live_component_controller_action_auto.t
+++ b/t/aggregate/live_component_controller_action_auto.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_begin.t b/t/aggregate/live_component_controller_action_begin.t
index e5b2e0f..8478910 100644
--- a/t/aggregate/live_component_controller_action_begin.t
+++ b/t/aggregate/live_component_controller_action_begin.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_chained.t b/t/aggregate/live_component_controller_action_chained.t
index 0cebe9b..99ea3c7 100644
--- a/t/aggregate/live_component_controller_action_chained.t
+++ b/t/aggregate/live_component_controller_action_chained.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_default.t b/t/aggregate/live_component_controller_action_default.t
index 4222b8c..6e809e7 100644
--- a/t/aggregate/live_component_controller_action_default.t
+++ b/t/aggregate/live_component_controller_action_default.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_detach.t b/t/aggregate/live_component_controller_action_detach.t
index 2f43a53..d00a9b4 100644
--- a/t/aggregate/live_component_controller_action_detach.t
+++ b/t/aggregate/live_component_controller_action_detach.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_die_in_end.t b/t/aggregate/live_component_controller_action_die_in_end.t
index b43aafe..a78b6f6 100644
--- a/t/aggregate/live_component_controller_action_die_in_end.t
+++ b/t/aggregate/live_component_controller_action_die_in_end.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_end.t b/t/aggregate/live_component_controller_action_end.t
index 22b8333..3e84623 100644
--- a/t/aggregate/live_component_controller_action_end.t
+++ b/t/aggregate/live_component_controller_action_end.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_forward.t b/t/aggregate/live_component_controller_action_forward.t
index d968965..5d4a8d0 100644
--- a/t/aggregate/live_component_controller_action_forward.t
+++ b/t/aggregate/live_component_controller_action_forward.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_global.t b/t/aggregate/live_component_controller_action_global.t
index 5a90084..7d4f6b8 100644
--- a/t/aggregate/live_component_controller_action_global.t
+++ b/t/aggregate/live_component_controller_action_global.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_go.t b/t/aggregate/live_component_controller_action_go.t
index 8554f72..60f8bb8 100644
--- a/t/aggregate/live_component_controller_action_go.t
+++ b/t/aggregate/live_component_controller_action_go.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_index.t b/t/aggregate/live_component_controller_action_index.t
index fbaeaab..48c6ec7 100644
--- a/t/aggregate/live_component_controller_action_index.t
+++ b/t/aggregate/live_component_controller_action_index.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_index_or_default.t b/t/aggregate/live_component_controller_action_index_or_default.t
index ea5d2c3..e984152 100644
--- a/t/aggregate/live_component_controller_action_index_or_default.t
+++ b/t/aggregate/live_component_controller_action_index_or_default.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_inheritance.t b/t/aggregate/live_component_controller_action_inheritance.t
index c58866b..ec2c663 100644
--- a/t/aggregate/live_component_controller_action_inheritance.t
+++ b/t/aggregate/live_component_controller_action_inheritance.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_local.t b/t/aggregate/live_component_controller_action_local.t
index 184a373..052c9c1 100644
--- a/t/aggregate/live_component_controller_action_local.t
+++ b/t/aggregate/live_component_controller_action_local.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_multipath.t b/t/aggregate/live_component_controller_action_multipath.t
index e4bb242..3fa4433 100644
--- a/t/aggregate/live_component_controller_action_multipath.t
+++ b/t/aggregate/live_component_controller_action_multipath.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_path.t b/t/aggregate/live_component_controller_action_path.t
index 950b4ac..1f8541d 100644
--- a/t/aggregate/live_component_controller_action_path.t
+++ b/t/aggregate/live_component_controller_action_path.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_path_matchsingle.t b/t/aggregate/live_component_controller_action_path_matchsingle.t
index beced91..7957012 100644
--- a/t/aggregate/live_component_controller_action_path_matchsingle.t
+++ b/t/aggregate/live_component_controller_action_path_matchsingle.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_private.t b/t/aggregate/live_component_controller_action_private.t
index 44d4f16..8ad01bd 100644
--- a/t/aggregate/live_component_controller_action_private.t
+++ b/t/aggregate/live_component_controller_action_private.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_streaming.t b/t/aggregate/live_component_controller_action_streaming.t
index ba18bd7..e14b928 100644
--- a/t/aggregate/live_component_controller_action_streaming.t
+++ b/t/aggregate/live_component_controller_action_streaming.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_action_visit.t b/t/aggregate/live_component_controller_action_visit.t
index b331e7c..5221372 100644
--- a/t/aggregate/live_component_controller_action_visit.t
+++ b/t/aggregate/live_component_controller_action_visit.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_args.t b/t/aggregate/live_component_controller_args.t
index 93b757c..7b99b24 100644
--- a/t/aggregate/live_component_controller_args.t
+++ b/t/aggregate/live_component_controller_args.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_controller_attributes.t b/t/aggregate/live_component_controller_attributes.t
index 9f8e8c7..925504f 100644
--- a/t/aggregate/live_component_controller_attributes.t
+++ b/t/aggregate/live_component_controller_attributes.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_component_view_single.t b/t/aggregate/live_component_view_single.t
index 15924cd..b5564e8 100644
--- a/t/aggregate/live_component_view_single.t
+++ b/t/aggregate/live_component_view_single.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_auth.t b/t/aggregate/live_engine_request_auth.t
index f5370ce..77b6e7c 100644
--- a/t/aggregate/live_engine_request_auth.t
+++ b/t/aggregate/live_engine_request_auth.t
@@ -1,5 +1,3 @@
-#!perl
-
 # This tests to make sure the Authorization header is passed through by the engine.
 
 use strict;
diff --git a/t/aggregate/live_engine_request_body.t b/t/aggregate/live_engine_request_body.t
index 954291c..0abe175 100644
--- a/t/aggregate/live_engine_request_body.t
+++ b/t/aggregate/live_engine_request_body.t
@@ -1,4 +1,3 @@
-#!perl
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_body_demand.t b/t/aggregate/live_engine_request_body_demand.t
index 5646769..699b162 100644
--- a/t/aggregate/live_engine_request_body_demand.t
+++ b/t/aggregate/live_engine_request_body_demand.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_cookies.t b/t/aggregate/live_engine_request_cookies.t
index 5a45acc..f63001a 100644
--- a/t/aggregate/live_engine_request_cookies.t
+++ b/t/aggregate/live_engine_request_cookies.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_env.t b/t/aggregate/live_engine_request_env.t
index 6d3e3e9..ecc2a0b 100644
--- a/t/aggregate/live_engine_request_env.t
+++ b/t/aggregate/live_engine_request_env.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_escaped_path.t b/t/aggregate/live_engine_request_escaped_path.t
index e86c154..68b31d1 100644
--- a/t/aggregate/live_engine_request_escaped_path.t
+++ b/t/aggregate/live_engine_request_escaped_path.t
@@ -1,4 +1,3 @@
-#!/usr/bin/evn perl
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_headers.t b/t/aggregate/live_engine_request_headers.t
index b93c1c9..4cd98db 100644
--- a/t/aggregate/live_engine_request_headers.t
+++ b/t/aggregate/live_engine_request_headers.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_parameters.t b/t/aggregate/live_engine_request_parameters.t
index d68ed0a..c7b4611 100644
--- a/t/aggregate/live_engine_request_parameters.t
+++ b/t/aggregate/live_engine_request_parameters.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_prepare_parameters.t b/t/aggregate/live_engine_request_prepare_parameters.t
index e933fb5..73ec7bd 100755
--- a/t/aggregate/live_engine_request_prepare_parameters.t
+++ b/t/aggregate/live_engine_request_prepare_parameters.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_request_remote_user.t b/t/aggregate/live_engine_request_remote_user.t
index 1a6c0d8..e6c8747 100644
--- a/t/aggregate/live_engine_request_remote_user.t
+++ b/t/aggregate/live_engine_request_remote_user.t
@@ -1,5 +1,3 @@
-#!perl
-
 # This tests to make sure the REMOTE_USER environment variable is properly passed through by the engine.
 
 use strict;
diff --git a/t/aggregate/live_engine_request_uploads.t b/t/aggregate/live_engine_request_uploads.t
index 35ec9c7..5ba8f18 100644
--- a/t/aggregate/live_engine_request_uploads.t
+++ b/t/aggregate/live_engine_request_uploads.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
@@ -334,6 +332,14 @@ use Path::Class::Dir;
         if ( $ENV{CATALYST_SERVER} ) {
             skip 'Not testing for deleted file on remote server', 1;
         }
+
+        # JNAP, I added the following line in order to properly let
+        # the $env go out of scope so that the associated tempfile
+        # would be deleted.  I think somewhere Catalyst::Test closed
+        # over ENV and holds state until a new command is issues but 
+        # I can't find it.
+
+        request GET  'http://localhost/';
         ok( !-e $body->body->filename, 'Upload temp file was deleted' );
     }
 }
diff --git a/t/aggregate/live_engine_response_body.t b/t/aggregate/live_engine_response_body.t
index cd0236b..8b38189 100644
--- a/t/aggregate/live_engine_response_body.t
+++ b/t/aggregate/live_engine_response_body.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_cookies.t b/t/aggregate/live_engine_response_cookies.t
index 3bb3533..af438cd 100644
--- a/t/aggregate/live_engine_response_cookies.t
+++ b/t/aggregate/live_engine_response_cookies.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_emptybody.t b/t/aggregate/live_engine_response_emptybody.t
index 825b48a..beb83fe 100644
--- a/t/aggregate/live_engine_response_emptybody.t
+++ b/t/aggregate/live_engine_response_emptybody.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_errors.t b/t/aggregate/live_engine_response_errors.t
index b991402..1cf04c5 100644
--- a/t/aggregate/live_engine_response_errors.t
+++ b/t/aggregate/live_engine_response_errors.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_headers.t b/t/aggregate/live_engine_response_headers.t
index 0e153cf..a0663e1 100644
--- a/t/aggregate/live_engine_response_headers.t
+++ b/t/aggregate/live_engine_response_headers.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_large.t b/t/aggregate/live_engine_response_large.t
index 84b796b..05c01fc 100644
--- a/t/aggregate/live_engine_response_large.t
+++ b/t/aggregate/live_engine_response_large.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_print.t b/t/aggregate/live_engine_response_print.t
index 4e8f024..6c985b3 100644
--- a/t/aggregate/live_engine_response_print.t
+++ b/t/aggregate/live_engine_response_print.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_redirect.t b/t/aggregate/live_engine_response_redirect.t
index a01b9d0..d40d3e1 100644
--- a/t/aggregate/live_engine_response_redirect.t
+++ b/t/aggregate/live_engine_response_redirect.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_response_status.t b/t/aggregate/live_engine_response_status.t
index a37c9b6..6edee3f 100644
--- a/t/aggregate/live_engine_response_status.t
+++ b/t/aggregate/live_engine_response_status.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_setup_basics.t b/t/aggregate/live_engine_setup_basics.t
index c2b81ba..f329d44 100644
--- a/t/aggregate/live_engine_setup_basics.t
+++ b/t/aggregate/live_engine_setup_basics.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_engine_setup_plugins.t b/t/aggregate/live_engine_setup_plugins.t
index 419982b..204fd92 100644
--- a/t/aggregate/live_engine_setup_plugins.t
+++ b/t/aggregate/live_engine_setup_plugins.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_loop.t b/t/aggregate/live_loop.t
index e7b59f9..6b80879 100644
--- a/t/aggregate/live_loop.t
+++ b/t/aggregate/live_loop.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_plugin_loaded.t b/t/aggregate/live_plugin_loaded.t
index 64161aa..106f6bc 100644
--- a/t/aggregate/live_plugin_loaded.t
+++ b/t/aggregate/live_plugin_loaded.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/live_priorities.t b/t/aggregate/live_priorities.t
index bd28d25..e415827 100644
--- a/t/aggregate/live_priorities.t
+++ b/t/aggregate/live_priorities.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/meta_method_unneeded.t b/t/aggregate/meta_method_unneeded.t
index f52a9b4..5678e94 100644
--- a/t/aggregate/meta_method_unneeded.t
+++ b/t/aggregate/meta_method_unneeded.t
@@ -3,7 +3,6 @@ use warnings;
 use FindBin qw/$Bin/;
 use lib "$Bin/../lib";
 use Test::More tests => 1;
-use Test::Exception;
 use Carp ();
 
 # Doing various silly things, like for example
diff --git a/t/aggregate/unit_core_action_for.t b/t/aggregate/unit_core_action_for.t
index c0af9d3..b3f0088 100644
--- a/t/aggregate/unit_core_action_for.t
+++ b/t/aggregate/unit_core_action_for.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/unit_core_classdata.t b/t/aggregate/unit_core_classdata.t
index d054dc6..2661fc4 100644
--- a/t/aggregate/unit_core_classdata.t
+++ b/t/aggregate/unit_core_classdata.t
@@ -1,5 +1,3 @@
-#!/usr/bin/perl
-
 use strict;
 use warnings;
 use Scalar::Util qw/refaddr blessed/;
diff --git a/t/aggregate/unit_core_engine_fixenv-iis6.t b/t/aggregate/unit_core_engine_fixenv-iis6.t
index cefcd35..d2f98b0 100644
--- a/t/aggregate/unit_core_engine_fixenv-iis6.t
+++ b/t/aggregate/unit_core_engine_fixenv-iis6.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/unit_core_engine_fixenv-lighttpd.t b/t/aggregate/unit_core_engine_fixenv-lighttpd.t
index 9c71ddb..51456a5 100644
--- a/t/aggregate/unit_core_engine_fixenv-lighttpd.t
+++ b/t/aggregate/unit_core_engine_fixenv-lighttpd.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/unit_core_plugin.t b/t/aggregate/unit_core_plugin.t
index becc3c1..847195e 100644
--- a/t/aggregate/unit_core_plugin.t
+++ b/t/aggregate/unit_core_plugin.t
@@ -1,5 +1,3 @@
-#!/usr/bin/perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/unit_core_script_cgi.t b/t/aggregate/unit_core_script_cgi.t
index 697f2ad..7c4ca00 100644
--- a/t/aggregate/unit_core_script_cgi.t
+++ b/t/aggregate/unit_core_script_cgi.t
@@ -1,4 +1,3 @@
-#!/usr/bin/env perl
 use strict;
 use warnings;
 
@@ -6,14 +5,14 @@ use FindBin qw/$Bin/;
 use lib "$Bin/../lib";
 
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 
 use Catalyst::Script::CGI;
 
 local @ARGV;
-lives_ok {
+is exception {
     Catalyst::Script::CGI->new_with_options(application_name => 'TestAppToTestScripts')->run;
-} "new_with_options";
+}, undef, "new_with_options";
 shift @TestAppToTestScripts::RUN_ARGS;
 my $server = pop @TestAppToTestScripts::RUN_ARGS;
 like ref($server), qr/^Plack::Handler/, 'Is a Plack::Handler';
diff --git a/t/aggregate/unit_core_script_create.t b/t/aggregate/unit_core_script_create.t
index d492fd9..a27dc25 100644
--- a/t/aggregate/unit_core_script_create.t
+++ b/t/aggregate/unit_core_script_create.t
@@ -1,8 +1,7 @@
-#!/usr/bin/env perl
 use strict;
 use warnings;
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 
 use FindBin qw/$Bin/;
 use lib "$Bin/../lib";
@@ -41,9 +40,9 @@ use lib "$Bin/../lib";
 {
     local $TestCreateScript::help;
     local @ARGV;
-    lives_ok {
+    is exception {
         TestCreateScript->new_with_options(application_name => 'TestAppToTestScripts', helper_class => 'TestHelperClass')->run;
-    } "no argv";
+    }, undef, "no argv";
     ok $TestCreateScript::help, 'Exited with usage info';
 }
 {
@@ -51,9 +50,9 @@ use lib "$Bin/../lib";
     local @ARGV = 'foo';
     local @TestHelperClass::ARGS;
     local %TestHelperClass::p;
-    lives_ok {
+    is exception {
         TestCreateScript->new_with_options(application_name => 'TestAppToTestScripts', helper_class => 'TestHelperClass')->run;
-    } "with argv";
+    }, undef, "with argv";
     ok !$TestCreateScript::help, 'Did not exit with usage into';
     is_deeply \@TestHelperClass::ARGS, ['TestAppToTestScripts', 'foo'], 'Args correct';
     is_deeply \%TestHelperClass::p, { '.newfiles' => 1, mech => undef }, 'Params correct';
@@ -64,9 +63,9 @@ use lib "$Bin/../lib";
     local @ARGV = 'foo';
     local @TestHelperClass::ARGS;
     local %TestHelperClass::p;
-    lives_ok {
+    is exception {
         TestCreateScript->new_with_options(application_name => 'TestAppToTestScripts', helper_class => 'TestHelperClass::False')->run;
-    } "with argv";
+    }, undef, "with argv";
     ok $TestCreateScript::help, 'Did exit with usage into as mk_component returned false';
     is_deeply \@TestHelperClass::ARGS, ['TestAppToTestScripts', 'foo'], 'Args correct';
     is_deeply \%TestHelperClass::p, { '.newfiles' => 1, mech => undef }, 'Params correct';
diff --git a/t/aggregate/unit_core_script_fastcgi.t b/t/aggregate/unit_core_script_fastcgi.t
index 93f1c16..80a8068 100644
--- a/t/aggregate/unit_core_script_fastcgi.t
+++ b/t/aggregate/unit_core_script_fastcgi.t
@@ -5,7 +5,7 @@ use FindBin qw/$Bin/;
 use lib "$Bin/../lib";
 
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 
 use Catalyst::Script::FastCGI;
 
@@ -32,9 +32,9 @@ sub testOption {
 
     local @ARGV = @$argstring;
     local @TestAppToTestScripts::RUN_ARGS;
-    lives_ok {
+    is exception {
         TestFastCGIScript->new_with_options(application_name => 'TestAppToTestScripts')->run;
-    } "new_with_options";
+    }, undef, "new_with_options";
     # First element of RUN_ARGS will be the script name, which we don't care about
     shift @TestAppToTestScripts::RUN_ARGS;
 
diff --git a/t/aggregate/unit_core_script_help.t b/t/aggregate/unit_core_script_help.t
index 00d24da..e2fc4a2 100644
--- a/t/aggregate/unit_core_script_help.t
+++ b/t/aggregate/unit_core_script_help.t
@@ -1,8 +1,7 @@
-#!/usr/bin/env perl
 use strict;
 use warnings;
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 
 use FindBin qw/$Bin/;
 use lib "$Bin/../lib";
@@ -21,9 +20,9 @@ test('-?');
 sub test {
     local $TestHelpScript::help;
     local @ARGV = (@_);
-    lives_ok {
+    is exception {
         TestHelpScript->new_with_options(application_name => 'TestAppToTestScripts')->run;
-    } 'Lives';
+    }, undef, 'Lives';
     ok $TestHelpScript::help, 'Got help';
 }
 
diff --git a/t/aggregate/unit_core_script_server-without_modules.t b/t/aggregate/unit_core_script_server-without_modules.t
index 3bb7d76..0fdaa87 100644
--- a/t/aggregate/unit_core_script_server-without_modules.t
+++ b/t/aggregate/unit_core_script_server-without_modules.t
@@ -14,7 +14,7 @@ plan skip_all => "Need Test::Without::Module for this test"
     unless try { require Test::Without::Module; 1 };
 
 Test::Without::Module->import(qw(
-    Starman
+    Starman::Server
     Plack::Handler::Starman
     MooseX::Daemonize
     MooseX::Daemonize::Pid::File
@@ -24,7 +24,7 @@ Test::Without::Module->import(qw(
 require "$Bin/../aggregate/unit_core_script_server.t";
 
 Test::Without::Module->unimport(qw(
-    Starman
+    Starman::Server
     Plack::Handler::Starman
     MooseX::Daemonize
     MooseX::Daemonize::Pid::File
diff --git a/t/aggregate/unit_core_script_server.t b/t/aggregate/unit_core_script_server.t
index 7121db4..b096c42 100644
--- a/t/aggregate/unit_core_script_server.t
+++ b/t/aggregate/unit_core_script_server.t
@@ -40,7 +40,7 @@ testOption( [ qw/--port 3001/ ], ['3001', undef, opthash(port => 3001)] );
     testOption( [ qw// ], [5000, undef, opthash(port => 5000)] );
 }
 
-if (try { require Starman; 1; }) {
+if (try { require Plack::Handler::Starman; 1; }) {
     # fork           -f -fork --fork           -f --fork
     testOption( [ qw/--fork/ ], ['3000', undef, opthash(fork => 1)] );
     testOption( [ qw/-f/ ], ['3000', undef, opthash(fork => 1)] );
@@ -52,7 +52,7 @@ if (try { require MooseX::Daemonize; 1; }) {
     testOption( [ qw/--pid cat.pid/ ], ['3000', undef, opthash(pidfile => "cat.pid")] );
 }
 
-if (try { require Starman; 1; }) {
+if (try { require Plack::Handler::Starman; 1; }) {
     # keepalive      -k -keepalive --keepalive -k --keepalive
     testOption( [ qw/-k/ ], ['3000', undef, opthash(keepalive => 1)] );
     testOption( [ qw/--keepalive/ ], ['3000', undef, opthash(keepalive => 1)] );
diff --git a/t/aggregate/unit_core_scriptrunner.t b/t/aggregate/unit_core_scriptrunner.t
index 763ddec..5e44ebe 100644
--- a/t/aggregate/unit_core_scriptrunner.t
+++ b/t/aggregate/unit_core_scriptrunner.t
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 use Test::More;
 use FindBin qw/$Bin/;
-use Test::Exception;
+use Test::Fatal;
 use lib "$Bin/../lib";
 
 use_ok('Catalyst::ScriptRunner');
@@ -15,8 +15,8 @@ is Catalyst::ScriptRunner->run('ScriptTestApp', 'Baz'), 'mooCatalyst::Script::Ba
     'Script existing only in Catalyst';
 # +1 test for the params passed to new_with_options in t/lib/Catalyst/Script/Baz.pm
 
-throws_ok(sub {
+like exception {
     Catalyst::ScriptRunner->run('ScriptTestApp', 'CompileTest');
-}, qr/Couldn't load class/);
+}, qr/Couldn't load class/;
 
 done_testing;
diff --git a/t/aggregate/unit_core_setup_log.t b/t/aggregate/unit_core_setup_log.t
index e2dba17..fb73297 100644
--- a/t/aggregate/unit_core_setup_log.t
+++ b/t/aggregate/unit_core_setup_log.t
@@ -2,7 +2,6 @@ use strict;
 use warnings;
 
 use Test::More tests => 30;
-use Test::Exception;
 
 use Catalyst ();
 
diff --git a/t/aggregate/unit_core_uri_for_action.t b/t/aggregate/unit_core_uri_for_action.t
index 156f79e..4036f88 100644
--- a/t/aggregate/unit_core_uri_for_action.t
+++ b/t/aggregate/unit_core_uri_for_action.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/aggregate/unit_load_catalyst_test.t b/t/aggregate/unit_load_catalyst_test.t
index 68dfbdf..a39498b 100644
--- a/t/aggregate/unit_load_catalyst_test.t
+++ b/t/aggregate/unit_load_catalyst_test.t
@@ -8,7 +8,7 @@ use FindBin qw/$Bin/;
 use lib "$Bin/../lib";
 use Catalyst::Utils;
 use HTTP::Request::Common;
-use Test::Exception;
+use Test::Fatal;
 
 my $Class   = 'Catalyst::Test';
 my $App     = 'TestApp';
@@ -88,7 +88,7 @@ use Catalyst::Test ();
         ok( $c->stash,          "               Stash accessible" );
         ok( $c->action,         "               Action object accessible" );
         ok( $res->request,      "               Response has request object" );
-        lives_and { is( $res->request->uri, $Url) }
+        is exception { is( $res->request->uri, $Url) }, undef,
                                 "               Request object has correct url";
     } }
 }
@@ -146,12 +146,12 @@ sub customize { Catalyst::Test::_customize_request($_[0], {}, @_[1 .. $#_]) }
 use_ok('Catalyst::Test', 'TestApp', 'foobar');
 
 # Back compat test, ensure that request ignores anything which isn't a hash.
-lives_ok {
+is exception {
     request(GET('/dummy'), 'foo');
-} 'scalar additional param to request method ignored';
-lives_ok {
+}, undef, 'scalar additional param to request method ignored';
+is exception {
     request(GET('/dummy'), []);
-} 'array additional param to request method ignored';
+}, undef, 'array additional param to request method ignored';
 
 my $res = request(GET('/'));
 is $res->code, 200, 'Response code 200';
diff --git a/t/aggregate/unit_metaclass_compat_extend_non_moose_controller.t b/t/aggregate/unit_metaclass_compat_extend_non_moose_controller.t
index 568a629..07a7daa 100644
--- a/t/aggregate/unit_metaclass_compat_extend_non_moose_controller.t
+++ b/t/aggregate/unit_metaclass_compat_extend_non_moose_controller.t
@@ -12,9 +12,9 @@ use Catalyst ();
     package TestApp::Controller::Other;
     use Moose;
     use Test::More tests => 1;
-    use Test::Exception;
-    lives_ok {
+    use Test::Fatal;
+    is exception {
         extends 'TestApp::Controller::Base';
-    };
+    }, undef;
 }
 
diff --git a/t/aggregate/unit_metaclass_compat_non_moose.t b/t/aggregate/unit_metaclass_compat_non_moose.t
index 8c9c279..3efc047 100644
--- a/t/aggregate/unit_metaclass_compat_non_moose.t
+++ b/t/aggregate/unit_metaclass_compat_non_moose.t
@@ -1,4 +1,3 @@
-#!/usr/bin/env perl
 use strict;
 use warnings;
 use lib 't/lib';
diff --git a/t/aggregate/unit_metaclass_compat_non_moose_controller.t b/t/aggregate/unit_metaclass_compat_non_moose_controller.t
index 1672a18..8036be4 100644
--- a/t/aggregate/unit_metaclass_compat_non_moose_controller.t
+++ b/t/aggregate/unit_metaclass_compat_non_moose_controller.t
@@ -5,7 +5,7 @@ use FindBin;
 use lib "$FindBin::Bin/../lib";
 
 use Test::More tests => 1;
-use Test::Exception;
+use Test::Fatal;
 use TestAppNonMooseController;
 
 # Metaclass init order causes fail.
@@ -13,7 +13,7 @@ use TestAppNonMooseController;
 # f2391d17574eff81d911b97be15ea51080500003
 # after which the evil kludge in core can die in a fire.
 
-lives_ok {
+is exception {
     TestAppNonMooseController::ControllerBase->get_action_methods
-} 'Base class->get_action_methods ok when sub class initialized first';
+}, undef, 'Base class->get_action_methods ok when sub class initialized first';
 
diff --git a/t/aggregate/unit_utils_prefix.t b/t/aggregate/unit_utils_prefix.t
index 506fbc2..0351955 100644
--- a/t/aggregate/unit_utils_prefix.t
+++ b/t/aggregate/unit_utils_prefix.t
@@ -1,5 +1,3 @@
-#!/usr/bin/perl
-
 use strict;
 use warnings;
 
diff --git a/t/author/http-server.t b/t/author/http-server.t
index 7f886ca..2861c27 100644
--- a/t/author/http-server.t
+++ b/t/author/http-server.t
@@ -2,6 +2,7 @@ use strict;
 use warnings;
 
 use Test::More tests => 1;
+use Test::TCP;
 
 use File::Path;
 use FindBin;
@@ -96,7 +97,7 @@ if ($^O eq 'MSWin32') {
 sub wait_port_timeout {
     my ($port, $timeout) = @_;
 
-    wait_port($port, 0.1, $timeout * 10) and return;
+    wait_port($port, $timeout * 10) and return;
 
     die "Server did not start within $timeout seconds";
 }
diff --git a/t/author/spelling.t b/t/author/spelling.t
index 37cea27..b4c5119 100644
--- a/t/author/spelling.t
+++ b/t/author/spelling.t
@@ -19,7 +19,8 @@ add_stopwords(qw(
     inline INLINE plugins cpanfile
     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
+    UTF async codebase dev filenames params MyMiddleware
+    JSON POSTed RESTful configuation performant subref actionrole
     Andreas
     Ashton
     Axel
diff --git a/t/author/unicode_plugin_nested_params.t b/t/author/unicode_plugin_nested_params.t
index 11e884e..f9f47c6 100644
--- a/t/author/unicode_plugin_nested_params.t
+++ b/t/author/unicode_plugin_nested_params.t
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use Test::More;
diff --git a/t/content_negotiation.t b/t/content_negotiation.t
new file mode 100644
index 0000000..559a370
--- /dev/null
+++ b/t/content_negotiation.t
@@ -0,0 +1,130 @@
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use FindBin;
+use Test::More;
+use HTTP::Request::Common;
+use JSON::MaybeXS;
+
+use lib "$FindBin::Bin/lib";
+use Catalyst::Test 'TestContentNegotiation';
+
+{
+  ok my $req = POST '/',
+     Content_Type => 'application/json',
+     Content => encode_json +{message=>'test'};
+
+  ok my $res = request $req;
+
+  is $res->content, 'is_json1';
+}
+
+{
+  ok my $req = POST '/', [a=>1,b=>2];
+  ok my $res = request $req;
+
+  is $res->content, 'is_urlencoded1';
+}
+
+{
+  ok my $path = TestContentNegotiation->path_to(qw/share file.txt/);
+  ok my $req = POST '/',
+    Content_Type => 'form-data',
+    Content =>  [a=>1, b=>2, file=>["$path"]];
+
+  ok my $res = request $req;
+
+  is $res->content, 'is_multipart1';
+}
+
+{
+  ok my $req = POST '/under',
+     Content_Type => 'application/json',
+     Content => encode_json +{message=>'test'};
+
+  ok my $res = request $req;
+
+  is $res->content, 'is_json2';
+}
+
+{
+  ok my $req = POST '/under', [a=>1,b=>2];
+  ok my $res = request $req;
+
+  is $res->content, 'is_urlencoded2';
+}
+
+{
+  ok my $path = TestContentNegotiation->path_to(qw/share file.txt/);
+  ok my $req = POST '/under',
+    Content_Type => 'form-data',
+    Content =>  [a=>1, b=>2, file=>["$path"]];
+
+  ok my $res = request $req;
+
+  is $res->content, 'is_multipart2';
+}
+
+{
+  ok my $req = POST '/is_more_than_one_1',
+    Content =>  [a=>1, b=>2];
+
+  ok my $res = request $req;
+
+  is $res->content, 'formdata1';
+}
+
+{
+  ok my $req = POST '/is_more_than_one_2',
+    Content =>  [a=>1, b=>2];
+
+  ok my $res = request $req;
+
+  is $res->content, 'formdata2';
+}
+
+{
+  ok my $req = POST '/is_more_than_one_3',
+    Content =>  [a=>1, b=>2];
+
+  ok my $res = request $req;
+
+  is $res->content, 'formdata3';
+}
+
+{
+  ok my $path = TestContentNegotiation->path_to(qw/share file.txt/);
+  ok my $req = POST '/is_more_than_one_1',
+    Content_Type => 'form-data',
+    Content =>  [a=>1, b=>2, file=>["$path"]];
+
+  ok my $res = request $req;
+
+  is $res->content, 'formdata1';
+}
+
+{
+  ok my $path = TestContentNegotiation->path_to(qw/share file.txt/);
+  ok my $req = POST '/is_more_than_one_2',
+    Content_Type => 'form-data',
+    Content =>  [a=>1, b=>2, file=>["$path"]];
+
+  ok my $res = request $req;
+
+  is $res->content, 'formdata2';
+}
+
+{
+  ok my $path = TestContentNegotiation->path_to(qw/share file.txt/);
+  ok my $req = POST '/is_more_than_one_3',
+    Content_Type => 'form-data',
+    Content =>  [a=>1, b=>2, file=>["$path"]];
+
+  ok my $res = request $req;
+
+  is $res->content, 'formdata3';
+}
+
+done_testing;
diff --git a/t/custom_exception_class_simple.t b/t/custom_exception_class_simple.t
index 24983fa..27e4516 100644
--- a/t/custom_exception_class_simple.t
+++ b/t/custom_exception_class_simple.t
@@ -1,20 +1,18 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use FindBin qw/$Bin/;
 use lib "$Bin/lib";
 use Test::More tests => 2;
-use Test::Exception;
+use Test::Fatal;
 
-lives_ok {
+is exception {
     require TestAppClassExceptionSimpleTest;
-} 'Can load application';
+}, undef, 'Can load application';
 
 
-lives_ok {
+is exception {
     Catalyst::Exception->throw
-} 'throw is properly stubbed out';
+}, undef, 'throw is properly stubbed out';
 
 
 
diff --git a/t/data_handler.t b/t/data_handler.t
new file mode 100644
index 0000000..0d4af33
--- /dev/null
+++ b/t/data_handler.t
@@ -0,0 +1,34 @@
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use FindBin;
+use Test::More;
+use HTTP::Request::Common;
+use JSON::MaybeXS;
+
+use lib "$FindBin::Bin/lib";
+use Catalyst::Test 'TestDataHandlers';
+
+ok my($res, $c) = ctx_request('/');
+
+{
+  ok my $message = 'helloworld';
+  ok my $post = encode_json +{message=>$message};
+  ok my $req = POST $c->uri_for_action('/test_json'),
+     Content_Type => 'application/json',
+     Content => $post;
+
+  ok my $response = request $req, 'got a response from a catalyst controller';
+  is $response->content, $message, 'expected content body';
+}
+
+{
+  ok my $req = POST $c->uri_for_action('/test_nested_for'), [ 'nested.value' => 'expected' ];
+  ok my $response = request $req, 'got a response from a catalyst controller';
+  is $response->content, 'expected', 'expected content body';
+}
+
+
+done_testing;
diff --git a/t/dead_load_bad_args.t b/t/dead_load_bad_args.t
index d80195f..98b566c 100644
--- a/t/dead_load_bad_args.t
+++ b/t/dead_load_bad_args.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 use lib 't/lib';
diff --git a/t/dead_load_multiple_chained_attributes.t b/t/dead_load_multiple_chained_attributes.t
index b870a75..4382141 100644
--- a/t/dead_load_multiple_chained_attributes.t
+++ b/t/dead_load_multiple_chained_attributes.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 use lib 't/lib';
diff --git a/t/dead_no_unknown_error.t b/t/dead_no_unknown_error.t
index 47b635f..fd9f6b8 100755
--- a/t/dead_no_unknown_error.t
+++ b/t/dead_no_unknown_error.t
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use FindBin qw/$Bin/;
diff --git a/t/dead_recursive_chained_attributes.t b/t/dead_recursive_chained_attributes.t
index 77b9bcd..c2971de 100644
--- a/t/dead_recursive_chained_attributes.t
+++ b/t/dead_recursive_chained_attributes.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 use lib 't/lib';
diff --git a/t/deprecated.t b/t/deprecated.t
index 307181b..9e5579e 100644
--- a/t/deprecated.t
+++ b/t/deprecated.t
@@ -1,5 +1,3 @@
-#!/usr/bin/perl
-
 use strict;
 use warnings;
 use FindBin qw/$Bin/;
diff --git a/t/lib/Catalyst/Plugin/Test/MangleDollarUnderScore.pm b/t/lib/Catalyst/Plugin/Test/MangleDollarUnderScore.pm
index 94a5184..32c304d 100644
--- a/t/lib/Catalyst/Plugin/Test/MangleDollarUnderScore.pm
+++ b/t/lib/Catalyst/Plugin/Test/MangleDollarUnderScore.pm
@@ -2,11 +2,12 @@ package Catalyst::Plugin::Test::MangleDollarUnderScore;
 use strict;
 use warnings;
 
+# FIXME - should proably use utf8??
 our $VERSION = 0.1; # Make is_class_loaded happy
 
-# Class::MOP::load_class($_) can hurt you real hard.
+# Class::Load::load_class($_) can hurt you real hard.
 BEGIN { $_ = q{
-mst sayeth, Class::MOP::load_class($_) will ruin your life
+mst sayeth, Class::Load::load_class($_) will ruin your life
 rafl spokeh "i ♥ my $_"',
 and verrily forsooth, t0m made tests
 and yea, there was fail' }; }
diff --git a/t/lib/TestApp.pm b/t/lib/TestApp.pm
index b06880c..bb88a73 100644
--- a/t/lib/TestApp.pm
+++ b/t/lib/TestApp.pm
@@ -11,6 +11,7 @@ use Catalyst qw/
     +TestApp::Role
 /;
 use Catalyst::Utils;
+use Class::Load 'try_load_class';
 
 use Moose;
 use namespace::autoclean;
@@ -59,7 +60,7 @@ TestApp->config(
 # above ->setup so we have some generated methods to be double sure.
 has an_attribute_before_we_change_base_classes => ( is => 'ro');
 
-if ($::setup_leakchecker && eval { Class::MOP::load_class('CatalystX::LeakChecker'); 1 }) {
+if ($::setup_leakchecker && try_load_class('CatalystX::LeakChecker')) {
     with 'CatalystX::LeakChecker';
 
     has leaks => (
diff --git a/t/lib/TestApp/Controller/Fork.pm b/t/lib/TestApp/Controller/Fork.pm
index 086d149..2a91193 100644
--- a/t/lib/TestApp/Controller/Fork.pm
+++ b/t/lib/TestApp/Controller/Fork.pm
@@ -1,4 +1,3 @@
-#!/usr/bin/perl
 # Fork.pm 
 # Copyright (c) 2006 Jonathan Rockway <jrockway at cpan.org>
 
diff --git a/t/lib/TestApp/View/Dump.pm b/t/lib/TestApp/View/Dump.pm
index dff41e8..016df81 100644
--- a/t/lib/TestApp/View/Dump.pm
+++ b/t/lib/TestApp/View/Dump.pm
@@ -39,6 +39,8 @@ sub process {
     # Remove context from reference if needed
     my $context = delete $reference->{_context};
 
+    my $env = delete $reference->{env};
+
     if (my $log = $reference->{_log}) {
         $log->clear_psgi if ($log->can('psgienv'));
     }
@@ -62,6 +64,8 @@ sub process {
             $reference->{_body} = $body;
         }
 
+        if($env) { $reference->{env} = $env }
+
         return 1;
     }
 
diff --git a/t/lib/TestApp/View/Dump/Request.pm b/t/lib/TestApp/View/Dump/Request.pm
index 97926ec..991eeca 100644
--- a/t/lib/TestApp/View/Dump/Request.pm
+++ b/t/lib/TestApp/View/Dump/Request.pm
@@ -6,7 +6,7 @@ use base qw[TestApp::View::Dump];
 sub process {
     my ( $self, $c ) = @_;
     my $r = $c->request;
-    local $r->{env};
+    #local $r->{env};
     return $self->SUPER::process( $c, $r );
 }
 
diff --git a/t/lib/TestAppPluginWithConstructor.pm b/t/lib/TestAppPluginWithConstructor.pm
index 3d0d552..faa1f9c 100644
--- a/t/lib/TestAppPluginWithConstructor.pm
+++ b/t/lib/TestAppPluginWithConstructor.pm
@@ -1,7 +1,7 @@
 # See t/plugin_new_method_backcompat.t
 package TestAppPluginWithConstructor;
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 use Catalyst qw/+TestPluginWithConstructor/;
 use Moose;
 extends qw/Catalyst/;
@@ -9,9 +9,9 @@ extends qw/Catalyst/;
 __PACKAGE__->setup;
 our $MODIFIER_FIRED = 0;
 
-lives_ok {
+is exception {
     before 'dispatch' => sub { $MODIFIER_FIRED = 1 }
-} 'Can apply method modifier';
+}, undef, 'Can apply method modifier';
 no Moose;
 
 our $IS_IMMUTABLE_YET = __PACKAGE__->meta->is_immutable;
diff --git a/t/lib/TestContentNegotiation.pm b/t/lib/TestContentNegotiation.pm
new file mode 100644
index 0000000..e126dcd
--- /dev/null
+++ b/t/lib/TestContentNegotiation.pm
@@ -0,0 +1,13 @@
+package TestContentNegotiation;
+
+use Moose;
+use Catalyst;
+
+extends 'Catalyst';
+
+__PACKAGE__->config(
+  'Controller::Root', { namespace => '' },
+);
+
+__PACKAGE__->setup;
+
diff --git a/t/lib/TestContentNegotiation/Controller/Root.pm b/t/lib/TestContentNegotiation/Controller/Root.pm
new file mode 100644
index 0000000..60fe6f7
--- /dev/null
+++ b/t/lib/TestContentNegotiation/Controller/Root.pm
@@ -0,0 +1,50 @@
+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_json1') }
+    sub is_urlencoded : Chained('start') PathPart('') Consumes('application/x-www-form-urlencoded') Args(0) { pop->res->body('is_urlencoded1') }
+    sub is_multipart  : Chained('start') PathPart('') Consumes('multipart/form-data') Args(0) { pop->res->body('is_multipart1') }
+      
+    sub under :Chained('start') CaptureArgs(0) { }
+
+      sub is_json_under       : Chained('under') PathPart('') Consumes(JSON) Args(0) { pop->res->body('is_json2') }
+      sub is_urlencoded_under : Chained('under') PathPart('') Consumes(UrlEncoded) Args(0) { pop->res->body('is_urlencoded2') }
+      sub is_multipart_under  : Chained('under') PathPart('') Consumes(Multipart) Args(0) { pop->res->body('is_multipart2') }
+
+      ## Or allow more than one type
+    
+    sub multi :Chained('start') PathPart('') CaptureArgs(0) { }
+      
+    sub is_more_than_one_1
+      : Chained('multi') 
+      : Consumes('application/x-www-form-urlencoded')
+      : Consumes('multipart/form-data')
+      : Args(0)
+    {
+      pop->res->body('formdata1');
+    }
+
+    sub is_more_than_one_2
+      : Chained('multi') 
+      : Consumes('HTMLForm')
+      : Args(0)
+    {
+      pop->res->body('formdata2');
+    }
+
+    sub is_more_than_one_3
+      : Chained('multi') 
+      : Consumes('application/x-www-form-urlencoded,multipart/form-data')
+      : Args(0)
+    {
+      pop->res->body('formdata3');
+    }
+
+
+__PACKAGE__->meta->make_immutable;
diff --git a/t/lib/TestContentNegotiation/share/file.txt b/t/lib/TestContentNegotiation/share/file.txt
new file mode 100644
index 0000000..ab8e0eb
--- /dev/null
+++ b/t/lib/TestContentNegotiation/share/file.txt
@@ -0,0 +1,50 @@
+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;
diff --git a/t/lib/TestDataHandlers.pm b/t/lib/TestDataHandlers.pm
new file mode 100644
index 0000000..0c52778
--- /dev/null
+++ b/t/lib/TestDataHandlers.pm
@@ -0,0 +1,9 @@
+package TestDataHandlers;
+
+use Catalyst;
+
+__PACKAGE__->config(
+  'Controller::Root', { namespace => '' }
+);
+
+__PACKAGE__->setup;
diff --git a/t/lib/TestDataHandlers/Controller/Root.pm b/t/lib/TestDataHandlers/Controller/Root.pm
new file mode 100644
index 0000000..3aa45f4
--- /dev/null
+++ b/t/lib/TestDataHandlers/Controller/Root.pm
@@ -0,0 +1,15 @@
+package TestDataHandlers::Controller::Root;
+
+use base 'Catalyst::Controller';
+
+sub test_json :Local {
+    my ($self, $c) = @_;
+    $c->res->body($c->req->body_data->{message});
+}
+
+sub test_nested_for :Local {
+    my ($self, $c) = @_;
+    $c->res->body($c->req->body_data->{nested}->{value});
+}
+
+1;
diff --git a/t/lib/TestFromPSGI.pm b/t/lib/TestFromPSGI.pm
new file mode 100644
index 0000000..31f486d
--- /dev/null
+++ b/t/lib/TestFromPSGI.pm
@@ -0,0 +1,12 @@
+package TestFromPSGI;
+
+use Moose;
+use Catalyst;
+
+__PACKAGE__->config(
+  'Controller::Root', { namespace => '' },
+  use_hash_multivalue_in_request => 1,
+);
+
+__PACKAGE__->setup;
+
diff --git a/t/lib/TestFromPSGI/Controller/Root.pm b/t/lib/TestFromPSGI/Controller/Root.pm
new file mode 100644
index 0000000..1f82453
--- /dev/null
+++ b/t/lib/TestFromPSGI/Controller/Root.pm
@@ -0,0 +1,56 @@
+package TestFromPSGI::Controller::Root;
+
+use Moose;
+use MooseX::MethodAttributes;
+
+extends 'Catalyst::Controller';
+
+sub test_psgi_keys :Local {
+  my ($self, $c) = @_;
+  $c->res->body('ok');
+}
+
+sub from_psgi_array : Local {
+  my ($self, $c) = @_;
+  my $res = sub {
+    my ($env) = @_;
+    return [200, ['Content-Type'=>'text/plain'],
+      [qw/hello world today/]];
+  }->($c->req->env);
+
+  $c->res->from_psgi_response($res);
+}
+
+sub from_psgi_code : Local {
+  my ($self, $c) = @_;
+
+  my $res = sub {
+    my ($env) = @_;
+    return sub {
+      my $responder = shift;
+      return $responder->([200, ['Content-Type'=>'text/plain'],
+        [qw/hello world today2/]]);
+    };
+  }->($c->req->env);
+
+  $c->res->from_psgi_response($res);
+}
+
+sub from_psgi_code_itr : Local {
+  my ($self, $c) = @_;
+  my $res = sub {
+    my ($env) = @_;
+    return sub {
+      my $responder = shift;
+      my $writer = $responder->([200, ['Content-Type'=>'text/plain']]);
+      $writer->write('hello');
+      $writer->write('world');
+      $writer->write('today3');
+      $writer->close;
+    };
+  }->($c->req->env);
+
+  $c->res->from_psgi_response($res);
+}
+
+__PACKAGE__->meta->make_immutable;
diff --git a/t/lib/TestMiddleware.pm b/t/lib/TestMiddleware.pm
new file mode 100644
index 0000000..326f1be
--- /dev/null
+++ b/t/lib/TestMiddleware.pm
@@ -0,0 +1,38 @@
+package TestMiddleware;
+
+use Moose;
+use Plack::Middleware::Static;
+use Plack::App::File;
+use Catalyst;
+
+extends 'Catalyst';
+
+my $static = Plack::Middleware::Static->new(
+  path => qr{^/static/}, root => TestMiddleware->path_to('share'));
+
+__PACKAGE__->config(
+  'Controller::Root', { namespace => '' },
+  'psgi_middleware', [
+    'Head',
+    $static,
+    'Static', { path => qr{^/static2/}, root => TestMiddleware->path_to('share') },
+    'Runtime',
+    '+TestMiddleware::Custom', { path => qr{^/static3/}, root => TestMiddleware->path_to('share') },
+    sub {
+      my $app = shift;
+      return sub {
+        my $env = shift;
+        if($env->{PATH_INFO} =~m/forced/) {
+          Plack::App::File->new(file=>TestMiddleware->path_to(qw/share static forced.txt/))
+            ->call($env);
+        } else {
+          return $app->($env);
+        }
+      },
+    },
+
+  ],
+);
+
+__PACKAGE__->setup;
+
diff --git a/t/lib/TestMiddleware/Controller/Root.pm b/t/lib/TestMiddleware/Controller/Root.pm
new file mode 100644
index 0000000..7c116a5
--- /dev/null
+++ b/t/lib/TestMiddleware/Controller/Root.pm
@@ -0,0 +1,13 @@
+package TestMiddleware::Controller::Root;
+
+use Moose;
+use MooseX::MethodAttributes;
+
+extends 'Catalyst::Controller';
+
+sub default : Path { }
+sub welcome : Path(welcome) {
+  pop->res->body('Welcome to Catalyst');
+}
+
+__PACKAGE__->meta->make_immutable;
diff --git a/t/lib/TestMiddleware/Custom.pm b/t/lib/TestMiddleware/Custom.pm
new file mode 100644
index 0000000..580a66e
--- /dev/null
+++ b/t/lib/TestMiddleware/Custom.pm
@@ -0,0 +1,8 @@
+package TestMiddleware::Custom;
+
+use strict;
+use warnings;
+
+use parent qw/Plack::Middleware::Static/;
+
+1;
diff --git a/t/lib/TestMiddleware/share/static/forced.txt b/t/lib/TestMiddleware/share/static/forced.txt
new file mode 100644
index 0000000..47b6118
--- /dev/null
+++ b/t/lib/TestMiddleware/share/static/forced.txt
@@ -0,0 +1 @@
+forced message
diff --git a/t/lib/TestMiddleware/share/static/message.txt b/t/lib/TestMiddleware/share/static/message.txt
new file mode 100644
index 0000000..9bdf9d1
--- /dev/null
+++ b/t/lib/TestMiddleware/share/static/message.txt
@@ -0,0 +1 @@
+static message
diff --git a/t/lib/TestMiddleware/share/static2/message2.txt b/t/lib/TestMiddleware/share/static2/message2.txt
new file mode 100644
index 0000000..9bdf9d1
--- /dev/null
+++ b/t/lib/TestMiddleware/share/static2/message2.txt
@@ -0,0 +1 @@
+static message
diff --git a/t/lib/TestMiddleware/share/static3/message3.txt b/t/lib/TestMiddleware/share/static3/message3.txt
new file mode 100644
index 0000000..9bdf9d1
--- /dev/null
+++ b/t/lib/TestMiddleware/share/static3/message3.txt
@@ -0,0 +1 @@
+static message
diff --git a/t/live_fork.t b/t/live_fork.t
index 9c053e3..3a2dc3c 100644
--- a/t/live_fork.t
+++ b/t/live_fork.t
@@ -1,4 +1,3 @@
-#!/usr/bin/perl
 # live_fork.t
 # Copyright (c) 2006 Jonathan Rockway <jrockway at cpan.org>
 
diff --git a/t/live_stats.t b/t/live_stats.t
index a8c9c13..d47b50b 100644
--- a/t/live_stats.t
+++ b/t/live_stats.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/more-psgi-compat.t b/t/more-psgi-compat.t
new file mode 100644
index 0000000..a176472
--- /dev/null
+++ b/t/more-psgi-compat.t
@@ -0,0 +1,53 @@
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use FindBin;
+use Test::More;
+use HTTP::Request::Common;
+
+use lib "$FindBin::Bin/lib";
+use Catalyst::Test 'TestFromPSGI';
+
+{
+  ok my $response = request GET '/from_psgi_array',
+    'got welcome from a catalyst controller';
+
+  is $response->content, 'helloworldtoday',
+    'expected content body /from_psgi_array';
+}
+
+{
+  ok my $response = request GET '/from_psgi_code',
+    'got welcome from a catalyst controller';
+
+  is $response->content, 'helloworldtoday2',
+    'expected content body /from_psgi_code';
+}
+
+{
+  ok my $response = request GET '/from_psgi_code_itr',
+    'got welcome from a catalyst controller';
+
+  is $response->content, 'helloworldtoday3',
+    'expected content body /from_psgi_code_itr';
+}
+
+{
+  ok my($res, $c) = ctx_request(POST '/test_psgi_keys?a=1&b=2', [c=>3,d=>4]);
+
+  ok $c->req->env->{"psgix.input.buffered"}, "input is buffered";
+
+  is $c->req->parameters->get('c'), 3;
+  is $c->req->parameters->get('d'), 4;
+  is $c->req->parameters->get('a'), 1;
+  is $c->req->parameters->get('b'), 2;
+
+  is $c->req->body_parameters->get('c'), 3;
+  is $c->req->body_parameters->get('d'), 4;
+  is $c->req->query_parameters->get('a'), 1;
+  is $c->req->query_parameters->get('b'), 2;
+}
+
+done_testing;
diff --git a/t/optional_apache-cgi-rewrite.pl b/t/optional_apache-cgi-rewrite.pl
index 8ce1d6b..abf467e 100755
--- a/t/optional_apache-cgi-rewrite.pl
+++ b/t/optional_apache-cgi-rewrite.pl
@@ -1,5 +1,3 @@
-#!perl
-
 # Run all tests against CGI mode under Apache
 #
 # Note, to get this to run properly, you may need to give it the path to your
diff --git a/t/optional_apache-cgi.pl b/t/optional_apache-cgi.pl
index fd2d9a6..f81c7c4 100755
--- a/t/optional_apache-cgi.pl
+++ b/t/optional_apache-cgi.pl
@@ -1,5 +1,3 @@
-#!perl
-
 # Run all tests against CGI mode under Apache
 #
 # Note, to get this to run properly, you may need to give it the path to your
diff --git a/t/optional_apache-fastcgi-non-root.pl b/t/optional_apache-fastcgi-non-root.pl
index 23ea42d..bc1b2a5 100755
--- a/t/optional_apache-fastcgi-non-root.pl
+++ b/t/optional_apache-fastcgi-non-root.pl
@@ -1,5 +1,3 @@
-#!perl
-
 # Run all tests against FastCGI mode under Apache
 #
 # Note, to get this to run properly, you may need to give it the path to your
diff --git a/t/optional_apache-fastcgi.pl b/t/optional_apache-fastcgi.pl
index 715a623..95c3702 100755
--- a/t/optional_apache-fastcgi.pl
+++ b/t/optional_apache-fastcgi.pl
@@ -1,5 +1,3 @@
-#!perl
-
 # Run all tests against FastCGI mode under Apache
 #
 # Note, to get this to run properly, you may need to give it the path to your
diff --git a/t/optional_lighttpd-fastcgi-non-root.t b/t/optional_lighttpd-fastcgi-non-root.t
index db191f3..1a59e29 100644
--- a/t/optional_lighttpd-fastcgi-non-root.t
+++ b/t/optional_lighttpd-fastcgi-non-root.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/optional_lighttpd-fastcgi.t b/t/optional_lighttpd-fastcgi.t
index 98567f7..07a5828 100644
--- a/t/optional_lighttpd-fastcgi.t
+++ b/t/optional_lighttpd-fastcgi.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/optional_memleak.t b/t/optional_memleak.t
index ba193a3..ca4cbcf 100644
--- a/t/optional_memleak.t
+++ b/t/optional_memleak.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/optional_stress.t b/t/optional_stress.t
index c4ccee2..9e73cc5 100644
--- a/t/optional_stress.t
+++ b/t/optional_stress.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/optional_threads.t b/t/optional_threads.t
index 9ed878f..c45e66e 100644
--- a/t/optional_threads.t
+++ b/t/optional_threads.t
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 
diff --git a/t/plack-middleware.t b/t/plack-middleware.t
new file mode 100644
index 0000000..4cc3e72
--- /dev/null
+++ b/t/plack-middleware.t
@@ -0,0 +1,57 @@
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use FindBin;
+use Test::More;
+use HTTP::Request::Common;
+
+use lib "$FindBin::Bin/lib";
+use Catalyst::Test 'TestMiddleware';
+
+ok my($res, $c) = ctx_request('/');
+
+{
+  ok my $response = request GET $c->uri_for_action('/welcome'),
+    'got welcome from a catalyst controller';
+
+  is $response->content, 'Welcome to Catalyst',
+    'expected content body';
+}
+
+{
+  ok my $response = request GET $c->uri_for('/static/message.txt'),
+    'got welcome from a catalyst controller';
+
+  like $response->content, qr'static message',
+    'expected content body';
+}
+
+{
+  ok my $response = request GET $c->uri_for('/static2/message2.txt'),
+    'got welcome from a catalyst controller';
+
+  like $response->content, qr'static message',
+    'expected content body';
+}
+
+{
+  ok my $response = request GET $c->uri_for('/static3/message3.txt'),
+    'got welcome from a catalyst controller';
+
+  like $response->content, qr'static message',
+    'expected content body';
+}
+
+{
+  ok my $response = request GET $c->uri_for('/forced'),
+    'got welcome from a catalyst controller';
+
+  like $response->content, qr'forced message',
+    'expected content body';
+
+  ok $response->headers->{"x-runtime"}, "Got value for expected middleware";
+}
+
+done_testing;
diff --git a/t/plugin_new_method_backcompat.t b/t/plugin_new_method_backcompat.t
index 07de6d9..28455fb 100644
--- a/t/plugin_new_method_backcompat.t
+++ b/t/plugin_new_method_backcompat.t
@@ -9,7 +9,6 @@
 
 # Also tests method modifiers and etc in MyApp.pm still work as expected.
 use Test::More;
-use Test::Exception;
 use Moose::Util qw/find_meta/;
 use FindBin;
 use lib "$FindBin::Bin/lib";
diff --git a/t/psgi_file_testapp_engine_plackup_compat.t b/t/psgi_file_testapp_engine_plackup_compat.t
index 3578c6c..4f5a2ea 100644
--- a/t/psgi_file_testapp_engine_plackup_compat.t
+++ b/t/psgi_file_testapp_engine_plackup_compat.t
@@ -4,7 +4,7 @@ use FindBin qw/$Bin/;
 use lib "$Bin/lib";
 
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 use Plack::Test;
 use TestApp;
 use HTTP::Request::Common;
@@ -23,7 +23,7 @@ like $warning, qr/You are running Catalyst\:\:Engine\:\:PSGI/,
 
 test_psgi $app, sub {
     my $cb = shift;
-    lives_ok {
+    is exception {
         my $TIMEOUT_IN_SECONDS = 5;
         local $SIG{ALRM} = sub { die "alarm\n" };
         alarm($TIMEOUT_IN_SECONDS);
@@ -34,7 +34,7 @@ test_psgi $app, sub {
 
         alarm(0);
         1
-    } q{app didn't die or timeout};
+    }, undef, q{app didn't die or timeout};
 };
 
 done_testing;
diff --git a/t/unicode_plugin_config.t b/t/unicode_plugin_config.t
index 513c978..37c5c6b 100644
--- a/t/unicode_plugin_config.t
+++ b/t/unicode_plugin_config.t
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use Test::More;
diff --git a/t/unicode_plugin_live.t b/t/unicode_plugin_live.t
index de810aa..87d9061 100644
--- a/t/unicode_plugin_live.t
+++ b/t/unicode_plugin_live.t
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use Test::More;
diff --git a/t/unicode_plugin_no_encoding.t b/t/unicode_plugin_no_encoding.t
index 8034c38..7b562f8 100644
--- a/t/unicode_plugin_no_encoding.t
+++ b/t/unicode_plugin_no_encoding.t
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use Test::More;
diff --git a/t/unicode_plugin_request_decode.t b/t/unicode_plugin_request_decode.t
index a3bab97..c3b7171 100644
--- a/t/unicode_plugin_request_decode.t
+++ b/t/unicode_plugin_request_decode.t
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
 use Test::More tests => 5 * 5;
diff --git a/t/unit_core_script_test.t b/t/unit_core_script_test.t
index 1328bde..61db9c0 100644
--- a/t/unit_core_script_test.t
+++ b/t/unit_core_script_test.t
@@ -6,7 +6,7 @@ use FindBin qw/$Bin/;
 use lib "$Bin/lib";
 
 use Test::More;
-use Test::Exception;
+use Test::Fatal;
 
 use Catalyst::Script::Test;
 use File::Temp qw/tempfile/;
@@ -28,9 +28,9 @@ sub run_test {
     {
         local @ARGV = ($url);
         my $i;
-        lives_ok {
+        is exception {
             $i = Catalyst::Script::Test->new_with_options(application_name => 'TestApp');
-        } "new_with_options";
+        }, undef, "new_with_options";
         ok $i;
         my $saved;
         open( $saved, '>&'. STDOUT->fileno )
diff --git a/t/unit_stats.t b/t/unit_stats.t
index 676f354..09778c9 100644
--- a/t/unit_stats.t
+++ b/t/unit_stats.t
@@ -1,5 +1,3 @@
-#!/usr/bin/perl
-
 use strict;
 use warnings;
 
diff --git a/t/unit_utils_load_class.t b/t/unit_utils_load_class.t
index 881b1ff..47994c5 100644
--- a/t/unit_utils_load_class.t
+++ b/t/unit_utils_load_class.t
@@ -1,10 +1,8 @@
-#!/usr/bin/perl
-
 use strict;
 use warnings;
 
 use Test::More tests => 18;
-use Class::MOP;
+use Class::Load 'is_class_loaded';
 
 use lib "t/lib";
 
@@ -21,11 +19,11 @@ $SIG{__WARN__} = sub {
     $warnings++;
 };
 
-ok( !Class::MOP::is_class_loaded("TestApp::View::Dump"), "component not yet loaded" );
+ok( !is_class_loaded("TestApp::View::Dump"), "component not yet loaded" );
 
 Catalyst::Utils::ensure_class_loaded("TestApp::View::Dump");
 
-ok( Class::MOP::is_class_loaded("TestApp::View::Dump"), "loaded ok" );
+ok( is_class_loaded("TestApp::View::Dump"), "loaded ok" );
 is( $warnings, 0, "no warnings emitted" );
 
 $warnings = 0;
@@ -33,10 +31,10 @@ $warnings = 0;
 Catalyst::Utils::ensure_class_loaded("TestApp::View::Dump");
 is( $warnings, 0, "calling again doesn't reaload" );
 
-ok( !Class::MOP::is_class_loaded("TestApp::View::Dump::Request"), "component not yet loaded" );
+ok( !is_class_loaded("TestApp::View::Dump::Request"), "component not yet loaded" );
 
 Catalyst::Utils::ensure_class_loaded("TestApp::View::Dump::Request");
-ok( Class::MOP::is_class_loaded("TestApp::View::Dump::Request"), "loaded ok" );
+ok( is_class_loaded("TestApp::View::Dump::Request"), "loaded ok" );
 
 is( $warnings, 0, "calling again doesn't reaload" );
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libcatalyst-perl.git



More information about the Pkg-perl-cvs-commits mailing list