merged
John Napiorkowski [Thu, 29 Oct 2015 15:13:48 +0000 (10:13 -0500)]
1  2 
Changes
lib/Catalyst.pm
t/aggregate/unit_core_uri_for.t

diff --combined Changes
+++ b/Changes
  # This file documents the revision history for Perl extension Catalyst.
  
 +5.90102 - 2015-10-29
 +  - Better warnings when there's an error reading the psgi.input (billmosley++)
 +  - Fixed spurious warnings in uri_for when using no arguments (melmothx++ and 
 +    paultcochrane++)
 +  - Documentation improvements (paultcochrane++)
++  - Improvements to 'search_extra' configuration and tests around using 
++    uri_for as a class method (cngarrison++)
 +
 +5.90101 - 2015-09-04
 +  - Fixed a regression introduced in the last release which caused test
 +    case failure when using a version of Perl 5.14 or older.
 +
 +5.90100 - 2015-08-24
 +  - Document using namespace::autoclean with controllers that have actions
 +    with type constraints.
 +  - Look for type constraints in super classes and consumed roles.
 +  - Change the way the stash middleware works to no longer localize $psgi_env.
 +  - If you delegate control to a sub Catalyst application, that application
 +    may now return information to the parent application via the stash.
 +  - Fix for RT#106373 (Issue when you try to install and also have an old
 +    version of Test::Mechanize::WWW::Catalyst)
 +
 +5.90097 - 2015-07-28
 +  - $c->uri_for now defines a final argument for setting the URL fragment
 +  /URL anchor.  This is now the canonical approach to setting a fragment
 +  via uri_for.
 +  - Reverted how we treat $c->uri_for($path) where $path is a string.  When
 +    we introduced the UTF-8 work we started encoding stringy paths, which
 +    breaks code that did not expect that.  We now consider stringy $path to
 +    be 'expert' mode and you are expected to perform all nessary encoding.
 +
 +5.90096 - 2015-07-27
 +  - Fixed regression introduced in previous release that prevented a URI
 +    fragment from getting properly encoded.  Added more tests around this
 +    to define behavior better.
 +
 +5.90095 - 2015-07-27
 +  - Minor test case tweak that I hope solve some minor hiesenfails reported
 +    on CPAN testers.
 +  - (https://github.com/perl-catalyst/catalyst-runtime/pull/109) added som
 +    additional directions to how to setup a development sandbox
 +  - (https://github.com/perl-catalyst/catalyst-runtime/pull/108) fix bug in
 +    encoding where URI fragment seperator '#' in ->uri_for would get encoded.
 +
 +5.90094 - 2015-07-24
 +  - When there is a multipart POST request and the parts have extended
 +    HTTP headers, try harder to decode and squeeze a meaningful value
 +    out of it before giving up and crying.  Updated docs and tests to
 +    reflect this change.  This should solve problems when your clients
 +    are posting multipart form values with special character sets.
 +  - Fixed issue where last_error actually returned the first error.  Took
 +    the change to add a 'pop_errors' to give the inverse of shift_errors.
 +  - Merged Pull Requests:
 +    - https://github.com/perl-catalyst/catalyst-runtime/pull/95
 +    - https://github.com/perl-catalyst/catalyst-runtime/pull/96
 +    - https://github.com/perl-catalyst/catalyst-runtime/pull/97
 +    - https://github.com/perl-catalyst/catalyst-runtime/pull/98
 +    - https://github.com/perl-catalyst/catalyst-runtime/pull/106
 +    - https://github.com/perl-catalyst/catalyst-runtime/pull/107
 +
 +5.90093 - 2015-05-29
 +  - Fixed a bug where if you used $res->write and then $res->body, the
 +    contents of body would be double encoded (gshank++).
 +
 +5.90092 - 2015-05-19
 +  - Allows you to use a namespace suffix for request, response and stats
 +    class traits.  Docs and tests for this.
 +  - Refactor the change introduced in 5.90091 to solve reported issues (for
 +    example Catalyst::Controller::DBIC::API fails its tests) and to be a more
 +    conservative refactor (new code more closely resembles the orginal code
 +    that has proven to work for years.)
 +
 +5.90091 - 2015-05-08
 +  - Fixed a bug where if an injected component expanded sub components, those
 +    sub components would not show up in the startup debug dev console (
 +    even though they were actually created).
 +
 +5.90090 - 2015-04-29
 +  - Updated some documention in Catalyst::Request::Upload to clarify behavior
 +    that RT ticket reported as confusing or unexpected
 +  - Merged all changes from 5.90089_XXX development cycle.
 +  - removed a mistaken use of Test::Most, which is not a core Catalyst
 +    dependency.  Used Test::More instead.
 +
 +5.90089_004 - 2015-04-28
 +  - Added swanky github badges.
 +  - Reverted a change to how the stats engine is setup that was incorrect.
 +  - New application setup hook 'config_for' which allows one to get the
 +    canonical application configuration for a controller, view or model, or
 +    a plugin.  Can also be used to override and adapt what configuration is
 +    retrieved.
 +
 +5.90089_003 - 2015-04-27
 +  - Fixed an issue where a delayed controller that did ACCEPT_CONTEXT would
 +    raise an error when registering its actions.
 +  - Updated some documentation around route matching.
 +  - refactored the setup of injected components to allow you to hook into
 +    the injection and do custom injection types.
 +
 +5.90089_002 - 2015-04-17
 +  - Changed the way we check for presence of Type::Tiny in a test case to be
 +    more explicit in the version requirement.  Hopefully a fix for reported
 +    test fail.
 +  - When declaring type constraints in Args and CaptureArgs, if you want to
 +    use a Moose builtin type (or a custom stringy type that you've already
 +    defined and associated with the Moose::TypeRegistry) you must now quote
 +    the type name.  This is to clearly disambiguate between Moose stringy types
 +    and imported types.
 +  - Additional changes to type constraint detection to between determine when a
 +    type constraint for reference types have a measured number of arguments or
 +    not.  clarify restriction on reference type constraints.
 +  - Several bugs with type constraints and uri_for squashed.  More test cases
 +    around all the argument type constraints to tighten scope of action.
 +  - NEW FEATURE: New method in Catalyst::Utils 'inject_component', which is a core
 +    version of the previously external addon 'CatalystX::InjectComponent'.  You should
 +    start to convert your existing code which uses the stand alone version, since
 +    going forward only the core version will be supported.  Also the core version in
 +    Catalyst::Utils has an additional feature to compose roles into the injected
 +    component.
 +  - NEW FEATURE: Concepts from 'CatalystX::RoleApplicator' have been moved to core
 +    so we now have the follow application attributes 'request_class_traits',
 +    'response_class_traits' and 'stats_class_traits' which allow you to compose
 +    traits for these core Catalyst classes without needing to create subclasses. So
 +    in general any request or response trait on CPAN that used 'CatalystX::RoleApplicator'
 +    should now just work with this core feature.  Note that  can also set thse roles
 +    via new configuration keys, 'request_class_traits', 'response_class_traits' 
 +    and 'stats_class_traits'. If you use both configuration and application class methods,
 +    they are combined.
 +  - NEW FEATURE: Core concepts from 'CatalystX::ComponentsFromConfig'.  You can now
 +    setup components directly from configuration.  This could save you some effort and
 +    creating 'empty' base classes in your Model/View and Controller directories.  This
 +    feature is currently limited in that you can only configure components that are
 +    'true' Catalyst components (but you may use Catalyst::Model::Adaptor to proxy
 +    stand alone classes...).
 +  - Only create a stats object if you are using stats.  This is a minor performance
 +    optimization, but there's a small chance it is a breaking change, so please
 +    report any stats related issues.
 +  - Added a developer mode warning if you call a component with arguments that does not
 +    expect arguments (for example calling $c->model('Foo', 1,2,3,4) where Myapp::Model::Foo
 +    does not ACCEPT_CONTEXT.  Only components that ACCEPT_CONTEXT do anything with
 +    passed arguments in $c->controller/view/model.
 +  - Change the way components are setup so that you can now rely on all components
 +    when setting up a component.  Previously application scoped components could not
 +    reliably use an existing application scoped component as a dependecy for initialization.
 +
 +5.90089_001 - 2015-03-26
 +  - New development branch synched with 5.90085.
 +  - NEW FEATURE: Type Constraints on Args/CaptureArgs.  Allows you to declare
 +    a Moose, MooseX::Types or Type::Tiny named constraint on your Arg or 
 +    CaptureArg.
 +  - When using $c->uri_for (or the derived $c->uri_for_action) and the target
 +    action has type constrainted args (or captures), verify that the proposed
 +    URL matches the defined args.  In general $c->uri_for will be a bit more
 +    noisy if the supplied arguments are not correct.
 +  - New top level document on Route matching. (Catalyst::RouteMatching).  This
 +    document is still in development, but is worth review and comments.
 +
 +5.90085 - 2015-03-25
 +  - Small change to Catalyst::Action to prevent autovivication of Args value (dim1++)
 +  - Minor typo fixes (Abraxxa++)
 +  - Make sure than when using chained actions and when more than one action
 +    matches the same path specification AND has Args(0), that we follow the
 +    "in a tie, the last action defined wins" rule.  There is a small chance
 +    this is a breaking change for you.  See Catalyst::Upgrading for more.
 +    You may use the application configuration setting "use_chained_args_0_special_case"
 +    to disable this new behavior, if you must for back-compat reasons.
 +  - Added PATCH HTTP Method action attribute shortcut.
 +  - Several new configuration options aimed to give improved backwards compatibility
 +    for when your URL query parameters or keywords have non UTF-8 encodings.
 +    See Catalyst::Upgrading.
 +
 +5.90084 - 2015-02-23
 +  - Small change to the way body parameters are created in order to prevent
 +    trying to create parameters twice.
 +  - Use new HTTP::Body and code updates to fix issue when POSTed params have
 +    non UTF-8 charset encodings or otherwise complex upload parts that are not
 +    file uploads. In these cases when Catalyst can't determine what the value of
 +    a form upload is, will return an instance of Catalyst::Request::PartData with
 +    all the information need to figure it out.  Documentation about this corner
 +    case. For RT https://rt.cpan.org/Ticket/Display.html?id=101556
 +  - Two new application configuration parameters 'skip_body_param_unicode_decoding'
 +    and 'skip_complex_post_part_handling' to assist you with any backward
 +    compatibility issues with all the new UTF8 work in the most recent stable
 +    Catalyst.  You may use these settings to TEMPORARILY disable certain new
 +    features while you are seeking a long term fix.
 +
 +5.90083 - 2015-02-16
 +  - Fixed typo in support for OPTIONS method matching (andre++)
 +  - Stop using $env->{'plack.request.query'} as a query parsing optimization
 +    since 1) it doesn't belong to us and 2) there's subtle differences in the
 +    way plack parses parameters and catalyst does.  This fixes a bug when you
 +    are using middleware that uses Plack::Request to do its thing.  This change
 +    might have subtle impact on query parsing.  Please test this change!
 +
 +5.90082 - 2015-01-10
 +  - Fixed a regression created in $response->from_psgi_response and test case
 +    to prevent it happening again.
 +
 +5.90081 - 2015-01-10
 +  - created class attribute 'finalized_default_middleware' which determines
 +    if the default middleware has been added to the stack yet or not.  This
 +    removes a horrible hack that polluted the configuration hash.  Added
 +    test case to prevent regressions.
 +
 +5.90080 - 2015-01-09
 +  - Minor documentation corrections
 +  - Make the '79 development series stable
 +
 +5.90079_008  - 2015-01-07
 +  - If we get a response set from $res->from_psgi_response and that response
 +    has a charset for the content type, we clear encoding for the rest of the
 +    response (avoid double encoding).  Added more documentation around this.
 +  - Documentation updates and typo fixes across various UTF8 docs (Mark Ellis++)
 +
 +5.90079_007  - 2015-01-07
 +  - Merged from Stable (5.90079)
 +  - reviewed and cleaned up UTF8 related docs
 +  - replace missing utf8 pragma in Catalyst::Engine
 +  - Cleaned up spelling errors in various docs (abbraxxa++)
 +  - New document Catalyst::UTF8 which attempts to summarize UTF8 and encoding
 +    changes introduced in v5.90080.
 +
 +5.90079_006  - 2015-01-02
 +  - Removed unneeded dependency on RenderView in new test case that was causing fails
 +    on CPAN testers that did not just happen to have that dependency already installed
 +  - Updated copyright notices to 2015
 +  - Documentation patches around the setup methods and clarification on on security
 +    note posted a few months ago.
 +  - Added my name to the contributors list
 +
 +5.90079_005 - 2014-12-31
 +  - Merged changes from 5.90078
 +  - If configuration 'using_frontend_proxy' is set, we add the correct middleware
 +    to the default middleware list.  This way you get the correct and expected
 +    behavior if you are starting your application via one of the generated scripts
 +    or if you are calling MyApp->psgi_app.  Previously if you started the application
 +    with ->psgi_app (or to_app) we ignored this configuration option
 +  - New configuration option 'using_frontend_proxy_path' which enables
 +    Plack::Middleware::ReverseProxyPath on your application easily.  Please note that
 +    Plack::Middleware::ReverseProxyPath is not an automatic dependency of Catalyst at
 +    this time, so if you want this feature you should add it to your project dependency
 +    list.  This is done to avoid continued growth of Catalyst dependencies.
 +  - Tweaks encoding docs a bit to get closer to final.
 +
 +5.90079_004 - 2014-12-26
 +  - Starting adding some docs around the new encoding stuff
 +  - Exposed the reqexp we use to match content types that need encoding via a
 +    global variable.
 +  - Added some test cases for JSON utf8 and tested file uploads with utf8.
 +  - Fixes to decoding on file upload filenames and related methods
 +  - new methods on upload object that tries to do the right thing if we find
 +    a character set on the upload and its UTF8.
 +  - new additional helper methods on the file upload object.
 +  - new helper methods has_encoding and clear_encoding on context.
 +  - Method on Catalyst::Response to determine if the response should be encoded.
 +  - Warn if changing headers only if headers are finalized AND the response callback
 +    has already been called (and headers already sent).
 +  - Centralized rules about detecting if we need to automatically encode or not and
 +    added tests around cases when you choose to skip auto encoding.
 +
 +5.90079_003 - 2014-12-03
 +  - Make sure all tests run even if debug mode is enabled.
 +  - Fixed issue with middleware stash test case that failed on older Perls
 +
 +5.90079_002 - 2014-12-02
 +  - Fixed typo in Makefile.PL which borked the previous distribution. No other
 +    changes.
 +
 +5.90079_001 - 2014-12-02
 +  - MyApp->to_app is now an alias for MyApp->psgi_app in order to better support
 +    existing Plack conventions.
 +  - Modify Catalyst::Response->from_psgi_response to allow the first argument to
 +    be an object that does ->as_psgi.
 +  - Modified Catalyst::Middleware::Stash to be a shallow copy in $env.  Added some
 +    docs.  Added a test case to make sure stash keys added in a child application
 +    don't bubble back up to the main application.
 +  - We no longer use Encode::is_utf8 since it doesn't work the way we think it
 +    does... This required some UTF-8 changes.  If your application is UTF-8 aware
 +    I highly suggest you test this release.
 +  - We always do utf8 decoding on incoming URLs (before we only did so if the server
 +    encoding was utf8.  I believe this is correct as per the w3c spec, but please
 +    correct if incorrect :)
 +  - Debug output now shows utf8 characters if those are incoming via Args or as
 +    path or pathparts in your actions.  query and body parameter keys are now also
 +    subject to utf8 decoding (or as specified via the encoding configuration value).
 +  - lots of UTF8 changes.  Again we think this is now more correct but please test.
 +  - Allow $c->res->redirect($url) to accept $url as an object that does ->as_string
 +    which I think will ease a common case (and common bug) and added documentation.
 +  - !!! UTF-8 is now the default encoding (there used to be none...).  You can disable
 +    this if you need to with MyApp->config(encoding => undef) if it causes you trouble.
 +  - Calling $c->res->write($data) now encodes $data based on the configured encoding
 +    (UTF-8 is default).
 +  - $c->res->writer_fh now returns Catalyst::Response::Writer which is a decorator
 +    over the PSGI writer and provides an additional method 'write_encoded' that just
 +    does the right thing for encoding your responses.  This is probably the method
 +    you want to use.
 +  - New dispatch matching attribute: Scheme.  This lets you match a route based on
 +    the incoming URI scheme (http, https, ws, wss).
 +  - If $c->uri_for targets an action or action chain that defines Scheme, use that
 +    scheme for the generated URI object instead of just using whatever the incoming
 +    request uses.
 +
 +5.90079 - 2015-01-02
 +  - Removed dependency from test case that we don't install for testing (
 +    rt #101243)
 +  - updated year in copyright notices
 +
 +5.90078 - 2014-12-30
 +  - POD corrections (sergey++)
 +  - New configuration option to disable the HTTP Exception passthrough feature
 +    introduced in 5.90060.  You can use this if that feature is causing you
 +    trouble. (davewood++);
 +  - Some additional helper methods for dealing with errors.
 +  - More clear exception when $request->body_data tries to parse malformed POSTed
 +    data.  Added documentation and tests around this.
 +
 +5.90077 - 2014-11-18
 +  - We store the PSGI $env in Catalyst::Engine for backcompat reasons.  Changed
 +    this so that the storage is a weak reference, so that it goes out of scope
 +    with the request.  This solves an issue where items in the stash (now in the
 +    PSGI env) would not get closed at the end of the request.  This caused some
 +    regression, primarily in custom testing classes.
 +
 +5.90076 - 2014-11-13
 +  - If throwing an exception object that does the code method, make sure that
 +    method returns an expected HTTP status code before passing it on to the
 +    HTTP Exception middleware.
 +
 +5.90075 - 2014-10-06
 +  - Documentation patch for $c->req->param to point out the recently discovered
 +    potential security issues: http://blog.gerv.net/2014/10/new-class-of-vulnerability-in-perl-web-applications/
 +  - You don't need to install this update, but you should read about the exploit
 +    and review if your code is vulnerable.  If you use the $c->req->param interface
 +    you really need to review this exploit.
 +
 +5.90074 - 2014-10-01
 +  - Specify Carp minimum version to avoid pointless test fails (valy++)
 +
  5.90073 - 2014-09-23
    - Fixed a regression caused by the last release where we broke what happened
      when you tried to set request parameters via $c->req->param('foo', 'bar').
      in the wild (Catalyst-Plugin-Authentication-0.10023) - (removed in 5.90070)
    - Reverted changes to debug log/handling (5.90069_003) to fix
      rev dep Catalyst-Plugin-Static-Simple-0.32 test suite.
 -  - Added italian translation of default error.
 +  - Added Italian translation of default error.
  
  5.90070 - 2014-08-07
    - Retagged previous release as stable; no changes
  
  5.90059_006 - 2014-02-06
    - MyApp->setup now returns $app to allow class method chaining.
 -  - New Util helper functional localize $env to make it easier to mount PSIG
 +  - New Util helper functional localize $env to make it easier to mount PSGI
      applications under controllers and actions.  See Catalyst::Utils/PSGI Helpers.
    - NOTICE: Final Development release for Runner, unless significant issues are
      raised.  Please test.
      that does 'read' but not 'getline'.  Added deprecation notice for this
      case.  Added docs to Catalyst::Delta.
    - Catalyst::Delta contains a list of behaviors which will be considered
 -    deprecated immediatelty.  Most items have workarounds and tweaks you can
 +    deprecated immediately.  Most items have workarounds and tweaks you can
      make to avoid issues.  These deprecations are targeted for removal/enforcement
      in the Catalyst 6 release.  Please review and give your feedback.
    - More middleware to replace inline code (upasana++)
    - Give a more descriptive error message when trying to load middleware that
      does not exist.
    - Change the way we initialize plugins to fix a bug where when using the 
 -    populare ConfigLoader plugin, configs merged are not available for setting
 +    popular ConfigLoader plugin, configs merged are not available for setting
      up middleware and data handlers (and probably other things as well).
  
      NOTE: This change might cause issues if you had code that was relying on the
  
    - You may now also call 'setup_middleware' as a package method if you think
      that loading middleware via configuration is a weird or broken idea.
 -  - Various POD formating fixed.
 +  - Various POD formatting fixed.
    - Improved some documentation about what type of filehandles that ->body can
      accept and issues that might arise.
  
  5.90051 - 2013-11-06
 -  - Be more skeptical of the existance of $request->env to fix a regression
 +  - Be more skeptical of the existence of $request->env to fix a regression
      introduced in Catalyst::Action::REST by the previous release
  
  5.90050 - 2013-11-05
  
  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
 +    whichever is first (preferring 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
  
  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
 +  - Merged from master many important bugfixes and forward compatibility
      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++)
      1) Only allow one of either :CaptureArgs or :Args
      2) :CaptureArgs() argument must be numeric
      3) :CaptureArgs() and :Args() arguments cannot be negative
 -  - Add Devel::InnerPackage to dependencies, fixing tests on perl 5.17.11
 +  - Add Devel::InnerPackage to dependencies, fixing tests on Perl 5.17.11
      as it's been removed from core. RT#84787
    - New support for closing over the PSGI $writer object, useful for working
      with event loops.
    - Added cpanfile as a way to notice we are a dev checkout.
    - Added 'x-tunneled-method' HTTP Header method override to match features in
      Catalyst::Action::REST and in other similar systems on CPAN.
 -  - smarter valiation around action attributes.
 +  - smarter validation around action attributes.
  
  5.90020 - 2013-02-22
    ! Catalyst::Action now defines 'match_captures' so it is no long considered
    - Some test and documentation improvements
  
  5.90019 - 2012-12-04 21:31:00
 -  - Fix for perl 5.17.6 (commit g7dc8663). RT#81601
 -  - Fix for perl 5.8. RT#61122
 -  - Remove use of MooseX::Types as MooseX::Types is broken on perl5.8
 +  - Fix for Perl 5.17.6 (commit g7dc8663). RT#81601
 +  - Fix for Perl 5.8. RT#61122
 +  - Remove use of MooseX::Types as MooseX::Types is broken on Perl 5.8
      RT#77100 & RT#81121
  
  5.90018 - 2012-10-23 20:55:00
  5.90016 - 2012-08-16 15:35:00
    - prepare_parameters is no longer an attribute builder.  It is now a method
      that calls the correct underlying functionality (Bill Moseley++)
 -  - Updated Makefile.PL to handle MacOXS tar
 +  - Updated Makefile.PL to handle MacOSX tar
    - Fix uri_for to handle a stringifiable object
    - Fix model/view/controller methods to handle stringifiable objects
    - Fix RT#78377 - IIS7 ignores response body for 3xx requests, which
      refactoring.
  
    - The Catalyst::Utils::home function is used to find if the application
 -    is a checkout in Catalyst::ScriptRunner. This means that a non-existant
 +    is a checkout in Catalyst::ScriptRunner. This means that a non-existent
      lib directory that is relative to the script install location is not
      included when not running from a checkout.
  
       application authors to add custom options to their scripts then
       get them passed through to the application.
  
 -  Doumentation:
 +  Documentation:
     - Clarify that if you manually write your own .psgi file, then optional
       proxy support (via the using_frontend_proxy config value) will not be
       enabled unless you explicitly apply the default middlewares from
     - Fix issue due to perl internals bugs in 5.8 and 5.10 (not present in
       other perl versions) require can pass the context inappropriately,
       meaning that some methods of loading classes can fail due to void
 -     context being passed throuh to make_immutable, causing it to not return
 +     context being passed through to make_immutable, causing it to not return
       a value.
       This bug caused loading Catalyst::Script::XXX to fail and is fixed
       both by bumping the Class::Load dependency, and also adding an explicit
  
     - Document how to get the vhost of the request in $c->req->hostname
       to avoid confusion
 -   - Remove documentation showing Global / Regex / Private actionsi
 +   - Remove documentation showing Global / Regex / Private actions
       as whilst these still exist (and work), they are not recommended.
     - Remove references to the -Engine flag.
     - Remove references to the deprecated Catalyst->plugin method
  5.90003 - 2011-10-05 08:32:00
    Bug fixes:
  
 -   - Make default body reponses for 302s W3C compliant. RT#71237
 +   - Make default body responses for 302s W3C compliant. RT#71237
  
     - Fix issue where groups of attributes to override controller actions
       in config would be (incorrectly) overwritten, if the parser for that
    Backward compatibility fixes:
  
     - Restore (an almost empty) Catalyst::Engine::HTTP to the dist for old
 -     scripts which explictly require Catalyst::Engine::HTTP
 +     scripts which explicitly require Catalyst::Engine::HTTP
  
    Documentation fixes:
  
  
      - nginx specific behaviour is removed as it is not needed with any
        web server configuration I can come up with (recommended config is
 -      documented in Catalst::Manual::Deployment::nginx::FastCGI)
 +      documented in Catalyst::Manual::Deployment::nginx::FastCGI)
  
  5.89003 2011-07-28 20:11:50 (TRIAL release)
  
    - Added a Catalyst::PSGI manual page with information about writing a .psgi
      file for your application.
  
 -   - Catalyst::Uprading has been improved, and the status of old Catalyst
 +   - Catalyst::Upgrading has been improved, and the status of old Catalyst
       engines clarified.
  
   Deprecations:
  
    Bug fixed:
     - $c->uri_for will now escape unsafe characters in captures
 -     ($c->request->captures) and correctly encode utf8 charracters.
 +     ($c->request->captures) and correctly encode utf8 characters.
  
  5.80020 2010-02-04 06:51:18
  
     - Restore -p option for pid file in the FastCGI server script.
     - Fix the script environment variables MYAPP_PORT and MYAPP_RELOAD RT#52604
     - Fix aliasing applications under non-root paths with mod_rewrite in
 -     some apache versions where %ENV{SCRIPT_NAME} is set to the real name of
 +     some Apache versions where %ENV{SCRIPT_NAME} is set to the real name of
       the script, by using $ENV{REDIRECT_URL} which contains the non-rewritten
       URI.
     - Fix usage display when myapp_create.pl is run with no arguments. RT#52630
      - Stop warnings when actions are forwarded to during dispatch.
      - Remove warnings for using Catalyst::Dispatcher->dispatch_types as this is a
        valid method to publicly call on the dispatcher.
 -    - Args ($c->request->args) and CaptureArgs ($c->request->captrues)
 +    - Args ($c->request->args) and CaptureArgs ($c->request->captures)
        passed to $c->uri_for with an action object ($c->action) will now
        correctly round-trip when args or captures contain / as it is now
        correctly uri encoded to %2F.
         - Fix POD to refer to ->config(key => $val), rather than
           ->config->{key} = $val, as the latter form is deprecated.
         - Clearer docs for the 'uri_for' method.
 -       - Fix POD refering to CGI::Cookie. We're using CGI::Simple::Cookie.
 +       - Fix POD referring to CGI::Cookie. We're using CGI::Simple::Cookie.
           (Forrest Cahoon)
  
  5.80007 2009-06-30 23:54:34
            in Catalyst::Engine (kmx)
  
  5.80004 2009-05-18 17:03:23
 -        - Rename the actions attribute in Catalyt::Controller to
 +        - Rename the actions attribute in Catalyst::Controller to
            _controller_actions to avoid name clashes with application
            controller naming. (random)
          - Test for using Moose in components which have a non-Moose base class
          - Fix RT#43375 by sorting results before testing them
          - Fixes for uri_for_action when using Catalyst::DispatchType::Regex
            + tests from RT#39369 (norbi)
 -        - Partial rewrite and reoganisation of the C3 docs in
 +        - Partial rewrite and reorganization of the C3 docs in
            Catalyst::Upgrading based on feedback from kiffin
          - If you make your application class immutable and turn off
            constructor inlining, Catalyst will die and tell you pass
  
  5.80002 2009-04-22 01:28:36
          - Fix CATALYST_DEBUG and MYAPP_DEBUG environment variables
 -          turning debuging on if defined, rather than if set.
 +          turning debugging on if defined, rather than if set.
            They now force debugging on or off, taking precedence over
            configuration in your application.
            - Tests for this
            allowing method modifiers on actions to work as expected.
          - Provide a reasonable API in Catalyst::Controller for working with
            and registering actions, allowing a controller sub-class to replace
 -          subroutine attributes for action declerations with an alternate
 +          subroutine attributes for action declarations with an alternate
            syntax.
          - Instantiate correct sub-class of Moose::Meta::Class for non-Moose
            components where Catalyst forces the creation of a metaclass instance.
            parameter used to be ignored, but started breaking if the parameter
            was not a hash in 5.8000_04. Extra parameter is now ignored if
            it isn't a hashref
 -        - Fix request argumentss getting corrupted if you override the
 +        - Fix request arguments getting corrupted if you override the
            dispatcher and call an action which detaches (for
            Catalyst::Plugin::Authorization::ACL)
          - Fix calling use Catalyst::Test 'MyApp' 'foo' which used to work,
            was introduced when attempting to allow "0" as a Path.
  
  5.7013  2008-05-16 18:20:00
 -        - Provide backwards compatability methods in Catalyst::Stats
 +        - Provide backwards compatibility methods in Catalyst::Stats
          - Fix subdirs for scripts that run in subdirs more than one level deep.
          - Added test and updated docs for handling the Authorization header
            under mod_fastcgi/mod_cgi.
diff --combined lib/Catalyst.pm
@@@ -50,7 -50,7 +50,7 @@@ use Plack::Middleware::RemoveRedundantB
  use Catalyst::Middleware::Stash;
  use Plack::Util;
  use Class::Load 'load_class';
 -use Encode 2.21 ();
 +use Encode 2.21 'decode_utf8', 'encode_utf8';
  
  BEGIN { require 5.008003; }
  
@@@ -63,9 -63,7 +63,9 @@@ has request => 
      is => 'rw',
      default => sub {
          my $self = shift;
 -        $self->request_class->new($self->_build_request_constructor_args);
 +        my $class = ref $self;
 +        my $composed_request_class = $class->composed_request_class;
 +        return $composed_request_class->new( $self->_build_request_constructor_args);
      },
      lazy => 1,
  );
@@@ -79,51 -77,17 +79,51 @@@ sub _build_request_constructor_args 
      \%p;
  }
  
 +sub composed_request_class {
 +  my $class = shift;
 +  my @traits = (@{$class->request_class_traits||[]}, @{$class->config->{request_class_traits}||[]});
 +
 +  # For each trait listed, figure out what the namespace is.  First we try the $trait
 +  # as it is in the config.  Then try $MyApp::TraitFor::Request:$trait. Last we try
 +  # Catalyst::TraitFor::Request::$trait.  If none load, throw error.
 +
 +  my $trait_ns = 'TraitFor::Request';
 +  my @normalized_traits = map {
 +    Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
 +  } @traits;
 +
 +  return $class->_composed_request_class ||
 +    $class->_composed_request_class(Moose::Util::with_traits($class->request_class, @normalized_traits));
 +}
 +
  has response => (
      is => 'rw',
      default => sub {
          my $self = shift;
 -        $self->response_class->new($self->_build_response_constructor_args);
 +        my $class = ref $self;
 +        my $composed_response_class = $class->composed_response_class;
 +        return $composed_response_class->new( $self->_build_response_constructor_args);
      },
      lazy => 1,
  );
  sub _build_response_constructor_args {
 -    my $self = shift;
 -    { _log => $self->log };
 +    return +{
 +      _log => $_[0]->log,
 +      encoding => $_[0]->encoding,
 +    };
 +}
 +
 +sub composed_response_class {
 +  my $class = shift;
 +  my @traits = (@{$class->response_class_traits||[]}, @{$class->config->{response_class_traits}||[]});
 +
 +  my $trait_ns = 'TraitFor::Response';
 +  my @normalized_traits = map {
 +    Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
 +  } @traits;
 +
 +  return $class->_composed_response_class ||
 +    $class->_composed_response_class(Moose::Util::with_traits($class->response_class, @normalized_traits));
  }
  
  has namespace => (is => 'rw');
@@@ -148,40 -112,22 +148,40 @@@ our $RECURSION = 1000
  our $DETACH    = Catalyst::Exception::Detach->new;
  our $GO        = Catalyst::Exception::Go->new;
  
 -#I imagine that very few of these really need to be class variables. if any.
 +#I imagine that very few of these really 
 +#need to be class variables. if any.
  #maybe we should just make them attributes with a default?
  __PACKAGE__->mk_classdata($_)
    for qw/components arguments dispatcher engine log dispatcher_class
    engine_loader context_class request_class response_class stats_class
    setup_finished _psgi_app loading_psgi_file run_options _psgi_middleware
 -  _data_handlers _encoding _encode_check/;
 +  _data_handlers _encoding _encode_check finalized_default_middleware
 +  request_class_traits response_class_traits stats_class_traits
 +  _composed_request_class _composed_response_class _composed_stats_class/;
  
  __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
  __PACKAGE__->request_class('Catalyst::Request');
  __PACKAGE__->response_class('Catalyst::Response');
  __PACKAGE__->stats_class('Catalyst::Stats');
 +
 +sub composed_stats_class {
 +  my $class = shift;
 +  my @traits = (@{$class->stats_class_traits||[]}, @{$class->config->{stats_class_traits}||[]});
 +
 +  my $trait_ns = 'TraitFor::Stats';
 +  my @normalized_traits = map {
 +    Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
 +  } @traits;
 +
 +  return $class->_composed_stats_class ||
 +    $class->_composed_stats_class(Moose::Util::with_traits($class->stats_class, @normalized_traits));
 +}
 +
  __PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
  
  # Remember to update this in Catalyst::Runtime as well!
 -our $VERSION = '5.90073';
 +our $VERSION = '5.90101';
 +$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
  
  sub import {
      my ( $class, @arguments ) = @_;
@@@ -222,11 -168,6 +222,11 @@@ sub _application { $_[0] 
  
  Catalyst - The Elegant MVC Web Application Framework
  
 +=for html
 +<a href="https://badge.fury.io/pl/Catalyst-Runtime"><img src="https://badge.fury.io/pl/Catalyst-Runtime.svg" alt="CPAN version" height="18"></a>
 +<a href="https://travis-ci.org/perl-catalyst/catalyst-runtime/"><img src="https://api.travis-ci.org/perl-catalyst/catalyst-runtime.png" alt="Catalyst></a>
 +<a href="http://cpants.cpanauthors.org/dist/Catalyst-Runtime"><img src="http://cpants.cpanauthors.org/dist/Catalyst-Runtime.png" alt='Kwalitee Score' /></a>
 +
  =head1 SYNOPSIS
  
  See the L<Catalyst::Manual> distribution for comprehensive
@@@ -554,23 -495,10 +554,23 @@@ Catalyst)
      # stash is automatically passed to the view for use in a template
      $c->forward( 'MyApp::View::TT' );
  
 +The stash hash is currently stored in the PSGI C<$env> and is managed by
 +L<Catalyst::Middleware::Stash>.  Since it's part of the C<$env> items in
 +the stash can be accessed in sub applications mounted under your main
 +L<Catalyst> application.  For example if you delegate the response of an
 +action to another L<Catalyst> application, that sub application will have
 +access to all the stash keys of the main one, and if can of course add
 +more keys of its own.  However those new keys will not 'bubble' back up
 +to the main application.
 +
 +For more information the best thing to do is to review the test case:
 +t/middleware-stash.t in the distribution /t directory.
 +
  =cut
  
  sub stash {
    my $c = shift;
 +  $c->log->error("You are requesting the stash but you don't have a context") unless blessed $c;
    return Catalyst::Middleware::Stash::get_stash($c->req->env)->(@_);
  }
  
@@@ -590,9 -518,6 +590,9 @@@ Add a new error
  
      $c->error('Something bad happened');
  
 +Calling this will always return an arrayref (if there are no errors it
 +will be an empty arrayref.
 +
  =cut
  
  sub error {
@@@ -637,49 -562,6 +637,49 @@@ Returns true if you have error
  
  sub has_errors { scalar(@{shift->error}) ? 1:0 }
  
 +=head2 $c->last_error
 +
 +Returns the most recent error in the stack (the one most recently added...)
 +or nothing if there are no errors.  This does not modify the contents of the
 +error stack.
 +
 +=cut
 +
 +sub last_error {
 +  my (@errs) = @{shift->error};
 +  return scalar(@errs) ? $errs[-1]: undef;
 +}
 +
 +=head2 shift_errors
 +
 +shifts the most recently added error off the error stack and returns it.  Returns
 +nothing if there are no more errors.
 +
 +=cut
 +
 +sub shift_errors {
 +    my ($self) = @_;
 +    my @errors = @{$self->error};
 +    my $err = shift(@errors);
 +    $self->{error} = \@errors;
 +    return $err;
 +}
 +
 +=head2 pop_errors
 +
 +pops the most recently added error off the error stack and returns it.  Returns
 +nothing if there are no more errors.
 +
 +=cut
 +
 +sub pop_errors {
 +    my ($self) = @_;
 +    my @errors = @{$self->error};
 +    my $err = pop(@errors);
 +    $self->{error} = \@errors;
 +    return $err;
 +}
 +
  sub _comp_search_prefixes {
      my $c = shift;
      return map $c->components->{ $_ }, $c->_comp_names_search_prefixes(@_);
@@@ -762,20 -644,13 +762,20 @@@ sub _comp_names 
  }
  
  # Filter a component before returning by calling ACCEPT_CONTEXT if available
 +
  sub _filter_component {
      my ( $c, $comp, @args ) = @_;
  
 +    if(ref $comp eq 'CODE') {
 +      $comp = $comp->();
 +    }
 +
      if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
 -        return $comp->ACCEPT_CONTEXT( $c, @args );
 +      return $comp->ACCEPT_CONTEXT( $c, @args );
      }
  
 +    $c->log->warn("You called component '${\$comp->catalyst_component_name}' with arguments [@args], but this component does not ACCEPT_CONTEXT, so args are ignored.") if scalar(@args) && $c->debug;
 +
      return $comp;
  }
  
@@@ -807,6 -682,11 +807,11 @@@ sub controller 
              my $comps = $c->components;
              my $check = $appclass."::Controller::".$name;
              return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+             foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) {
+                 next unless $path =~ /.*::Controller/;
+                 $check = $path."::".$name;
+                 return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+             }
          }
          my @result = $c->_comp_search_prefixes( $name, qw/Controller C/ );
          return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@@ -822,8 -702,7 +827,8 @@@ Gets a L<Catalyst::Model> instance by n
  
      $c->model('Foo')->do_stuff;
  
 -Any extra arguments are directly passed to ACCEPT_CONTEXT.
 +Any extra arguments are directly passed to ACCEPT_CONTEXT, if the model
 +defines ACCEPT_CONTEXT.  If it does not, the args are discarded.
  
  If the name is omitted, it will look for
   - a model object in $c->stash->{current_model_instance}, then
@@@ -846,6 -725,11 +851,11 @@@ sub model 
              my $comps = $c->components;
              my $check = $appclass."::Model::".$name;
              return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+             foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) {
+                 next unless $path =~ /.*::Model/;
+                 $check = $path."::".$name;
+                 return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+             }
          }
          my @result = $c->_comp_search_prefixes( $name, qw/Model M/ );
          return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@@ -910,6 -794,11 +920,11 @@@ sub view 
              else {
                  $c->log->warn( "Attempted to use view '$check', but does not exist" );
              }
+             foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) {
+                 next unless $path =~ /.*::View/;
+                 $check = $path."::".$name;
+                 return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+             }
          }
          my @result = $c->_comp_search_prefixes( $name, qw/View V/ );
          return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@@ -1124,47 -1013,17 +1139,47 @@@ And later
  Your log class should implement the methods described in
  L<Catalyst::Log>.
  
 +=head2 has_encoding
 +
 +Returned True if there's a valid encoding
 +
 +=head2 clear_encoding
 +
 +Clears the encoding for the current context
 +
  =head2 encoding
  
 -Sets or gets the application encoding.
 +Sets or gets the application encoding.  Setting encoding takes either an
 +Encoding object or a string that we try to resolve via L<Encode::find_encoding>.
 +
 +You would expect to get the encoding object back if you attempt to set it.  If
 +there is a failure you will get undef returned and an error message in the log.
  
  =cut
  
 +sub has_encoding { shift->encoding ? 1:0 }
 +
 +sub clear_encoding {
 +    my $c = shift;
 +    if(blessed $c) {
 +        $c->encoding(undef);
 +    } else {
 +        $c->log->error("You can't clear encoding on the application");
 +    }
 +}
 +
  sub encoding {
      my $c = shift;
      my $encoding;
  
      if ( scalar @_ ) {
 +
 +        # Don't let one change this once we are too far into the response
 +        if(blessed $c && $c->res->finalized_headers) {
 +          Carp::croak("You may not change the encoding once the headers are finalized");
 +          return;
 +        }
 +
          # Let it be set to undef
          if (my $wanted = shift)  {
              $encoding = Encode::find_encoding($wanted)
@@@ -1280,17 -1139,6 +1295,17 @@@ Catalyst> line
  B<Note:> You B<should not> wrap this method with method modifiers
  or bad things will happen - wrap the C<setup_finalize> method instead.
  
 +B<Note:> You can create a custom setup stage that will execute when the
 +application is starting.  Use this to customize setup.
 +
 +    MyApp->setup(-Custom=value);
 +
 +    sub setup_custom {
 +      my ($class, $value) = @_;
 +    }
 +
 +Can be handy if you want to hook into the setup phase.
 +
  =cut
  
  sub setup {
@@@ -1427,7 -1275,6 +1442,7 @@@ EO
            : $class->log->debug(q/Couldn't find home/);
  
          my $column_width = Catalyst::Utils::term_width() - 8 - 9;
 +
          my $t = Text::SimpleTable->new( [ $column_width, 'Class' ], [ 8, 'Type' ] );
          for my $comp ( sort keys %{ $class->components } ) {
              my $type = ref $class->components->{$comp} ? 'instance' : 'class';
@@@ -1484,11 -1331,9 +1499,11 @@@ sub setup_finalize 
      $class->setup_finished(1);
  }
  
 -=head2 $c->uri_for( $path?, @args?, \%query_values? )
 +=head2 $c->uri_for( $path?, @args?, \%query_values?, \$fragment? )
  
 -=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values? )
 +=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values?, \$fragment? )
 +
 +=head2 $c->uri_for( $action, [@captures, @args], \%query_values?, \$fragment? )
  
  Constructs an absolute L<URI> object based on the application root, the
  provided path, and the additional arguments and query parameters provided.
@@@ -1506,15 -1351,6 +1521,15 @@@ relative to the application root (if i
  C<< $c->request->base >>; any C<@args> are appended as additional path
  components; and any C<%query_values> are appended as C<?foo=bar> parameters.
  
 +B<NOTE> If you are using this 'stringy' first argument, we skip encoding and
 +allow you to declare something like:
 +
 +    $c->uri_for('/foo/bar#baz')
 +
 +Where 'baz' is a URI fragment.  We consider this first argument string to be
 +'expert' mode where you are expected to create a valid URL and we for the most
 +part just pass it through without a lot of internal effort to escape and encode.
 +
  If the first argument is a L<Catalyst::Action> it represents an action which
  will have its path resolved using C<< $c->dispatcher->uri_for_action >>. The
  optional C<\@captures> argument (an arrayref) allows passing the captured
@@@ -1538,14 -1374,6 +1553,14 @@@ path, use C<< $c->uri_for_action >> ins
    # Path to a static resource
    $c->uri_for('/static/images/logo.png');
  
 +In general the scheme of the generated URI object will follow the incoming request
 +however if your targeted action or action chain has the Scheme attribute it will
 +use that instead.
 +
 +Also, if the targeted Action or Action chain declares Args/CaptureArgs that have
 +type constraints, we will require that your proposed URL verify on those declared
 +constraints.
 +
  =cut
  
  sub uri_for {
          $path .= '/';
      }
  
 -    undef($path) if (defined $path && $path eq '');
 +    my $fragment =  ((scalar(@args) && ref($args[-1]) eq 'SCALAR') ? pop @args : undef );
 +
 +    unless(blessed $path) {
 +      if (defined($path) and $path =~ s/#(.+)$//)  {
 +        if(defined($1) and $fragment) {
 +          carp "Abiguious fragment declaration: You cannot define a fragment in '$path' and as an argument '$fragment'";
 +        }
 +        if(defined($1)) {
 +          $fragment = $1;
 +        }
 +      }
 +    }
  
      my $params =
        ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
  
 +    undef($path) if (defined $path && $path eq '');
 +
      carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
 -    foreach my $arg (@args) {
 -        utf8::encode($arg) if utf8::is_utf8($arg);
 -        $arg =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
 -    }
  
 +    my $target_action = $path->$_isa('Catalyst::Action') ? $path : undef;
      if ( $path->$_isa('Catalyst::Action') ) { # action object
          s|/|%2F|g for @args;
          my $captures = [ map { s|/|%2F|g; $_; }
                           ? @{ shift(@args) }
                           : ()) ];
  
 -        foreach my $capture (@$captures) {
 -            utf8::encode($capture) if utf8::is_utf8($capture);
 -            $capture =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
 -        }
 -
          my $action = $path;
 +        my $expanded_action = $c->dispatcher->expand_action( $action );
 +        my $num_captures = $expanded_action->number_of_captures;
 +
          # ->uri_for( $action, \@captures_and_args, \%query_values? )
          if( !@args && $action->number_of_args ) {
 -            my $expanded_action = $c->dispatcher->expand_action( $action );
 +          unshift @args, splice @$captures, $num_captures;
 +        }
  
 -            my $num_captures = $expanded_action->number_of_captures;
 -            unshift @args, splice @$captures, $num_captures;
 +        if($num_captures) {
 +          unless($expanded_action->match_captures_constraints($c, $captures)) {
 +            carp "captures [@{$captures}] do not match the type constraints in actionchain ending with '$expanded_action'";
 +            return;
 +          }
          }
  
 -       $path = $c->dispatcher->uri_for_action($action, $captures);
 +        $path = $c->dispatcher->uri_for_action($action, $captures);
          if (not defined $path) {
              $c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
                  if $c->debug;
              return undef;
          }
          $path = '/' if $path eq '';
 +
 +        # At this point @encoded_args is the remaining Args (all captures removed).
 +        if($expanded_action->has_args_constraints) {
 +          unless($expanded_action->match_args($c,\@args)) {
 +             carp "args [@args] do not match the type constraints in action '$expanded_action'";
 +             return;
 +          }
 +        }
      }
  
      unshift(@args, $path);
      my ($base, $class) = ('/', 'URI::_generic');
      if(blessed($c)) {
        $base = $c->req->base;
 -      $class = ref($base);
 +      if($target_action) {
 +        $target_action = $c->dispatcher->expand_action($target_action);
 +        if(my $s = $target_action->scheme) {
 +          $s = lc($s);
 +          $class = "URI::$s";
 +          $base->scheme($s);
 +        } else {
 +          $class = ref($base);
 +        }
 +      } else {
 +        $class = ref($base);
 +      }
 +
        $base =~ s{(?<!/)$}{/};
      }
  
      my $query = '';
 -
      if (my @keys = keys %$params) {
        # somewhat lifted from URI::_query's query_form
        $query = '?'.join('&', map {
            my $val = $params->{$_};
 -          s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
 +          #s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go; ## Commented out because seems to lead to double encoding - JNAP
            s/ /+/g;
            my $key = $_;
            $val = '' unless defined $val;
            (map {
                my $param = "$_";
 -              utf8::encode( $param ) if utf8::is_utf8($param);
 +              $param = encode_utf8($param);
                # using the URI::Escape pattern here so utf8 chars survive
                $param =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
                $param =~ s/ /+/g;
 +
 +              $key = encode_utf8($key);
 +              # using the URI::Escape pattern here so utf8 chars survive
 +              $key =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
 +              $key =~ s/ /+/g;
 +
                "${key}=$param"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
        } @keys);
      }
  
 +    $base = encode_utf8 $base;
 +    $base =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
 +    $args = encode_utf8 $args;
 +    $args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
 +
 +    if(defined $fragment) {
 +      if(blessed $path) {
 +        $fragment = encode_utf8(${$fragment});
 +        $fragment =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
 +        $fragment =~ s/ /+/g;
 +      }
 +      $query .= "#$fragment";
 +    }
 +
      my $res = bless(\"${base}${args}${query}", $class);
      $res;
  }
@@@ -2013,7 -1790,7 +2028,7 @@@ sub execute 
  
      if ( my $error = $@ ) {
          #rethow if this can be handled by middleware
 -        if(blessed $error && ($error->can('as_psgi') || $error->can('code'))) {
 +        if ( $c->_handle_http_exception($error) ) {
              foreach my $err (@{$c->error}) {
                  $c->log->error($err);
              }
@@@ -2126,7 -1903,7 +2141,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) {
        $c->log_response;
        return;
@@@ -2194,7 -1971,10 +2209,7 @@@ sub finalize_error 
          $c->engine->finalize_error( $c, @_ );
      } else {
          my ($error) = @{$c->error};
 -        if(
 -          blessed $error &&
 -          ($error->can('as_psgi') || $error->can('code'))
 -        ) {
 +        if ( $c->_handle_http_exception($error) ) {
              # In the case where the error 'knows what it wants', becauses its PSGI
              # aware, just rethow and let middleware catch it
              $error->can('rethrow') ? $error->rethrow : croak $error;
@@@ -2229,8 -2009,6 +2244,8 @@@ sub finalize_headers 
  
      $c->finalize_cookies;
  
 +    # This currently is a NOOP but I don't want to remove it since I guess people
 +    # might have Response subclasses that use it for something... (JNAP)
      $c->response->finalize_headers();
  
      # Done
  
  =head2 $c->finalize_encoding
  
 -Make sure your headers and body are encoded properly IF you set an encoding.
 +Make sure your body is encoded properly IF you set an encoding.  By
 +default the encoding is UTF-8 but you can disable it by explicitly setting the
 +encoding configuration value to undef.
 +
 +We can only encode when the body is a scalar.  Methods for encoding via the
 +streaming interfaces (such as C<write> and C<write_fh> on L<Catalyst::Response>
 +are available).
 +
  See L</ENCODING>.
  
  =cut
  
  sub finalize_encoding {
      my $c = shift;
 -
 -    my $body = $c->response->body;
 -
 -    return unless defined($body);
 -
 -    my $enc = $c->encoding;
 -
 -    return unless $enc;
 -
 -    my ($ct, $ct_enc) = $c->response->content_type;
 -
 -    # Only touch 'text-like' contents
 -    return unless $c->response->content_type =~ /^text|xml$|javascript$/;
 -
 -    if ($ct_enc && $ct_enc =~ /charset=([^;]*)/) {
 -        if (uc($1) ne uc($enc->mime_name)) {
 -            $c->log->debug("Unicode::Encoding is set to encode in '" .
 -                           $enc->mime_name .
 -                           "', content type is '$1', not encoding ");
 -            return;
 -        }
 -    } else {
 -        $c->res->content_type($c->res->content_type . "; charset=" . $enc->mime_name);
 +    my $res = $c->res || return;
 +
 +    # Warn if the set charset is different from the one you put into encoding.  We need
 +    # to do this early since encodable_response is false for this condition and we need
 +    # to match the debug output for backcompat (there's a test for this...) -JNAP
 +    if(
 +      $res->content_type_charset and $c->encoding and 
 +      (uc($c->encoding->mime_name) ne uc($res->content_type_charset))
 +    ) {
 +        my $ct = lc($res->content_type_charset);
 +        $c->log->debug("Catalyst encoding config is set to encode in '" .
 +            $c->encoding->mime_name .
 +            "', content type is '$ct', not encoding ");
      }
  
 -    # Oh my, I wonder what filehandle responses and streams do... - jnap.
 -    # Encode expects plain scalars (IV, NV or PV) and segfaults on ref's
 -    $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) )
 -        if ref(\$body) eq 'SCALAR';
 +    if(
 +      ($res->encodable_response) and
 +      (defined($res->body)) and
 +      (ref(\$res->body) eq 'SCALAR')
 +    ) {
 +        $c->res->body( $c->encoding->encode( $c->res->body, $c->_encode_check ) );
 +
 +        # Set the charset if necessary.  This might be a bit bonkers since encodable response
 +        # is false when the set charset is not the same as the encoding mimetype (maybe 
 +        # confusing action at a distance here..
 +        # Don't try to set the charset if one already exists or if headers are already finalized
 +        $c->res->content_type($c->res->content_type . "; charset=" . $c->encoding->mime_name)
 +          unless($c->res->content_type_charset ||
 +                ($c->res->_context && $c->res->finalized_headers && !$c->res->_has_response_cb));
 +    }
  }
  
  =head2 $c->finalize_output
@@@ -2346,7 -2116,7 +2361,7 @@@ sub handle_request 
          $status = $c->finalize;
      } catch {
          #rethow if this can be handled by middleware
 -        if(blessed $_ && ($_->can('as_psgi') || $_->can('code'))) {
 +        if ( $class->_handle_http_exception($_) ) {
              $_->can('rethrow') ? $_->rethrow : croak $_;
          }
          chomp(my $error = $_);
@@@ -2386,8 -2156,8 +2401,8 @@@ sub prepare 
  
      $c->response->_context($c);
  
 -    #surely this is not the most efficient way to do things...
      $c->stats($class->stats_class->new)->enable($c->use_stats);
 +
      if ( $c->debug || $c->config->{enable_catalyst_header} ) {
          $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
      }
@@@ -2496,7 -2266,7 +2511,7 @@@ Prepares body parameters
  
  sub prepare_body_parameters {
      my $c = shift;
 -    $c->engine->prepare_body_parameters( $c, @_ );
 +    $c->request->prepare_body_parameters( $c, @_ );
  }
  
  =head2 $c->prepare_connection
@@@ -2590,10 -2360,6 +2605,10 @@@ sub log_request 
      $method ||= '';
      $path = '/' unless length $path;
      $address ||= '';
 +
 +    $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
 +    $path = decode_utf8($path);
 +
      $c->log->debug(qq/"$method" request for "$path" from "$address"/);
  
      $c->log_request_headers($request->headers);
@@@ -2779,6 -2545,37 +2794,6 @@@ Prepares uploads
  sub prepare_uploads {
      my $c = shift;
      $c->engine->prepare_uploads( $c, @_ );
 -
 -    my $enc = $c->encoding;
 -    return unless $enc;
 -
 -    # Uggg we hook prepare uploads to do the encoding crap on post and query
 -    # parameters!  Sorry -jnap
 -    for my $key (qw/ parameters query_parameters body_parameters /) {
 -        for my $value ( values %{ $c->request->{$key} } ) {
 -            # N.B. Check if already a character string and if so do not try to double decode.
 -            #      http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg02350.html
 -            #      this avoids exception if we have already decoded content, and is _not_ the
 -            #      same as not encoding on output which is bad news (as it does the wrong thing
 -            #      for latin1 chars for example)..
 -            $value = $c->_handle_unicode_decoding($value);
 -        }
 -    }
 -    for my $value ( values %{ $c->request->uploads } ) {
 -        # skip if it fails for uploads, as we don't usually want uploads touched
 -        # in any way
 -        for my $inner_value ( ref($value) eq 'ARRAY' ? @{$value} : $value ) {
 -            $inner_value->{filename} = try {
 -                $enc->decode( $inner_value->{filename}, $c->_encode_check )
 -            } catch {
 -                $c->handle_unicode_encoding_exception({
 -                    param_value => $inner_value->{filename},
 -                    error_msg => $_,
 -                    encoding_step => 'uploads',
 -                });
 -            };
 -        }
 -    }
  }
  
  =head2 $c->prepare_write
@@@ -2793,65 -2590,10 +2808,65 @@@ sub prepare_write { my $c = shift; $c->
  
  Returns or sets the request class. Defaults to L<Catalyst::Request>.
  
 +=head2 $app->request_class_traits
 +
 +An arrayref of L<Moose::Role>s which are applied to the request class.  You can
 +name the full namespace of the role, or a namespace suffix, which will then
 +be tried against the following standard namespace prefixes.
 +
 +    $MyApp::TraitFor::Request::$trait_suffix
 +    Catalyst::TraitFor::Request::$trait_suffix
 +
 +So for example if you set:
 +
 +    MyApp->request_class_traits(['Foo']);
 +
 +We try each possible role in turn (and throw an error if none load)
 +
 +    Foo
 +    MyApp::TraitFor::Request::Foo
 +    Catalyst::TraitFor::Request::Foo
 +
 +The namespace part 'TraitFor::Request' was chosen to assist in backwards
 +compatibility with L<CatalystX::RoleApplicator> which previously provided
 +these features in a stand alone package.
 +  
 +=head2 $app->composed_request_class
 +
 +This is the request class which has been composed with any request_class_traits.
 +
  =head2 $c->response_class
  
  Returns or sets the response class. Defaults to L<Catalyst::Response>.
  
 +=head2 $app->response_class_traits
 +
 +An arrayref of L<Moose::Role>s which are applied to the response class.  You can
 +name the full namespace of the role, or a namespace suffix, which will then
 +be tried against the following standard namespace prefixes.
 +
 +    $MyApp::TraitFor::Response::$trait_suffix
 +    Catalyst::TraitFor::Response::$trait_suffix
 +
 +So for example if you set:
 +
 +    MyApp->response_class_traits(['Foo']);
 +
 +We try each possible role in turn (and throw an error if none load)
 +
 +    Foo
 +    MyApp::TraitFor::Response::Foo
 +    Catalyst::TraitFor::Responset::Foo
 +
 +The namespace part 'TraitFor::Response' was chosen to assist in backwards
 +compatibility with L<CatalystX::RoleApplicator> which previously provided
 +these features in a stand alone package.
 +
 +
 +=head2 $app->composed_response_class
 +
 +This is the request class which has been composed with any response_class_traits.
 +
  =head2 $c->read( [$maxlength] )
  
  Reads a chunk of data from the request body. This method is designed to
@@@ -2960,119 -2702,17 +2975,119 @@@ sub setup_components 
      }
  
      for my $component (@comps) {
 -        my $instance = $class->components->{ $component } = $class->setup_component($component);
 -        my @expanded_components = $instance->can('expand_modules')
 -            ? $instance->expand_modules( $component, $config )
 -            : $class->expand_component_module( $component, $config );
 -        for my $component (@expanded_components) {
 -            next if $comps{$component};
 -            $class->components->{ $component } = $class->setup_component($component);
 -        }
 +        my $instance = $class->components->{ $component } = $class->delayed_setup_component($component);
 +    }
 +
 +    # Inject a component or wrap a stand alone class in an adaptor. This makes a list
 +    # of named components in the configuration that are not actually existing (not a
 +    # real file).
 +
 +    my @injected = $class->setup_injected_components;
 +
 +    # All components are registered, now we need to 'init' them.
 +    foreach my $component_name (@comps, @injected) {
 +      $class->components->{$component_name} = $class->components->{$component_name}->() if
 +        (ref($class->components->{$component_name}) || '') eq 'CODE';
      }
  }
  
 +=head2 $app->setup_injected_components
 +
 +Called by setup_compoents to setup components that are injected.
 +
 +=cut
 +
 +sub setup_injected_components {
 +    my ($class) = @_;
 +    my @injected_components = keys %{$class->config->{inject_components} ||+{}};
 +
 +    foreach my $injected_comp_name(@injected_components) {
 +        $class->setup_injected_component(
 +          $injected_comp_name,
 +          $class->config->{inject_components}->{$injected_comp_name});
 +    }
 +
 +    return map { $class ."::" . $_ }
 +      @injected_components;
 +}
 +
 +=head2 $app->setup_injected_component( $injected_component_name, $config )
 +
 +Setup a given injected component.
 +
 +=cut
 +
 +sub setup_injected_component {
 +    my ($class, $injected_comp_name, $config) = @_;
 +    if(my $component_class = $config->{from_component}) {
 +        my @roles = @{$config->{roles} ||[]};
 +        Catalyst::Utils::inject_component(
 +          into => $class,
 +          component => $component_class,
 +          (scalar(@roles) ? (traits => \@roles) : ()),
 +          as => $injected_comp_name);
 +    }
 +}
 +
 +=head2 $app->inject_component($MyApp_Component_name => \%args);
 +
 +Add a component that is injected at setup:
 +
 +    MyApp->inject_component( 'Model::Foo' => { from_component => 'Common::Foo' } );
 +
 +Must be called before ->setup.  Expects a component name for your
 +current application and \%args where
 +
 +=over 4
 +
 +=item from_component
 +
 +The target component being injected into your application
 +
 +=item roles
 +
 +An arrayref of L<Moose::Role>s that are applied to your component.
 +
 +=back
 +
 +Example
 +
 +    MyApp->inject_component(
 +      'Model::Foo' => {
 +        from_component => 'Common::Model::Foo',
 +        roles => ['Role1', 'Role2'],
 +      });
 +
 +=head2 $app->inject_components
 +
 +Inject a list of components:
 +
 +    MyApp->inject_components(
 +      'Model::FooOne' => {
 +        from_component => 'Common::Model::Foo',
 +        roles => ['Role1', 'Role2'],
 +      },
 +      'Model::FooTwo' => {
 +        from_component => 'Common::Model::Foo',
 +        roles => ['Role1', 'Role2'],
 +      });
 +
 +=cut
 +
 +sub inject_component {
 +  my ($app, $name, $args) = @_;
 +  die "Component $name exists" if
 +    $app->config->{inject_components}->{$name};
 +  $app->config->{inject_components}->{$name} = $args;
 +}
 +
 +sub inject_components {
 +  my $app = shift;
 +  while(@_) {
 +    $app->inject_component(shift, shift);
 +  }
 +}
 +
  =head2 $c->locate_components( $setup_component_config )
  
  This method is meant to provide a list of component modules that should be
@@@ -3090,7 -2730,7 +3105,7 @@@ sub locate_components 
      my $config = shift;
  
      my @paths   = qw( ::M ::Model ::V ::View ::C ::Controller );
-     my $extra   = delete $config->{ search_extra } || [];
+     my $extra   = $config->{ search_extra } || [];
  
      unshift @paths, @$extra;
  
@@@ -3114,21 -2754,6 +3129,21 @@@ sub expand_component_module 
      return Devel::InnerPackage::list_packages( $module );
  }
  
 +=head2 $app->delayed_setup_component
 +
 +Returns a coderef that points to a setup_component instance.  Used
 +internally for when you want to delay setup until the first time
 +the component is called.
 +
 +=cut
 +
 +sub delayed_setup_component {
 +  my($class, $component, @more) = @_;
 +  return sub {
 +    return my $instance = $class->setup_component($component, @more);
 +  };
 +}
 +
  =head2 $c->setup_component
  
  =cut
@@@ -3140,21 -2765,21 +3155,21 @@@ sub setup_component 
          return $component;
      }
  
 -    my $suffix = Catalyst::Utils::class2classsuffix( $component );
 -    my $config = $class->config->{ $suffix } || {};
 +    my $config = $class->config_for($component);
      # Stash catalyst_component_name in the config here, so that custom COMPONENT
      # methods also pass it. local to avoid pointlessly shitting in config
      # for the debug screen, as $component is already the key name.
      local $config->{catalyst_component_name} = $component;
  
 -    my $instance = eval { $component->COMPONENT( $class, $config ); };
 -
 -    if ( my $error = $@ ) {
 -        chomp $error;
 -        Catalyst::Exception->throw(
 -            message => qq/Couldn't instantiate component "$component", "$error"/
 -        );
 -    }
 +    my $instance = eval {
 +      $component->COMPONENT( $class, $config );
 +    } || do {
 +      my $error = $@;
 +      chomp $error;
 +      Catalyst::Exception->throw(
 +        message => qq/Couldn't instantiate component "$component", "$error"/
 +      );
 +    };
  
      unless (blessed $instance) {
          my $metaclass = Moose::Util::find_meta($component);
              qq/Couldn't instantiate component "$component", COMPONENT() method (from $component_method_from) didn't return an object-like value (value was $value)./
          );
      }
 -    return $instance;
 +
 +    my @expanded_components = $instance->can('expand_modules')
 +      ? $instance->expand_modules( $component, $config )
 +      : $class->expand_component_module( $component, $config );
 +    for my $component (@expanded_components) {
 +      next if $class->components->{ $component };
 +      $class->components->{ $component } = $class->setup_component($component);
 +    }
 +
 +    return $instance; 
 +}
 +
 +=head2 $app->config_for( $component_name )
 +
 +Return the application level configuration (which is not yet merged with any
 +local component configuration, via $component_class->config) for the named
 +component or component object. Example:
 +
 +    MyApp->config(
 +      'Model::Foo' => { a => 1, b => 2},
 +    );
 +
 +    my $config = MyApp->config_for('MyApp::Model::Foo');
 +
 +In this case $config is the hashref C< {a=>1, b=>2} >.
 +
 +This is also handy for looking up configuration for a plugin, to make sure you follow
 +existing L<Catalyst> standards for where a plugin should put its configuration.
 +
 +=cut
 +
 +sub config_for {
 +    my ($class, $component_name) = @_;
 +    my $component_suffix = Catalyst::Utils::class2classsuffix($component_name);
 +    my $config = $class->config->{ $component_suffix } || {};
 +
 +    return $config;
  }
  
  =head2 $c->setup_dispatcher
  Adds the following L<Plack> middlewares to your application, since they are
  useful and commonly needed:
  
 -L<Plack::Middleware::ReverseProxy>, (conditionally added based on the status
 -of your $ENV{REMOTE_ADDR}, and can be forced on with C<using_frontend_proxy>
 -or forced off with C<ignore_frontend_proxy>), L<Plack::Middleware::LighttpdScriptNameFix>
 -(if you are using Lighttpd), L<Plack::Middleware::IIS6ScriptNameFix> (always
 -applied since this middleware is smart enough to conditionally apply itself).
 +L<Plack::Middleware::LighttpdScriptNameFix> (if you are using Lighttpd),
 +L<Plack::Middleware::IIS6ScriptNameFix> (always applied since this middleware
 +is smart enough to conditionally apply itself).
 +
 +We will also automatically add L<Plack::Middleware::ReverseProxy> if we notice
 +that your HTTP $env variable C<REMOTE_ADDR> is '127.0.0.1'.  This is usually
 +an indication that your server is running behind a proxy frontend.  However in
 +2014 this is often not the case.  We preserve this code for backwards compatibility
 +however I B<highly> recommend that if you are running the server behind a front
 +end proxy that you clearly indicate so with the C<using_frontend_proxy> configuration
 +setting to true for your environment configurations that run behind a proxy.  This
 +way if you change your front end proxy address someday your code would inexplicably
 +stop working as expected.
  
  Additionally if we detect we are using Nginx, we add a bit of custom middleware
  to solve some problems with the way that server handles $ENV{PATH_INFO} and
 -$ENV{SCRIPT_NAME}
 +$ENV{SCRIPT_NAME}.
 +
 +Please B<NOTE> that if you do use C<using_frontend_proxy> the middleware is now
 +adding via C<registered_middleware> rather than this method.
 +
 +If you are using Lighttpd or IIS6 you may wish to apply these middlewares.  In
 +general this is no longer a common case but we have this here for backward
 +compatibility.
  
  =cut
  
  sub apply_default_middlewares {
      my ($app, $psgi_app) = @_;
  
 -    $psgi_app = Plack::Middleware::Conditional->wrap(
 -        $psgi_app,
 -        builder   => sub { Plack::Middleware::ReverseProxy->wrap($_[0]) },
 -        condition => sub {
 -            my ($env) = @_;
 -            return if $app->config->{ignore_frontend_proxy};
 -            return $env->{REMOTE_ADDR} eq '127.0.0.1'
 -                || $app->config->{using_frontend_proxy};
 -        },
 -    );
 +    # Don't add this conditional IF we are explicitly saying we want the
 +    # frontend proxy support.  We don't need it here since if that is the
 +    # case it will be always loaded in the default_middleware.
 +
 +    unless($app->config->{using_frontend_proxy}) {
 +      $psgi_app = Plack::Middleware::Conditional->wrap(
 +          $psgi_app,
 +          builder   => sub { Plack::Middleware::ReverseProxy->wrap($_[0]) },
 +          condition => sub {
 +              my ($env) = @_;
 +              return if $app->config->{ignore_frontend_proxy};
 +              return $env->{REMOTE_ADDR} eq '127.0.0.1';
 +          },
 +      );
 +    }
  
      # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
      # http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html
      return $psgi_app;
  }
  
 -=head2 $c->psgi_app
 +=head2 App->psgi_app
 +
 +=head2 App->to_app
  
  Returns a PSGI application code reference for the catalyst application
 -C<$c>. This is the bare application without any middlewares
 -applied. C<${myapp}.psgi> is not taken into account.
 +C<$c>. This is the bare application created without the C<apply_default_middlewares>
 +method called.  We do however apply C<registered_middleware> since those are
 +integral to how L<Catalyst> functions.  Also, unlike starting your application
 +with a generated server script (via L<Catalyst::Devel> and C<catalyst.pl>) we do
 +not attempt to return a valid L<PSGI> application using any existing C<${myapp}.psgi>
 +scripts in your $HOME directory.
 +
 +B<NOTE> C<apply_default_middlewares> was originally created when the first PSGI
 +port was done for v5.90000.  These are middlewares that are added to achieve
 +backward compatibility with older applications.  If you start your application
 +using one of the supplied server scripts (generated with L<Catalyst::Devel> and
 +the project skeleton script C<catalyst.pl>) we apply C<apply_default_middlewares>
 +automatically.  This was done so that pre and post PSGI port applications would
 +work the same way.
  
  This is what you want to be using to retrieve the PSGI application code
 -reference of your Catalyst application for use in F<.psgi> files.
 +reference of your Catalyst application for use in a custom F<.psgi> or in your
 +own created server modules.
  
  =cut
  
 +*to_app = \&psgi_app;
 +
  sub psgi_app {
      my ($app) = @_;
      my $psgi = $app->engine->build_psgi_app($app);
@@@ -3497,20 -3049,14 +3512,20 @@@ sub setup_home 
  
  =head2 $c->setup_encoding
  
 -Sets up the input/output encoding.  See L<ENCODING>
 +Sets up the input/output encoding. See L<ENCODING>
  
  =cut
  
  sub setup_encoding {
      my $c = shift;
 -    my $enc = delete $c->config->{encoding};
 -    $c->encoding( $enc ) if defined $enc;
 +    if( exists($c->config->{encoding}) && !defined($c->config->{encoding}) ) {
 +        # Ok, so the user has explicitly said "I don't want encoding..."
 +        return;
 +    } else {
 +      my $enc = defined($c->config->{encoding}) ?
 +        delete $c->config->{encoding} : 'UTF-8'; # not sure why we delete it... (JNAP)
 +      $c->encoding($enc);
 +    }
  }
  
  =head2 handle_unicode_encoding_exception
@@@ -3548,13 -3094,8 +3563,13 @@@ sub _handle_unicode_decoding 
          return $value;
      }
      elsif ( ref $value eq 'HASH' ) {
 -        foreach ( values %$value ) {
 -            $_ = $self->_handle_unicode_decoding($_);
 +        foreach (keys %$value) {
 +            my $encoded_key = $self->_handle_param_unicode_decoding($_);
 +            $value->{$encoded_key} = $self->_handle_unicode_decoding($value->{$_});
 +
 +            # If the key was encoded we now have two (the original and current so
 +            # delete the original.
 +            delete $value->{$_} if $_ ne $encoded_key;
          }
          return $value;
      }
  sub _handle_param_unicode_decoding {
      my ( $self, $value ) = @_;
      return unless defined $value; # not in love with just ignoring undefs - jnap
 +    return $value if blessed($value); #don't decode when the value is an object.
  
      my $enc = $self->encoding;
      return try {
 -        Encode::is_utf8( $value ) ?
 -            $value
 -        : $enc->decode( $value, $self->_encode_check );
 +      $enc->decode( $value, $self->_encode_check );
      }
      catch {
          $self->handle_unicode_encoding_exception({
@@@ -3740,69 -3282,7 +3755,69 @@@ the plugin name does not begin with C<C
              $class => @roles
          ) if @roles;
      }
 -}    
 +}
 +
 +=head2 default_middleware
 +
 +Returns a list of instantiated PSGI middleware objects which is the default
 +middleware that is active for this application (taking any configuration
 +options into account, excluding your custom added middleware via the C<psgi_middleware>
 +configuration option).  You can override this method if you wish to change
 +the default middleware (although do so at risk since some middleware is vital
 +to application function.)
 +
 +The current default middleware list is:
 +
 +      Catalyst::Middleware::Stash
 +      Plack::Middleware::HTTPExceptions
 +      Plack::Middleware::RemoveRedundantBody
 +      Plack::Middleware::FixMissingBodyInRedirect
 +      Plack::Middleware::ContentLength
 +      Plack::Middleware::MethodOverride
 +      Plack::Middleware::Head
 +
 +If the configuration setting C<using_frontend_proxy> is true we add:
 +
 +      Plack::Middleware::ReverseProxy
 +
 +If the configuration setting C<using_frontend_proxy_path> is true we add:
 +
 +      Plack::Middleware::ReverseProxyPath
 +
 +But B<NOTE> that L<Plack::Middleware::ReverseProxyPath> is not a dependency of the
 +L<Catalyst> distribution so if you want to use this option you should add it to
 +your project distribution file.
 +
 +These middlewares will be added at L</setup_middleware> during the
 +L</setup> phase of application startup.
 +
 +=cut
 +
 +sub default_middleware {
 +    my $class = shift;
 +    my @mw = (
 +      Catalyst::Middleware::Stash->new,
 +      Plack::Middleware::HTTPExceptions->new,
 +      Plack::Middleware::RemoveRedundantBody->new,
 +      Plack::Middleware::FixMissingBodyInRedirect->new,
 +      Plack::Middleware::ContentLength->new,
 +      Plack::Middleware::MethodOverride->new,
 +      Plack::Middleware::Head->new);
 +
 +    if($class->config->{using_frontend_proxy}) {
 +        push @mw, Plack::Middleware::ReverseProxy->new;
 +    }
 +
 +    if($class->config->{using_frontend_proxy_path}) {
 +        if(Class::Load::try_load_class('Plack::Middleware::ReverseProxyPath')) {
 +            push @mw, Plack::Middleware::ReverseProxyPath->new;
 +        } else {
 +          $class->log->error("Cannot use configuration 'using_frontend_proxy_path' because 'Plack::Middleware::ReverseProxyPath' is not installed");
 +        }
 +    }
 +
 +    return @mw;
 +}
  
  =head2 registered_middlewares
  
  sub registered_middlewares {
      my $class = shift;
      if(my $middleware = $class->_psgi_middleware) {
 -        return (
 -          Catalyst::Middleware::Stash->new,
 -          Plack::Middleware::HTTPExceptions->new,
 -          Plack::Middleware::RemoveRedundantBody->new,
 -          Plack::Middleware::FixMissingBodyInRedirect->new,
 -          Plack::Middleware::ContentLength->new,
 -          Plack::Middleware::MethodOverride->new,
 -          Plack::Middleware::Head->new,
 -          @$middleware);
 +        my @mw = ($class->default_middleware, @$middleware);
 +
 +        if($class->config->{using_frontend_proxy}) {
 +          push @mw, Plack::Middleware::ReverseProxy->new;
 +        }
 +
 +        return @mw;
      } else {
          die "You cannot call ->registered_middlewares until middleware has been setup";
      }
  
  sub setup_middleware {
      my $class = shift;
 -    my @middleware_definitions = @_ ? 
 -      reverse(@_) : reverse(@{$class->config->{'psgi_middleware'}||[]});
 +    my @middleware_definitions;
 +
 +    # If someone calls this method you can add middleware with args.  However if its
 +    # called without an arg we need to setup the configuration middleware.
 +    if(@_) {
 +      @middleware_definitions = reverse(@_);
 +    } else {
 +      @middleware_definitions = reverse(@{$class->config->{'psgi_middleware'}||[]})
 +        unless $class->finalized_default_middleware;
 +      $class->finalized_default_middleware(1); # Only do this once, just in case some people call setup over and over...
 +    }
  
      my @middleware = ();
      while(my $next = shift(@middleware_definitions)) {
@@@ -3960,34 -3433,12 +3975,34 @@@ sub default_data_handlers 
              ->can('build_cgi_struct')->($params);
        },
        'application/json' => sub {
 -          Class::Load::load_first_existing_class('JSON::MaybeXS', 'JSON')
 -            ->can('decode_json')->(do { local $/; $_->getline });
 -      },
 +          my ($fh, $req) = @_;
 +          my $parser = Class::Load::load_first_existing_class('JSON::MaybeXS', 'JSON');
 +          my $slurped;
 +          return eval { 
 +            local $/;
 +            $slurped = $fh->getline;
 +            $parser->can("decode_json")->($slurped); # decode_json does utf8 decoding for us
 +          } || Catalyst::Exception->throw(sprintf "Error Parsing POST '%s', Error: %s", (defined($slurped) ? $slurped : 'undef') ,$@);
 +        },
      };
  }
  
 +sub _handle_http_exception {
 +    my ( $self, $error ) = @_;
 +    if (
 +           !$self->config->{always_catch_http_exceptions}
 +        && blessed $error
 +        && (
 +            $error->can('as_psgi')
 +            || (   $error->can('code')
 +                && $error->code =~ m/^[1-5][0-9][0-9]$/ )
 +        )
 +      )
 +    {
 +        return 1;
 +    }
 +}
 +
  =head2 $c->stack
  
  Returns an arrayref of the internal execution stack (actions that are
@@@ -4008,33 -3459,6 +4023,33 @@@ by itself
  
  Returns or sets the stats (timing statistics) class. L<Catalyst::Stats|Catalyst::Stats> is used by default.
  
 +=head2 $app->stats_class_traits
 +
 +A arrayref of L<Moose::Role>s that are applied to the stats_class before creating it.
 +
 +=head2 $app->composed_stats_class
 +
 +this is the stats_class composed with any 'stats_class_traits'.  You can
 +name the full namespace of the role, or a namespace suffix, which will then
 +be tried against the following standard namespace prefixes.
 +
 +    $MyApp::TraitFor::Stats::$trait_suffix
 +    Catalyst::TraitFor::Stats::$trait_suffix
 +
 +So for example if you set:
 +
 +    MyApp->stats_class_traits(['Foo']);
 +
 +We try each possible role in turn (and throw an error if none load)
 +
 +    Foo
 +    MyApp::TraitFor::Stats::Foo
 +    Catalyst::TraitFor::Stats::Foo
 +
 +The namespace part 'TraitFor::Stats' was chosen to assist in backwards
 +compatibility with L<CatalystX::RoleApplicator> which previously provided
 +these features in a stand alone package.
 +
  =head2 $c->use_stats
  
  Returns 1 when L<< stats collection|/"-Stats" >> is enabled.
@@@ -4081,13 -3505,6 +4096,13 @@@ There are a number of 'base' config var
  
  =item *
  
 +C<always_catch_http_exceptions> - As of version 5.90060 Catalyst
 +rethrows errors conforming to the interface described by
 +L<Plack::Middleware::HTTPExceptions> and lets the middleware deal with it.
 +Set true to get the deprecated behaviour and have Catalyst catch HTTP exceptions.
 +
 +=item *
 +
  C<default_model> - The default model picked if you say C<< $c->model >>. See L<< /$c->model($name) >>.
  
  =item *
@@@ -4143,7 -3560,7 +4158,7 @@@ to be shown in hit debug tables in the 
  =item *
  
  C<use_request_uri_for_path> - Controls if the C<REQUEST_URI> or C<PATH_INFO> environment
 -variable should be used for determining the request path. 
 +variable should be used for determining the request path.
  
  Most web server environments pass the requested path to the application using environment variables,
  from which Catalyst has to reconstruct the request base (i.e. the top level path to / in the application,
@@@ -4182,7 -3599,7 +4197,7 @@@ is having paths rewritten into it (e.g
  at other URIs than that which the app is 'normally' based at with C<mod_rewrite>), the resolution of
  C<< $c->request->base >> will be incorrect.
  
 -=back 
 +=back
  
  =item *
  
@@@ -4190,20 -3607,8 +4205,20 @@@ C<using_frontend_proxy> - See L</PROXY 
  
  =item *
  
 +C<using_frontend_proxy_path> - Enabled L<Plack::Middleware::ReverseProxyPath> on your application (if
 +installed, otherwise log an error).  This is useful if your application is not running on the
 +'root' (or /) of your host server.  B<NOTE> if you use this feature you should add the required
 +middleware to your project dependency list since its not automatically a dependency of L<Catalyst>.
 +This has been done since not all people need this feature and we wish to restrict the growth of
 +L<Catalyst> dependencies.
 +
 +=item *
 +
  C<encoding> - See L</ENCODING>
  
 +This now defaults to 'UTF-8'.  You my turn it off by setting this configuration
 +value to undef.
 +
  =item *
  
  C<abort_chain_on_error_fix>
@@@ -4212,7 -3617,7 +4227,7 @@@ When there is an error in an action cha
  processing the remaining actions and then catch the error upon chain end.  This
  can lead to running actions when the application is in an unexpected state.  If
  you have this issue, setting this config value to true will promptly exit a
 -chain when there is an error raised in any action (thus terminating the chain 
 +chain when there is an error raised in any action (thus terminating the chain
  early.)
  
  use like:
@@@ -4243,127 -3648,12 +4258,127 @@@ backwardly compatible)
  
  =item *
  
 +C<skip_complex_post_part_handling>
 +
 +When creating body parameters from a POST, if we run into a multipart POST
 +that does not contain uploads, but instead contains inlined complex data
 +(very uncommon) we cannot reliably convert that into field => value pairs.  So
 +instead we create an instance of L<Catalyst::Request::PartData>.  If this causes
 +issue for you, you can disable this by setting C<skip_complex_post_part_handling>
 +to true (default is false).  
 +
 +=item *
 +
 +C<skip_body_param_unicode_decoding>
 +
 +Generally we decode incoming POST params based on your declared encoding (the
 +default for this is to decode UTF-8).  If this is causing you trouble and you
 +do not wish to turn all encoding support off (with the C<encoding> configuration
 +parameter) you may disable this step atomically by setting this configuration
 +parameter to true.
 +
 +=item *
 +
 +C<do_not_decode_query>
 +
 +If true, then do not try to character decode any wide characters in your
 +request URL query or keywords.  Most readings of the relevant specifications
 +suggest these should be UTF-* encoded, which is the default that L<Catalyst>
 +will use, however if you are creating a lot of URLs manually or have external
 +evil clients, this might cause you trouble.  If you find the changes introduced
 +in Catalyst version 5.90080+ break some of your query code, you may disable 
 +the UTF-8 decoding globally using this configuration.
 +
 +This setting takes precedence over C<default_query_encoding> and
 +C<decode_query_using_global_encoding>
 +
 +=item *
 +
 +C<default_query_encoding>
 +
 +By default we decode query and keywords in your request URL using UTF-8, which
 +is our reading of the relevant specifications.  This setting allows one to
 +specify a fixed value for how to decode your query.  You might need this if
 +you are doing a lot of custom encoding of your URLs and not using UTF-8.
 +
 +This setting take precedence over C<decode_query_using_global_encoding>.
 +
 +=item *
 +
 +C<decode_query_using_global_encoding>
 +
 +Setting this to true will default your query decoding to whatever your
 +general global encoding is (the default is UTF-8).
 +
 +=item *
 +
 +C<use_chained_args_0_special_case>
 +
 +In older versions of Catalyst, when more than one action matched the same path
 +AND all those matching actions declared Args(0), we'd break the tie by choosing
 +the first action defined.  We now normalized how Args(0) works so that it
 +follows the same rule as Args(N), which is to say when we need to break a tie
 +we choose the LAST action defined.  If this breaks your code and you don't
 +have time to update to follow the new normalized approach, you may set this
 +value to true and it will globally revert to the original chaining behavior.
 +
 +=item *
 +
  C<psgi_middleware> - See L<PSGI MIDDLEWARE>.
  
  =item *
  
  C<data_handlers> - See L<DATA HANDLERS>.
  
 +=item *
 +
 +C<stats_class_traits>
 +
 +An arrayref of L<Moose::Role>s that get composed into your stats class.
 +
 +=item *
 +
 +C<request_class_traits>
 +
 +An arrayref of L<Moose::Role>s that get composed into your request class.
 +
 +=item *
 +
 +C<response_class_traits>
 +
 +An arrayref of L<Moose::Role>s that get composed into your response class.
 +
 +=item *
 +
 +C<inject_components>
 +
 +A Hashref of L<Catalyst::Component> subclasses that are 'injected' into configuration.
 +For example:
 +
 +    MyApp->config({
 +      inject_components => {
 +        'Controller::Err' => { from_component => 'Local::Controller::Errors' },
 +        'Model::Zoo' => { from_component => 'Local::Model::Foo' },
 +        'Model::Foo' => { from_component => 'Local::Model::Foo', roles => ['TestRole'] },
 +      },
 +      'Controller::Err' => { a => 100, b=>200, namespace=>'error' },
 +      'Model::Zoo' => { a => 2 },
 +      'Model::Foo' => { a => 100 },
 +    });
 +
 +Generally L<Catalyst> looks for components in your Model/View or Controller directories.
 +However for cases when you which to use an existing component and you don't need any
 +customization (where for when you can apply a role to customize it) you may inject those
 +components into your application.  Please note any configuration should be done 'in the
 +normal way', with a key under configuration named after the component affix, as in the
 +above example.
 +
 +Using this type of injection allows you to construct significant amounts of your application
 +with only configuration!.  This may or may not lead to increased code understanding.
 +
 +Please not you may also call the ->inject_components application method as well, although
 +you must do so BEFORE setup.
 +
  =back
  
  =head1 EXCEPTIONS
@@@ -4373,7 -3663,7 +4388,7 @@@ your stack, such as in a model that an 
  is caught by Catalyst and unless you either catch it yourself (via eval
  or something like L<Try::Tiny> or by reviewing the L</error> stack, it
  will eventually reach L</finalize_errors> and return either the debugging
 -error stack page, or the default error page.  However, if your exception 
 +error stack page, or the default error page.  However, if your exception
  can be caught by L<Plack::Middleware::HTTPExceptions>, L<Catalyst> will
  instead rethrow it so that it can be handled by that middleware (which
  is part of the default middleware).  For example this would allow
      sub throws_exception :Local {
        my ($self, $c) = @_;
  
 -      http_throw(SeeOther => { location => 
 +      http_throw(SeeOther => { location =>
          $c->uri_for($self->action_for('redirect')) });
  
      }
@@@ -4661,45 -3951,8 +4676,45 @@@ Please see L<PSGI> for more on middlewa
  
  =head1 ENCODING
  
 -On request, decodes all params from encoding into a sequence of
 -logical characters. On response, encodes body into encoding.
 +Starting in L<Catalyst> version 5.90080 encoding is automatically enabled
 +and set to encode all body responses to UTF8 when possible and applicable.
 +Following is documentation on this process.  If you are using an older
 +version of L<Catalyst> you should review documentation for that version since
 +a lot has changed.
 +
 +By default encoding is now 'UTF-8'.  You may turn it off by setting
 +the encoding configuration to undef.
 +
 +    MyApp->config(encoding => undef);
 +
 +This is recommended for temporary backwards compatibility only.
 +
 +Encoding is automatically applied when the content-type is set to
 +a type that can be encoded.  Currently we encode when the content type
 +matches the following regular expression:
 +
 +    $content_type =~ /^text|xml$|javascript$/
 +
 +Encoding is set on the application, but it is copied to the context object
 +so that you can override it on a request basis.
 +
 +Be default we don't automatically encode 'application/json' since the most
 +common approaches to generating this type of response (Either via L<Catalyst::View::JSON>
 +or L<Catalyst::Action::REST>) will do so already and we want to avoid double
 +encoding issues.
 +
 +If you are producing JSON response in an unconventional manner (such
 +as via a template or manual strings) you should perform the UTF8 encoding
 +manually as well such as to conform to the JSON specification.
 +
 +NOTE: We also examine the value of $c->response->content_encoding.  If
 +you set this (like for example 'gzip', and manually gzipping the body)
 +we assume that you have done all the necessary encoding yourself, since
 +we cannot encode the gzipped contents.  If you use a plugin like
 +L<Catalyst::Plugin::Compress> you need to update to a modern version in order
 +to have this function correctly  with the new UTF8 encoding code, or you
 +can use L<Plack::Middleware::Deflater> or (probably best) do your compression on
 +a front end proxy.
  
  =head2 Methods
  
@@@ -4792,8 -4045,6 +4807,8 @@@ acme: Leon Brocard <leon@astray.com
  
  abraxxa: Alexander Hartmaier <abraxxa@cpan.org>
  
 +andrewalker: AndrĂ© Walker <andre@cpan.org>
 +
  Andrew Bramble
  
  Andrew Ford E<lt>A.Ford@ford-mason.co.ukE<gt>
@@@ -4816,8 -4067,6 +4831,8 @@@ Chisel Wright C<pause@herlpacker.co.uk
  
  Danijel Milicevic C<me@danijel.de>
  
 +davewood: David Schmidt <davewood@cpan.org>
 +
  David Kamholz E<lt>dkamholz@cpan.orgE<gt>
  
  David Naughton, C<naughton@umn.edu>
@@@ -4932,11 -4181,9 +4947,11 @@@ dd070: Dhaval Dhanani <dhaval070@gmail.
  
  Upasana <me@upasana.me>
  
 +John Napiorkowski (jnap) <jjnapiork@cpan.org>
 +
  =head1 COPYRIGHT
  
 -Copyright (c) 2005-2014, the above named PROJECT FOUNDER and CONTRIBUTORS.
 +Copyright (c) 2005-2015, the above named PROJECT FOUNDER and CONTRIBUTORS.
  
  =head1 LICENSE
  
@@@ -60,29 -60,58 +60,82 @@@ is
  );
  
  is(
 +    Catalyst::uri_for( $context, '/bar#fragment', { param1 => 'value1' } )->as_string,
 +    'http://127.0.0.1/foo/bar?param1=value1#fragment',
 +    'URI for path with fragment and query params 1'
 +);
 +
 +is(
 +    Catalyst::uri_for( $context, '0#fragment', { param1 => 'value1' } )->as_string,
 +    'http://127.0.0.1/foo/yada/0?param1=value1#fragment',
 +    'URI for path 0 with fragment and query params 1'
 +);
 +
 +is(
 +    Catalyst::uri_for( $context, '/bar#fragment^%$', { param1 => 'value1' } )->as_string,
 +    'http://127.0.0.1/foo/bar?param1=value1#fragment^%$',
 +    'URI for path with fragment and query params 3'
 +);
 +
 +is(
 +    Catalyst::uri_for( $context, '/foo#bar/baz', { param1 => 'value1' } )->as_string,
 +    'http://127.0.0.1/foo/foo?param1=value1#bar/baz',
 +    'URI for path with fragment and query params 3'
 +);
 +
++is(
+     Catalyst::uri_for( 'TestApp', '/bar/baz' )->as_string,
+     '/bar/baz',
+     'URI for absolute path, called with only class name'
+ );
+ ## relative action (or path) doesn't make sense when calling as class method
+ # is(
+ #     Catalyst::uri_for( 'TestApp', 'bar/baz' )->as_string,
+ #     '/yada/bar/baz',
+ #     'URI for relative path, called with only class name'
+ # );
+ is(
+     Catalyst::uri_for( 'TestApp', '/', 'arg1', 'arg2' )->as_string,
+     '/arg1/arg2',
+     'URI for root action with args, called with only class name'
+ );
+ ## relative action (or path) doesn't make sense when calling as class method
+ # is( Catalyst::uri_for( 'TestApp', '../quux' )->as_string,
+ #     '/quux', 'URI for relative dot path, called with only class name' );
+ is(
+     Catalyst::uri_for( 'TestApp', '/quux', { param1 => 'value1' } )->as_string,
+     '/quux?param1=value1',
+     'URI for quux action with query params, called with only class name'
+ );
+ is (Catalyst::uri_for( 'TestApp', '/bar/wibble?' )->as_string,
+    '/bar/wibble%3F', 'Question Mark gets encoded, called with only class name'
+ );
+ ## relative action (or path) doesn't make sense when calling as class method
+ # is( Catalyst::uri_for( 'TestApp', qw/bar wibble?/, 'with space' )->as_string,
+ #     '/yada/bar/wibble%3F/with%20space', 'Space gets encoded, called with only class name'
+ # );
+ is(
+     Catalyst::uri_for( 'TestApp', '/bar', 'with+plus', { 'also' => 'with+plus' })->as_string,
+     '/bar/with+plus?also=with%2Bplus',
+     'Plus is not encoded, called with only class name'
+ );
+ TODO: {
+     local $TODO = 'broken by 5.7008';
+     is(
+         Catalyst::uri_for( $context, '/bar#fragment', { param1 => 'value1' } )->as_string,
+         'http://127.0.0.1/foo/bar?param1=value1#fragment',
+         'URI for path with fragment and query params'
+     );
+ }
  # test with utf-8
  is(
      Catalyst::uri_for( $context, 'quux', { param1 => "\x{2620}" } )->as_string,
@@@ -100,26 -129,7 +153,26 @@@ is
      Catalyst::uri_for( $context, 'quux', { param1 => $request->base } )->as_string,
      'http://127.0.0.1/foo/yada/quux?param1=http%3A%2F%2F127.0.0.1%2Ffoo',
      'URI for undef action with query param as object'
 -);
 +  );
 +
 +# test with empty arg
 +{
 +    my @warnings;
 +    local $SIG{__WARN__} = sub { push @warnings, @_ };
 +    is(
 +       Catalyst::uri_for( $context )->as_string,
 +       'http://127.0.0.1/foo/yada',
 +       'URI with no action'
 +      );
 +
 +    is(
 +       Catalyst::uri_for( $context, 0 )->as_string,
 +       'http://127.0.0.1/foo/yada/0',
 +       'URI with 0 path'
 +      );
 +
 +    is_deeply(\@warnings, [], "No warnings with no path argument");
 +}
  
  $request->base( URI->new('http://localhost:3000/') );
  $request->match( 'orderentry/contract' );