The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Build.PL 24
Changes 036
MANIFEST 142
META.json 6061
META.yml 6061
Makefile.PL 46
lib/Dancer2/CLI/Command/gen.pm 22
lib/Dancer2/CLI/Command/version.pm 22
lib/Dancer2/CLI.pm 22
lib/Dancer2/Config.pod 22
lib/Dancer2/Cookbook.pod 22
lib/Dancer2/Core/App.pm 4389
lib/Dancer2/Core/Cookie.pm 22
lib/Dancer2/Core/DSL.pm 216
lib/Dancer2/Core/Dispatcher.pm 23
lib/Dancer2/Core/Error.pm 22
lib/Dancer2/Core/Factory.pm 53
lib/Dancer2/Core/HTTP.pm 22
lib/Dancer2/Core/Hook.pm 22
lib/Dancer2/Core/MIME.pm 22
lib/Dancer2/Core/Request/Upload.pm 22
lib/Dancer2/Core/Request.pm 22
lib/Dancer2/Core/Response.pm 333
lib/Dancer2/Core/Role/ConfigReader.pm 22
lib/Dancer2/Core/Role/DSL.pm 22
lib/Dancer2/Core/Role/Engine.pm 311
lib/Dancer2/Core/Role/Handler.pm 22
lib/Dancer2/Core/Role/HasLocation.pm 22
lib/Dancer2/Core/Role/Headers.pm 22
lib/Dancer2/Core/Role/Hookable.pm 22
lib/Dancer2/Core/Role/Logger.pm 33
lib/Dancer2/Core/Role/Serializer.pm 22
lib/Dancer2/Core/Role/SessionFactory/File.pm 22
lib/Dancer2/Core/Role/SessionFactory.pm 22
lib/Dancer2/Core/Role/StandardResponses.pm 22
lib/Dancer2/Core/Role/Template.pm 1313
lib/Dancer2/Core/Route.pm 22
lib/Dancer2/Core/Runner.pm 22
lib/Dancer2/Core/Session.pm 22
lib/Dancer2/Core/Time.pm 22
lib/Dancer2/Core/Types.pm 22
lib/Dancer2/Core.pm 22
lib/Dancer2/FileUtils.pm 22
lib/Dancer2/Handler/AutoPage.pm 33
lib/Dancer2/Handler/File.pm 22
lib/Dancer2/Logger/Capture/Trap.pm 22
lib/Dancer2/Logger/Capture.pm 22
lib/Dancer2/Logger/Console.pm 22
lib/Dancer2/Logger/Diag.pm 22
lib/Dancer2/Logger/File.pm 1916
lib/Dancer2/Logger/Note.pm 22
lib/Dancer2/Logger/Null.pm 22
lib/Dancer2/Manual/Migration.pod 25
lib/Dancer2/Manual.pod 223
lib/Dancer2/Plugin/Ajax.pm 22
lib/Dancer2/Plugin.pm 22
lib/Dancer2/Plugins.pod 22
lib/Dancer2/Policy.pod 0119
lib/Dancer2/Serializer/Dumper.pm 22
lib/Dancer2/Serializer/JSON.pm 22
lib/Dancer2/Serializer/Mutable.pm 54
lib/Dancer2/Serializer/YAML.pm 22
lib/Dancer2/Session/Simple.pm 22
lib/Dancer2/Session/YAML.pm 22
lib/Dancer2/Template/Implementation/ForkedTiny.pm 22
lib/Dancer2/Template/Simple.pm 22
lib/Dancer2/Template/TemplateToolkit.pm 22
lib/Dancer2/Template/Tiny.pm 22
lib/Dancer2/Test.pm 22
lib/Dancer2/Tutorial.pod 22
lib/Dancer2.pm 55
script/dancer2 11
t/00-report-prereqs.dd 12
t/author-no-tabs.t 142
t/classes/Dancer2/import.t 0265
t/classes/Dancer2-Core/camelize.t 024
t/classes/Dancer2-Core-Factory/create.t 017
t/classes/Dancer2-Core-Hook/base.t 070
t/classes/Dancer2-Core-Response/new_from.t 080
t/classes/Dancer2-Core-Role-Engine/base.t 022
t/classes/Dancer2-Core-Role-Handler/base.t 021
t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/bin/.exists 00
t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/lib/fake/inner/dir/.exists 00
t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/.dancer 00
t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/fakescript.pl 00
t/classes/Dancer2-Core-Role-HasLocation/base.t 090
t/classes/Dancer2-Core-Role-StandardResponses/base.t 0171
t/classes/Dancer2-Core-Runner/base.t 0246
t/classes/Dancer2-Core-Runner/environment.t 038
t/classes/Dancer2-Core-Runner/psgi_app.t 092
t/dsl/content.t 077
t/issues/gh-634.t 0120
t/issues/gh-723.t 057
t/issues/gh-730.t 072
t/logger/file.t 100
t/session_hooks.t 111
t/session_in_template.t 079
t/sessions/VD8wIQAAIErosiPuPzgc7Feo60_y7s2K.yml 02
t/sessions/VD8xFwAAIfVHBp2nUIRlhPrHBxZFewkg.yml 02
t/sessions/VD8xPwAAIqUQa3U0CK_Q43bf7JSaXj68.yml 02
t/sessions/VDf4nIP4n0A4Ya5vcE7SaaDntyVZj9oB.yml 02
t/sessions/VDfsgXhalKhiOdSVDEk4iwyf_j3JJ1lU.yml 02
t/sessions/VDgFcPJynjsERU0GCt8fE9hhT-R3ErKV.yml 02
t/sessions/VDgH-lQYfi_XUNztQLT-6ebJ_gzwGZKp.yml 02
t/sessions/VDgHth9A4cXrh0fLlBodXUMnCXkcPlOO.yml 02
t/sessions/VDsBvbCel9L5vqAA8X12v_IKYwpqtEIb.yml 02
t/sessions/VDsC67174msADj1P2kEtWWWWqenpf_Gh.yml 02
t/sessions/VDsdec7YkN_t5HYgYTY4UTO0rGbd3quL.yml 02
t/sessions/VDskH-mTqVSrtI7vn3Cfjc22M3sDZ4nf.yml 02
t/sessions/VDxpkwmXPxXgntfDkSbIJIW3-ZmOV6F2.yml 02
t/sessions/VDxr8vlFwjuihF5Oq6qfdcX_C-sqJFst.yml 02
t/sessions/VDxsUBz1JAMQos-edO9ShtnKnIqjRugy.yml 02
t/sessions/VDxszUJNZJrCm2146wLcBL4Tauj5tlx3.yml 02
t/sessions/VDxtWd3557qlVPhU5y4QeEnoTzopT4XL.yml 02
t/sessions/VDxuf7UcBT5V58xfDyZ2akeLCE0stVRe.yml 02
t/sessions/VEcEMgAADIiqAdXb4PP-YxIqDskws7Qd.yml 02
t/views/session_in_template.tt 01
117 files changed (This is a version diff) 3702282
@@ -20,7 +20,7 @@ my %module_build_args = (
     "Dancer Core Developers"
   ],
   "dist_name" => "Dancer2",
-  "dist_version" => "0.151000",
+  "dist_version" => "0.153000",
   "license" => "perl",
   "module_name" => "Dancer2",
   "recommends" => {
@@ -72,7 +72,7 @@ my %module_build_args = (
     "MooX::Types::MooseLike" => "0.16",
     "MooX::Types::MooseLike::Base" => 0,
     "POSIX" => 0,
-    "Plack" => "1.0016",
+    "Plack" => "1.0029",
     "Plack::Builder" => 0,
     "Pod::Simple::Search" => 0,
     "Pod::Simple::SimpleTree" => 0,
@@ -112,6 +112,7 @@ my %module_build_args = (
     "IO::Handle" => 0,
     "IPC::Open3" => 0,
     "LWP::Protocol::PSGI" => "0.06",
+    "Plack::Response" => 0,
     "Plack::Test" => 0,
     "Test::Fatal" => 0,
     "Test::Memory::Cycle" => "1.04",
@@ -141,6 +142,7 @@ my %fallback_build_requires = (
   "IPC::Open3" => 0,
   "LWP::Protocol::PSGI" => "0.06",
   "Module::Build" => "0.3601",
+  "Plack::Response" => 0,
   "Plack::Test" => 0,
   "Test::Fatal" => 0,
   "Test::Memory::Cycle" => "1.04",
@@ -1,3 +1,39 @@
+0.153000  2014-10-23 23:45:36+02:00 Europe/Amsterdam
+
+    [ ENHANCEMENT ]
+    * Internal: Move the implementation of send_file from DSL to App.
+      (Russell Jenkins)
+
+    [ BUG FIXES ]
+    * GH #634, #687: Fix file logger defaults.
+      (Russell Jenkins, Dávid Kovács, Sawyer X)
+    * GH #730: Make App use app-level config for behind_proxy. (Sawyer X)
+    * GH #727: Disable regex metachars when calculating app location in tests
+      (Gregor Herrmann)
+    * GH #681, #682, #712: Clear session engine within destroy_session.
+      (DavX, Russell Jenkins)
+    * Ignore :tests in importing, don't suggest :script. (Sawyer X)
+
+    [ DOCUMENTATION ]
+    * GH #728: Typos in Policy document. (Olaf Alders, Sawyer X)
+
+0.152000  2014-10-14 04:30:59+02:00 Europe/Amsterdam
+
+    [ BUG FIXES ]
+    * GH #723: Redispatched requests lose data. (Sawyer X)
+
+    [ ENHANCEMENT ]
+    * Provide 'content' keyword to set the response content. (Sawyer x)
+    * GH #616, #155, #615: Session engines are now lazy! (Russell Jenkins)
+    * Dancer2 response objects can be created from arrays or from
+      Plack::Response objects. (Sawyer X)
+    * GH #718: Clean up App's Template engine. (Russell Jenkins)
+    * Adding class-based tests. (Sawyer X)
+
+    [ DOCUMENTATION ]
+    * Add a policy document under Dancer2::Policy. (Sawyer X)
+    * Document log_format instead of logger_format. (Sawyer X)
+
 0.151000  2014-10-08 21:49:06+02:00 Europe/Amsterdam
 
     [ ENHANCEMENT ]
@@ -62,6 +62,7 @@ lib/Dancer2/Manual/Migration.pod
 lib/Dancer2/Plugin.pm
 lib/Dancer2/Plugin/Ajax.pm
 lib/Dancer2/Plugins.pod
+lib/Dancer2/Policy.pod
 lib/Dancer2/Serializer/Dumper.pm
 lib/Dancer2/Serializer/JSON.pm
 lib/Dancer2/Serializer/Mutable.pm
@@ -114,8 +115,24 @@ t/author-no-tabs.t
 t/auto_page.t
 t/caller.t
 t/charset_server.t
+t/classes/Dancer2-Core-Factory/create.t
+t/classes/Dancer2-Core-Hook/base.t
+t/classes/Dancer2-Core-Response/new_from.t
+t/classes/Dancer2-Core-Role-Engine/base.t
+t/classes/Dancer2-Core-Role-Handler/base.t
+t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/bin/.exists
 t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/blib/bin/.exists
 t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/blib/lib/fakescript.pl
+t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/lib/fake/inner/dir/.exists
+t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/.dancer
+t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/fakescript.pl
+t/classes/Dancer2-Core-Role-HasLocation/base.t
+t/classes/Dancer2-Core-Role-StandardResponses/base.t
+t/classes/Dancer2-Core-Runner/base.t
+t/classes/Dancer2-Core-Runner/environment.t
+t/classes/Dancer2-Core-Runner/psgi_app.t
+t/classes/Dancer2-Core/camelize.t
+t/classes/Dancer2/import.t
 t/config.yml
 t/config/config.yml
 t/config/environments/failure.yml
@@ -138,6 +155,7 @@ t/dancer-test/config.yml
 t/deserialize.t
 t/dispatcher.t
 t/dsl.t
+t/dsl/content.t
 t/dsl/extend.t
 t/dsl/extend_config/config.yml
 t/dsl/halt.t
@@ -155,6 +173,9 @@ t/handler_file.t
 t/hooks.t
 t/http_methods.t
 t/http_status.t
+t/issues/gh-634.t
+t/issues/gh-723.t
+t/issues/gh-730.t
 t/lib/App1.pm
 t/lib/App2.pm
 t/lib/DancerPlugin.pm
@@ -170,7 +191,6 @@ t/lib/TestPod.pm
 t/log_die_before_hook.t
 t/log_levels.t
 t/logger.t
-t/logger/file.t
 t/logger_console.t
 t/lwp-protocol-psgi.t
 t/memory_cycles.t
@@ -206,10 +226,30 @@ t/session_config.t
 t/session_engines.t
 t/session_forward.t
 t/session_hooks.t
+t/session_in_template.t
 t/session_lifecycle.t
 t/session_object.t
 t/sessions/VBzn5-yKiV0ZEaZqEtEvK_pmMT8n4QQx.yml
+t/sessions/VD8wIQAAIErosiPuPzgc7Feo60_y7s2K.yml
+t/sessions/VD8xFwAAIfVHBp2nUIRlhPrHBxZFewkg.yml
+t/sessions/VD8xPwAAIqUQa3U0CK_Q43bf7JSaXj68.yml
 t/sessions/VDKr30YvCd7R3WEniUv5Re5999E6SJmQ.yml
+t/sessions/VDf4nIP4n0A4Ya5vcE7SaaDntyVZj9oB.yml
+t/sessions/VDfsgXhalKhiOdSVDEk4iwyf_j3JJ1lU.yml
+t/sessions/VDgFcPJynjsERU0GCt8fE9hhT-R3ErKV.yml
+t/sessions/VDgH-lQYfi_XUNztQLT-6ebJ_gzwGZKp.yml
+t/sessions/VDgHth9A4cXrh0fLlBodXUMnCXkcPlOO.yml
+t/sessions/VDsBvbCel9L5vqAA8X12v_IKYwpqtEIb.yml
+t/sessions/VDsC67174msADj1P2kEtWWWWqenpf_Gh.yml
+t/sessions/VDsdec7YkN_t5HYgYTY4UTO0rGbd3quL.yml
+t/sessions/VDskH-mTqVSrtI7vn3Cfjc22M3sDZ4nf.yml
+t/sessions/VDxpkwmXPxXgntfDkSbIJIW3-ZmOV6F2.yml
+t/sessions/VDxr8vlFwjuihF5Oq6qfdcX_C-sqJFst.yml
+t/sessions/VDxsUBz1JAMQos-edO9ShtnKnIqjRugy.yml
+t/sessions/VDxszUJNZJrCm2146wLcBL4Tauj5tlx3.yml
+t/sessions/VDxtWd3557qlVPhU5y4QeEnoTzopT4XL.yml
+t/sessions/VDxuf7UcBT5V58xfDyZ2akeLCE0stVRe.yml
+t/sessions/VEcEMgAADIiqAdXb4PP-YxIqDskws7Qd.yml
 t/shared_engines.t
 t/splat.t
 t/template.t
@@ -258,6 +298,7 @@ t/views/beforetemplate.tt
 t/views/folder/page.tt
 t/views/index.tt
 t/views/layouts/main.tt
+t/views/session_in_template.tt
 t/views/template_simple_index.tt
 t/views/tokens.tt
 xt/perlcritic.rc
@@ -83,7 +83,7 @@
             "MooX::Types::MooseLike" : "0.16",
             "MooX::Types::MooseLike::Base" : "0",
             "POSIX" : "0",
-            "Plack" : "1.0016",
+            "Plack" : "1.0029",
             "Plack::Builder" : "0",
             "Pod::Simple::Search" : "0",
             "Pod::Simple::SimpleTree" : "0",
@@ -127,6 +127,7 @@
             "IO::Handle" : "0",
             "IPC::Open3" : "0",
             "LWP::Protocol::PSGI" : "0.06",
+            "Plack::Response" : "0",
             "Plack::Test" : "0",
             "Test::Fatal" : "0",
             "Test::Memory::Cycle" : "1.04",
@@ -145,235 +146,235 @@
    "provides" : {
       "Dancer2" : {
          "file" : "lib/Dancer2.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::CLI" : {
          "file" : "lib/Dancer2/CLI.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::CLI::Command::gen" : {
          "file" : "lib/Dancer2/CLI/Command/gen.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::CLI::Command::version" : {
          "file" : "lib/Dancer2/CLI/Command/version.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core" : {
          "file" : "lib/Dancer2/Core.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::App" : {
          "file" : "lib/Dancer2/Core/App.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Cookie" : {
          "file" : "lib/Dancer2/Core/Cookie.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::DSL" : {
          "file" : "lib/Dancer2/Core/DSL.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Dispatcher" : {
          "file" : "lib/Dancer2/Core/Dispatcher.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Error" : {
          "file" : "lib/Dancer2/Core/Error.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Factory" : {
          "file" : "lib/Dancer2/Core/Factory.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::HTTP" : {
          "file" : "lib/Dancer2/Core/HTTP.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Hook" : {
          "file" : "lib/Dancer2/Core/Hook.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::MIME" : {
          "file" : "lib/Dancer2/Core/MIME.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Request" : {
          "file" : "lib/Dancer2/Core/Request.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Request::Upload" : {
          "file" : "lib/Dancer2/Core/Request/Upload.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Response" : {
          "file" : "lib/Dancer2/Core/Response.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::ConfigReader" : {
          "file" : "lib/Dancer2/Core/Role/ConfigReader.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::DSL" : {
          "file" : "lib/Dancer2/Core/Role/DSL.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Engine" : {
          "file" : "lib/Dancer2/Core/Role/Engine.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Handler" : {
          "file" : "lib/Dancer2/Core/Role/Handler.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::HasLocation" : {
          "file" : "lib/Dancer2/Core/Role/HasLocation.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Headers" : {
          "file" : "lib/Dancer2/Core/Role/Headers.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Hookable" : {
          "file" : "lib/Dancer2/Core/Role/Hookable.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Logger" : {
          "file" : "lib/Dancer2/Core/Role/Logger.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Serializer" : {
          "file" : "lib/Dancer2/Core/Role/Serializer.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::SessionFactory" : {
          "file" : "lib/Dancer2/Core/Role/SessionFactory.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::SessionFactory::File" : {
          "file" : "lib/Dancer2/Core/Role/SessionFactory/File.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::StandardResponses" : {
          "file" : "lib/Dancer2/Core/Role/StandardResponses.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Role::Template" : {
          "file" : "lib/Dancer2/Core/Role/Template.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Route" : {
          "file" : "lib/Dancer2/Core/Route.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Runner" : {
          "file" : "lib/Dancer2/Core/Runner.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Session" : {
          "file" : "lib/Dancer2/Core/Session.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Time" : {
          "file" : "lib/Dancer2/Core/Time.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Core::Types" : {
          "file" : "lib/Dancer2/Core/Types.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::FileUtils" : {
          "file" : "lib/Dancer2/FileUtils.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Handler::AutoPage" : {
          "file" : "lib/Dancer2/Handler/AutoPage.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Handler::File" : {
          "file" : "lib/Dancer2/Handler/File.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::Capture" : {
          "file" : "lib/Dancer2/Logger/Capture.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::Capture::Trap" : {
          "file" : "lib/Dancer2/Logger/Capture/Trap.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::Console" : {
          "file" : "lib/Dancer2/Logger/Console.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::Diag" : {
          "file" : "lib/Dancer2/Logger/Diag.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::File" : {
          "file" : "lib/Dancer2/Logger/File.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::Note" : {
          "file" : "lib/Dancer2/Logger/Note.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Logger::Null" : {
          "file" : "lib/Dancer2/Logger/Null.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Plugin" : {
          "file" : "lib/Dancer2/Plugin.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Plugin::Ajax" : {
          "file" : "lib/Dancer2/Plugin/Ajax.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Serializer::Dumper" : {
          "file" : "lib/Dancer2/Serializer/Dumper.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Serializer::JSON" : {
          "file" : "lib/Dancer2/Serializer/JSON.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Serializer::Mutable" : {
          "file" : "lib/Dancer2/Serializer/Mutable.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Serializer::YAML" : {
          "file" : "lib/Dancer2/Serializer/YAML.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Session::Simple" : {
          "file" : "lib/Dancer2/Session/Simple.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Session::YAML" : {
          "file" : "lib/Dancer2/Session/YAML.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Template::Implementation::ForkedTiny" : {
          "file" : "lib/Dancer2/Template/Implementation/ForkedTiny.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Template::Simple" : {
          "file" : "lib/Dancer2/Template/Simple.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Template::TemplateToolkit" : {
          "file" : "lib/Dancer2/Template/TemplateToolkit.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Template::Tiny" : {
          "file" : "lib/Dancer2/Template/Tiny.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       },
       "Dancer2::Test" : {
          "file" : "lib/Dancer2/Test.pm",
-         "version" : "0.151000"
+         "version" : "0.153000"
       }
    },
    "release_status" : "stable",
@@ -390,6 +391,6 @@
       "x_IRC" : "irc://irc.perl.org/#dancer",
       "x_WebIRC" : "https://chat.mibbit.com/#dancer@irc.perl.org"
    },
-   "version" : "0.151000"
+   "version" : "0.153000"
 }
 
@@ -15,6 +15,7 @@ build_requires:
   IPC::Open3: 0
   LWP::Protocol::PSGI: 0.06
   Module::Build: 0.3601
+  Plack::Response: 0
   Plack::Test: 0
   Test::Fatal: 0
   Test::Memory::Cycle: 1.04
@@ -41,178 +42,178 @@ name: Dancer2
 provides:
   Dancer2:
     file: lib/Dancer2.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::CLI:
     file: lib/Dancer2/CLI.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::CLI::Command::gen:
     file: lib/Dancer2/CLI/Command/gen.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::CLI::Command::version:
     file: lib/Dancer2/CLI/Command/version.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core:
     file: lib/Dancer2/Core.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::App:
     file: lib/Dancer2/Core/App.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Cookie:
     file: lib/Dancer2/Core/Cookie.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::DSL:
     file: lib/Dancer2/Core/DSL.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Dispatcher:
     file: lib/Dancer2/Core/Dispatcher.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Error:
     file: lib/Dancer2/Core/Error.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Factory:
     file: lib/Dancer2/Core/Factory.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::HTTP:
     file: lib/Dancer2/Core/HTTP.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Hook:
     file: lib/Dancer2/Core/Hook.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::MIME:
     file: lib/Dancer2/Core/MIME.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Request:
     file: lib/Dancer2/Core/Request.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Request::Upload:
     file: lib/Dancer2/Core/Request/Upload.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Response:
     file: lib/Dancer2/Core/Response.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::ConfigReader:
     file: lib/Dancer2/Core/Role/ConfigReader.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::DSL:
     file: lib/Dancer2/Core/Role/DSL.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Engine:
     file: lib/Dancer2/Core/Role/Engine.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Handler:
     file: lib/Dancer2/Core/Role/Handler.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::HasLocation:
     file: lib/Dancer2/Core/Role/HasLocation.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Headers:
     file: lib/Dancer2/Core/Role/Headers.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Hookable:
     file: lib/Dancer2/Core/Role/Hookable.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Logger:
     file: lib/Dancer2/Core/Role/Logger.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Serializer:
     file: lib/Dancer2/Core/Role/Serializer.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::SessionFactory:
     file: lib/Dancer2/Core/Role/SessionFactory.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::SessionFactory::File:
     file: lib/Dancer2/Core/Role/SessionFactory/File.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::StandardResponses:
     file: lib/Dancer2/Core/Role/StandardResponses.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Role::Template:
     file: lib/Dancer2/Core/Role/Template.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Route:
     file: lib/Dancer2/Core/Route.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Runner:
     file: lib/Dancer2/Core/Runner.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Session:
     file: lib/Dancer2/Core/Session.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Time:
     file: lib/Dancer2/Core/Time.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Core::Types:
     file: lib/Dancer2/Core/Types.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::FileUtils:
     file: lib/Dancer2/FileUtils.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Handler::AutoPage:
     file: lib/Dancer2/Handler/AutoPage.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Handler::File:
     file: lib/Dancer2/Handler/File.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::Capture:
     file: lib/Dancer2/Logger/Capture.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::Capture::Trap:
     file: lib/Dancer2/Logger/Capture/Trap.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::Console:
     file: lib/Dancer2/Logger/Console.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::Diag:
     file: lib/Dancer2/Logger/Diag.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::File:
     file: lib/Dancer2/Logger/File.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::Note:
     file: lib/Dancer2/Logger/Note.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Logger::Null:
     file: lib/Dancer2/Logger/Null.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Plugin:
     file: lib/Dancer2/Plugin.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Plugin::Ajax:
     file: lib/Dancer2/Plugin/Ajax.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Serializer::Dumper:
     file: lib/Dancer2/Serializer/Dumper.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Serializer::JSON:
     file: lib/Dancer2/Serializer/JSON.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Serializer::Mutable:
     file: lib/Dancer2/Serializer/Mutable.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Serializer::YAML:
     file: lib/Dancer2/Serializer/YAML.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Session::Simple:
     file: lib/Dancer2/Session/Simple.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Session::YAML:
     file: lib/Dancer2/Session/YAML.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Template::Implementation::ForkedTiny:
     file: lib/Dancer2/Template/Implementation/ForkedTiny.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Template::Simple:
     file: lib/Dancer2/Template/Simple.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Template::TemplateToolkit:
     file: lib/Dancer2/Template/TemplateToolkit.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Template::Tiny:
     file: lib/Dancer2/Template/Tiny.pm
-    version: 0.151000
+    version: 0.153000
   Dancer2::Test:
     file: lib/Dancer2/Test.pm
-    version: 0.151000
+    version: 0.153000
 recommends:
   CGI::Deurl::XS: 0
   Crypt::URandom: 0
@@ -260,7 +261,7 @@ requires:
   MooX::Types::MooseLike: 0.16
   MooX::Types::MooseLike::Base: 0
   POSIX: 0
-  Plack: 1.0016
+  Plack: 1.0029
   Plack::Builder: 0
   Pod::Simple::Search: 0
   Pod::Simple::SimpleTree: 0
@@ -287,4 +288,4 @@ resources:
   bugtracker: https://github.com/PerlDancer/Dancer2/issues
   homepage: http://perldancer.org/
   repository: https://github.com/PerlDancer/Dancer2
-version: 0.151000
+version: 0.153000
@@ -66,7 +66,7 @@ my %WriteMakefileArgs = (
     "MooX::Types::MooseLike" => "0.16",
     "MooX::Types::MooseLike::Base" => 0,
     "POSIX" => 0,
-    "Plack" => "1.0016",
+    "Plack" => "1.0029",
     "Plack::Builder" => 0,
     "Pod::Simple::Search" => 0,
     "Pod::Simple::SimpleTree" => 0,
@@ -99,6 +99,7 @@ my %WriteMakefileArgs = (
     "IO::Handle" => 0,
     "IPC::Open3" => 0,
     "LWP::Protocol::PSGI" => "0.06",
+    "Plack::Response" => 0,
     "Plack::Test" => 0,
     "Test::Fatal" => 0,
     "Test::Memory::Cycle" => "1.04",
@@ -111,9 +112,9 @@ my %WriteMakefileArgs = (
     "utf8" => 0,
     "vars" => 0
   },
-  "VERSION" => "0.151000",
+  "VERSION" => "0.153000",
   "test" => {
-    "TESTS" => "t/*.t t/dsl/*.t t/logger/*.t t/roles/*.t t/route-pod-coverage/*.t t/template_tiny/*.t"
+    "TESTS" => "t/*.t t/classes/Dancer2-Core-Factory/*.t t/classes/Dancer2-Core-Hook/*.t t/classes/Dancer2-Core-Response/*.t t/classes/Dancer2-Core-Role-Engine/*.t t/classes/Dancer2-Core-Role-Handler/*.t t/classes/Dancer2-Core-Role-HasLocation/*.t t/classes/Dancer2-Core-Role-StandardResponses/*.t t/classes/Dancer2-Core-Runner/*.t t/classes/Dancer2-Core/*.t t/classes/Dancer2/*.t t/dsl/*.t t/issues/*.t t/roles/*.t t/route-pod-coverage/*.t t/template_tiny/*.t"
   }
 );
 
@@ -163,8 +164,9 @@ my %FallbackPrereqs = (
   "MooX::Types::MooseLike" => "0.16",
   "MooX::Types::MooseLike::Base" => 0,
   "POSIX" => 0,
-  "Plack" => "1.0016",
+  "Plack" => "1.0029",
   "Plack::Builder" => 0,
+  "Plack::Response" => 0,
   "Plack::Test" => 0,
   "Pod::Simple::Search" => 0,
   "Pod::Simple::SimpleTree" => 0,
@@ -1,6 +1,6 @@
 # ABSTRACT: create new Dancer2 application
 package Dancer2::CLI::Command::gen;
-$Dancer2::CLI::Command::gen::VERSION = '0.151000';
+$Dancer2::CLI::Command::gen::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -279,7 +279,7 @@ Dancer2::CLI::Command::gen - create new Dancer2 application
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::CLI::Command::version;
 # ABSTRACT: display version
-$Dancer2::CLI::Command::version::VERSION = '0.151000';
+$Dancer2::CLI::Command::version::VERSION = '0.153000';
 use App::Cmd::Setup -command;
 
 sub description { 'Display version of Dancer2' }
@@ -29,7 +29,7 @@ Dancer2::CLI::Command::version - display version
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::CLI;
 # ABSTRACT: Dancer2 cli application
-$Dancer2::CLI::VERSION = '0.151000';
+$Dancer2::CLI::VERSION = '0.153000';
 use App::Cmd::Setup -app;
 
 1;
@@ -17,7 +17,7 @@ Dancer2::CLI - Dancer2 cli application
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Config;
 # ABSTRACT: Configure Dancer2 to suit your needs
-$Dancer2::Config::VERSION = '0.151000';
+$Dancer2::Config::VERSION = '0.153000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Config - Configure Dancer2 to suit your needs
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Cookbook;
 # ABSTRACT: Example-driven quick-start to the Dancer2 web framework
-$Dancer2::Cookbook::VERSION = '0.151000';
+$Dancer2::Cookbook::VERSION = '0.153000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Cookbook - Example-driven quick-start to the Dancer2 web framework
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 # ABSTRACT: encapsulation of Dancer2 packages
 package Dancer2::Core::App;
-$Dancer2::Core::App::VERSION = '0.151000';
+$Dancer2::Core::App::VERSION = '0.153000';
 use Moo;
 use Carp               'croak';
 use Scalar::Util       'blessed';
@@ -13,11 +13,12 @@ use Plack::Builder;
 use Dancer2::FileUtils 'path';
 use Dancer2::Core;
 use Dancer2::Core::Cookie;
+use Dancer2::Core::Error;
 use Dancer2::Core::Types;
 use Dancer2::Core::Route;
 use Dancer2::Core::Hook;
 use Dancer2::Core::Request;
-
+use Dancer2::Core::Factory;
 
 # we have hooks here
 with 'Dancer2::Core::Role::Hookable';
@@ -25,6 +26,13 @@ with 'Dancer2::Core::Role::ConfigReader';
 
 sub supported_engines { [ qw<logger serializer session template> ] }
 
+has _factory => (
+    is      => 'ro',
+    isa     => Object['Dancer2::Core::Factory'],
+    lazy    => 1,
+    default => sub { Dancer2::Core::Factory->new },
+);
+
 has logger_engine => (
     is      => 'ro',
     isa     => Maybe[ConsumerOf['Dancer2::Core::Role::Logger']],
@@ -57,6 +65,16 @@ has serializer_engine => (
     writer  => 'set_serializer_engine',
 );
 
+sub defined_engines {
+    my $self = shift;
+    return map {
+        my $type   = "${_}_engine";
+        my $engine = $self->$type;
+
+        defined $engine ? $engine : ()
+    } @{ $self->supported_engines };
+}
+
 has '+local_triggers' => (
     default => sub {
         my $self     = shift;
@@ -126,9 +144,11 @@ sub _build_logger_engine {
     my $engine_options =
         $self->_get_config_for_engine( logger => $value, $config );
 
-    my $logger = Dancer2::Core::Factory->create(
+    my $logger = $self->_factory->create(
         logger => $value,
         %{$engine_options},
+        location        => $self->config_location,
+        environment     => $self->environment,
         app_name        => $self->name,
         postponed_hooks => $self->get_postponed_hooks
     );
@@ -154,7 +174,7 @@ sub _build_session_engine {
     my $engine_options =
           $self->_get_config_for_engine( session => $value, $config );
 
-    return Dancer2::Core::Factory->create(
+    return $self->_factory->create(
         session => $value,
         %{$engine_options},
         postponed_hooks => $self->get_postponed_hooks,
@@ -183,7 +203,7 @@ sub _build_template_engine {
     $engine_attrs->{views}  ||= $config->{views}
         || path( $self->location, 'views' );
 
-    return Dancer2::Core::Factory->create(
+    return $self->_factory->create(
         template => $value,
         %{$engine_attrs},
         postponed_hooks => $self->get_postponed_hooks,
@@ -204,7 +224,7 @@ sub _build_serializer_engine {
     my $engine_options =
         $self->_get_config_for_engine( serializer => $value, $config );
 
-    return Dancer2::Core::Factory->create(
+    return $self->_factory->create(
         serializer      => $value,
         config          => $engine_options,
         postponed_hooks => $self->get_postponed_hooks,
@@ -357,9 +377,11 @@ sub destroy_session {
     $session->expires(-86400);    # yesterday
     $engine->destroy( id => $session->id );
 
-    # Clear session and invalidate session cookie in request
+    # Invalidate session cookie in request
+    # and clear session in app and engines
     $self->set_destroyed_session($session);
     $self->clear_session;
+    $_->clear_session for $self->defined_engines;
 
     return;
 }
@@ -367,10 +389,7 @@ sub destroy_session {
 sub setup_session {
     my $self = shift;
 
-    for my $type ( @{ $self->supported_engines } ) {
-        my $attr   = "${type}_engine";
-        my $engine = $self->$attr or next;
-
+    for my $engine ( $self->defined_engines ) {
         $self->has_session                         ?
             $engine->set_session( $self->session ) :
             $engine->clear_session;
@@ -518,10 +537,23 @@ sub _init_hooks {
                 # session, first flush the session so cookie-based sessions can
                 # update the session ID if needed, then set the session cookie
                 # in the response
+                #
+                # if there is NO session object but the request has a cookie with
+                # a session key, create a dummy session with the same ID (without
+                # actually retrieving and flushing immediately) and generate the
+                # cookie header from the dummy session. Lazy Sessions FTW!
 
                 if ( $app->has_session ) {
-                    my $session = $app->session;
-                    $session->is_dirty and $engine->flush( session => $session );
+                    my $session;
+                    if ( $app->_has_session ) { # Session object exists
+                        $session = $app->session;
+                        $session->is_dirty and $engine->flush( session => $session );
+                    }
+                    else { # Cookie header exists. Create a dummy session object
+                        my $cookie = $app->cookie( $engine->cookie_name );
+                        my $session_id = $cookie->value;
+                        $session = Dancer2::Core::Session->new( id => $session_id );
+                    }
                     $engine->set_cookie_header(
                         response => $response,
                         session  => $session
@@ -575,6 +607,11 @@ sub cleanup {
     $self->clear_response;
     $self->clear_session;
     $self->clear_destroyed_session;
+    # Clear engine attributes
+    for my $engine ( $self->defined_engines ) {
+        $engine->clear_session;
+        $engine->clear_request;
+    }
 }
 
 sub engine {
@@ -595,18 +632,13 @@ sub template {
     $template->set_settings( $self->config );
 
     # return content
-    return $template->process( $self->request, @_ );
+    return $template->process( @_ );
 }
 
 sub hook_candidates {
     my $self = shift;
 
-    my @engines;
-    for my $e ( @{ $self->supported_engines } ) {
-        my $attr   = "${e}_engine";
-        my $engine = $self->$attr or next;
-        push @engines, $engine;
-    }
+    my @engines = $self->defined_engines;
 
     my @route_handlers;
     for my $handler ( @{ $self->route_handlers } ) {
@@ -653,6 +685,23 @@ sub log {
     $logger->$level(@_);
 }
 
+sub send_error {
+    my $self = shift;
+    my ( $message, $status ) = @_;
+
+    my $serializer = $self->engine('serializer');
+    my $err = Dancer2::Core::Error->new(
+          message    => $message,
+          app        => $self,
+        ( status     => $status     )x!! $status,
+        ( serializer => $serializer )x!! $serializer,
+    )->throw;
+
+    # Immediately return to dispatch if with_return coderef exists
+    $self->has_with_return && $self->with_return->($err);
+    return $err;
+}
+
 sub send_file {
     my $self    = shift;
     my $path    = shift;
@@ -675,7 +724,7 @@ sub send_file {
     # pretending it's a file (on-the-fly file sending)
     ref $path eq 'SCALAR' and return $$path;
 
-    my $file_handler = Dancer2::Core::Factory->create(
+    my $file_handler = $self->_factory->create(
         Handler => 'File',
         app     => $self,
         postponed_hooks => $self->postponed_hooks,
@@ -718,7 +767,7 @@ sub init_route_handlers {
         my ($handler_name, $config) = @{$handler_data};
         $config = {} if !ref($config);
 
-        my $handler = Dancer2::Core::Factory->create(
+        my $handler = $self->_factory->create(
             Handler => $handler_name,
             app     => $self,
             %$config,
@@ -1008,7 +1057,9 @@ DISPATCH:
 
             $request->_set_route_params($match);
 
+            # Add request to app and engines
             $self->set_request($request);
+            $_->set_request( $request ) for $self->defined_engines;
 
             # Add session to app *if* we have a session and the request
             # has the appropriate cookie header for _this_ app.
@@ -1072,6 +1123,10 @@ DISPATCH:
                     and delete $request->{_params}{splat};
 
                 $response->has_passed(0); # clear for the next round
+
+                # clear the content because if you pass it,
+                # the next route is in charge of catching it
+                $response->clear_content;
                 next ROUTE;
             }
 
@@ -1091,7 +1146,13 @@ DISPATCH:
 
     # make sure Core::Dispatcher recognizes this failure
     # so it can try the next Core::App
-    Dancer2->runner->{'internal_404'} = 1;
+    # and set the created request so we don't create it again
+    # (this is important so we don't ignore the previous body)
+    if ( Dancer2->runner->{'internal_dispatch'} ) {
+        Dancer2->runner->{'internal_404'}     = 1;
+        Dancer2->runner->{'internal_request'} = $request;
+    }
+
     return $self->response_not_found($request);
 }
 
@@ -1102,19 +1163,10 @@ sub build_request {
     my $engine  = $self->serializer_engine;
     my $request = Dancer2::Core::Request->new(
           env             => $env,
-          is_behind_proxy => Dancer2->runner->config->{'behind_proxy'} || 0,
+          is_behind_proxy => $self->settings->{'behind_proxy'} || 0,
         ( serializer      => $engine )x!! $engine,
     );
 
-    # if it's a mutable serializer, we add more headers
-    # so it can be set properly
-    # I don't like doing this... -- Sawyer
-    if ( $engine->$_isa('Dancer2::Serializer::Mutable') ) {
-        $engine->{'extra_headers'} = {
-            map +( $_ => $request->$_ ), qw<content_type accept accept_type>
-        }
-    }
-
     # Log deserialization errors
     if ($engine) {
         $engine->has_error and $self->log(
@@ -1130,9 +1182,6 @@ sub build_request {
 sub _dispatch_route {
     my ( $self, $route ) = @_;
 
-    # FIXME: check for memory leak here
-    # perhaps we need to weaken $self, perhaps not
-    # would it matter if we do? could it be a problem?
     $self->execute_hook( 'core.app.before_request', $self );
     my $response = $self->response;
 
@@ -1142,22 +1191,19 @@ sub _dispatch_route {
         $content = $response->content;
     }
     else {
-        # FIXME: check for memory leak here
-        # perhaps we need to weaken $self, perhaps not
-        # would it matter if we do? could it be a problem?
         $content = eval { $route->execute($self) };
 
         my $error = $@;
         if ($error) {
             $self->log( error => "Route exception: $error" );
-            # FIXME: check for memory leak here
-            # perhaps we need to weaken $self, perhaps not
-            # would it matter if we do? could it be a problem?
             $self->execute_hook( 'core.app.route_exception', $self, $error );
             return $self->response_internal_error($error);
         }
     }
 
+    $response->has_content
+        and $content = $response->content;
+
     if ( ref $content eq 'Dancer2::Core::Response' ) {
         $response = $self->set_response($content);
     }
@@ -1219,7 +1265,7 @@ Dancer2::Core::App - encapsulation of Dancer2 packages
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Cookie;
 # ABSTRACT: A cookie representing class
-$Dancer2::Core::Cookie::VERSION = '0.151000';
+$Dancer2::Core::Cookie::VERSION = '0.153000';
 use Moo;
 use URI::Escape;
 use Dancer2::Core::Types;
@@ -106,7 +106,7 @@ Dancer2::Core::Cookie - A cookie representing class
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,12 +1,11 @@
 # ABSTRACT: Dancer2's Domain Specific Language (DSL)
 
 package Dancer2::Core::DSL;
-$Dancer2::Core::DSL::VERSION = '0.151000';
+$Dancer2::Core::DSL::VERSION = '0.153000';
 use Moo;
 use Carp;
 use Class::Load 'load_class';
 use Dancer2::Core::Hook;
-use Dancer2::Core::Error;
 use Dancer2::FileUtils;
 
 with 'Dancer2::Core::Role::DSL';
@@ -20,6 +19,7 @@ sub dsl_keywords {
         app                  => { is_global => 1 },
         captures             => { is_global => 0 },
         config               => { is_global => 1 },
+        content              => { is_global => 0 },
         content_type         => { is_global => 0 },
         context              => { is_global => 0 },
         cookie               => { is_global => 0 },
@@ -142,6 +142,8 @@ sub session {
     }
 }
 
+sub send_error { shift->app->send_error(@_) }
+
 sub send_file { shift->app->send_file(@_) }
 
 #
@@ -291,6 +293,7 @@ sub status       { shift->response->status(@_) }
 sub push_header  { shift->response->push_header(@_) }
 sub header       { shift->response->header(@_) }
 sub headers      { shift->response->header(@_) }
+sub content      { shift->response->content(@_) }
 sub content_type { shift->response->content_type(@_) }
 sub pass         { shift->app->pass }
 
@@ -341,24 +344,6 @@ sub mime {
     }
 }
 
-sub send_error {
-    my ( $self, $message, $status ) = @_;
-
-    my $serializer = $self->app->engine('serializer');
-    my $x = Dancer2::Core::Error->new(
-          message    => $message,
-          app        => $self->app,
-        ( status     => $status     )x!! $status,
-        ( serializer => $serializer )x!! $serializer,
-    )->throw;
-
-    # return if there is a with_return coderef
-    $self->app->with_return->($x)
-      if $self->app->has_with_return;
-
-    return $x;
-}
-
 #
 # engines
 #
@@ -415,7 +400,7 @@ Dancer2::Core::DSL - Dancer2's Domain Specific Language (DSL)
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 FUNCTIONS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Dispatcher;
 # ABSTRACT: Class for dispatching request to the appropriate route handler
-$Dancer2::Core::Dispatcher::VERSION = '0.151000';
+$Dancer2::Core::Dispatcher::VERSION = '0.153000';
 use Moo;
 
 use Dancer2::Core::Types;
@@ -46,6 +46,7 @@ sub dispatch {
         }
 
         # don't run anymore
+        delete Dancer2->runner->{'internal_request'};
         last;
     } # while
 
@@ -69,7 +70,7 @@ Dancer2::Core::Dispatcher - Class for dispatching request to the appropriate rou
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Error;
 # ABSTRACT: Class representing fatal errors
-$Dancer2::Core::Error::VERSION = '0.151000';
+$Dancer2::Core::Error::VERSION = '0.153000';
 use Moo;
 use Carp;
 use Dancer2::Core::Types;
@@ -488,7 +488,7 @@ Dancer2::Core::Error - Class representing fatal errors
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,9 +1,7 @@
 package Dancer2::Core::Factory;
 # ABSTRACT: Instantiate components by type and name
-$Dancer2::Core::Factory::VERSION = '0.151000';
-use strict;
-use warnings;
-
+$Dancer2::Core::Factory::VERSION = '0.153000';
+use Moo;
 use Dancer2::Core;
 use Class::Load 'try_load_class';
 use Carp 'croak';
@@ -35,7 +33,7 @@ Dancer2::Core::Factory - Instantiate components by type and name
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,7 +1,7 @@
 # ABSTRACT: helper for rendering HTTP status codes for Dancer2
 
 package Dancer2::Core::HTTP;
-$Dancer2::Core::HTTP::VERSION = '0.151000';
+$Dancer2::Core::HTTP::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -134,7 +134,7 @@ Dancer2::Core::HTTP - helper for rendering HTTP status codes for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 FUNCTIONS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Hook;
 # ABSTRACT: Manipulate hooks with Dancer2
-$Dancer2::Core::Hook::VERSION = '0.151000';
+$Dancer2::Core::Hook::VERSION = '0.153000';
 use Moo;
 use Dancer2::Core::Types;
 use Carp;
@@ -51,7 +51,7 @@ Dancer2::Core::Hook - Manipulate hooks with Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Class to ease manipulation of MIME types
 
 package Dancer2::Core::MIME;
-$Dancer2::Core::MIME::VERSION = '0.151000';
+$Dancer2::Core::MIME::VERSION = '0.153000';
 use Moo;
 
 use MIME::Types;
@@ -90,7 +90,7 @@ Dancer2::Core::MIME - Class to ease manipulation of MIME types
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Request::Upload;
 # ABSTRACT: Class representing file upload requests
-$Dancer2::Core::Request::Upload::VERSION = '0.151000';
+$Dancer2::Core::Request::Upload::VERSION = '0.153000';
 use Moo;
 
 use Carp;
@@ -91,7 +91,7 @@ Dancer2::Core::Request::Upload - Class representing file upload requests
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Dancer2::Core::Request;
-$Dancer2::Core::Request::VERSION = '0.151000';
+$Dancer2::Core::Request::VERSION = '0.153000';
 # ABSTRACT: Interface for accessing incoming requests
 
 use Moo;
@@ -714,7 +714,7 @@ Dancer2::Core::Request - Interface for accessing incoming requests
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Response object for Dancer2
 
 package Dancer2::Core::Response;
-$Dancer2::Core::Response::VERSION = '0.151000';
+$Dancer2::Core::Response::VERSION = '0.153000';
 use Moo;
 
 use Encode;
@@ -69,7 +69,6 @@ has status => (
 has content => (
     is      => 'rw',
     isa     => Str,
-    default => sub {''},
     coerce  => sub {
         my $value = shift;
         return "$value";
@@ -82,6 +81,9 @@ has content => (
         $self->has_passed or $self->header( 'Content-Length' => length($value) );
         return $value;
     },
+
+    predicate => 'has_content',
+    clearer   => 'clear_content',
 );
 
 before content => sub {
@@ -118,6 +120,26 @@ sub encode_content {
     return $content;
 }
 
+sub new_from_plack {
+    my ($self, $psgi_res) = @_;
+
+    return Dancer2::Core::Response->new(
+        status  => $psgi_res->status,
+        headers => $psgi_res->headers,
+        content => $psgi_res->body,
+    );
+}
+
+sub new_from_array {
+    my ($self, $arrayref) = @_;
+
+    return Dancer2::Core::Response->new(
+        status  => $arrayref->[0],
+        headers => $arrayref->[1],
+        content => $arrayref->[2][0],
+    );
+}
+
 sub to_psgi {
     my ($self) = @_;
     # It is possible to have no content and/or no content type set
@@ -201,7 +223,7 @@ Dancer2::Core::Response - Response object for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 ATTRIBUTES
 
@@ -254,6 +276,14 @@ Interally, it uses the L<is_encoded> flag to make sure that content is not encod
 If it encodes the content, then it will return the encoded content.  In all other
 cases it returns C<false>.
 
+=head2 new_from_plack
+
+Creates a new response object from a L<Plack::Response> object.
+
+=head2 new_from_array
+
+Creates a new response object from a PSGI arrayref.
+
 =head2 to_psgi
 
 Converts the response object to a PSGI array.
@@ -1,6 +1,6 @@
 # ABSTRACT: Config role for Dancer2 core objects
 package Dancer2::Core::Role::ConfigReader;
-$Dancer2::Core::Role::ConfigReader::VERSION = '0.151000';
+$Dancer2::Core::Role::ConfigReader::VERSION = '0.153000';
 use Moo::Role;
 
 use File::Spec;
@@ -274,7 +274,7 @@ Dancer2::Core::Role::ConfigReader - Config role for Dancer2 core objects
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::DSL;
 # ABSTRACT: Role for DSL
-$Dancer2::Core::Role::DSL::VERSION = '0.151000';
+$Dancer2::Core::Role::DSL::VERSION = '0.153000';
 use Moo::Role;
 use Dancer2::Core::Types;
 use Carp 'croak';
@@ -106,7 +106,7 @@ Dancer2::Core::Role::DSL - Role for DSL
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Engine;
 # ABSTRACT: Role for engines
-$Dancer2::Core::Role::Engine::VERSION = '0.151000';
+$Dancer2::Core::Role::Engine::VERSION = '0.153000';
 use Moo::Role;
 use Dancer2::Core::Types;
 
@@ -15,11 +15,19 @@ has session => (
 );
 
 has config => (
-    is      => 'rw',
+    is      => 'ro',
     isa     => HashRef,
     default => sub { {} },
 );
 
+has request => (
+    is        => 'ro',
+    isa       => InstanceOf['Dancer2::Core::Request'],
+    writer    => 'set_request',
+    clearer   => 'clear_request',
+    predicate => 'has_request',
+);
+
 1;
 
 __END__
@@ -34,7 +42,7 @@ Dancer2::Core::Role::Engine - Role for engines
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Handler;
 # ABSTRACT: Role for Handlers
-$Dancer2::Core::Role::Handler::VERSION = '0.151000';
+$Dancer2::Core::Role::Handler::VERSION = '0.153000';
 use Moo::Role;
 use Dancer2::Core::Types;
 
@@ -26,7 +26,7 @@ Dancer2::Core::Role::Handler - Role for Handlers
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 ATTRIBUTES
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::HasLocation;
 # ABSTRACT: Role for application location "guessing"
-$Dancer2::Core::Role::HasLocation::VERSION = '0.151000';
+$Dancer2::Core::Role::HasLocation::VERSION = '0.153000';
 use Moo::Role;
 use Dancer2::Core::Types;
 use Dancer2::FileUtils;
@@ -84,7 +84,7 @@ Dancer2::Core::Role::HasLocation - Role for application location "guessing"
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Role for handling headers
 
 package Dancer2::Core::Role::Headers;
-$Dancer2::Core::Role::Headers::VERSION = '0.151000';
+$Dancer2::Core::Role::Headers::VERSION = '0.153000';
 use Moo::Role;
 use Dancer2::Core::Types;
 use HTTP::Headers;
@@ -77,7 +77,7 @@ Dancer2::Core::Role::Headers - Role for handling headers
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Hookable;
 # ABSTRACT: Role for hookable objects
-$Dancer2::Core::Role::Hookable::VERSION = '0.151000';
+$Dancer2::Core::Role::Hookable::VERSION = '0.153000';
 use Moo::Role;
 use Dancer2::Core;
 use Dancer2::Core::Types;
@@ -156,7 +156,7 @@ Dancer2::Core::Role::Hookable - Role for hookable objects
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Logger;
 # ABSTRACT: Role for logger engines
-$Dancer2::Core::Role::Logger::VERSION = '0.151000';
+$Dancer2::Core::Role::Logger::VERSION = '0.153000';
 use Dancer2::Core::Types;
 
 use Moo::Role;
@@ -177,7 +177,7 @@ Dancer2::Core::Role::Logger - Role for logger engines
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -302,7 +302,7 @@ You can change it either in your config.yml file:
     logger: "console"
 
 The log format can also be configured,
-please see L<Dancer2::Core::Role::Logger/"logger_format"> for details.
+please see L<Dancer2::Core::Role::Logger/"log_format"> for details.
 
 =head1 METHODS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Serializer;
 # ABSTRACT: Role for Serializer engines
-$Dancer2::Core::Role::Serializer::VERSION = '0.151000';
+$Dancer2::Core::Role::Serializer::VERSION = '0.153000';
 use Dancer2::Core::Types;
 use Moo::Role;
 
@@ -78,7 +78,7 @@ Dancer2::Core::Role::Serializer - Role for Serializer engines
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::SessionFactory::File;
 #ABSTRACT: Role for file-based session factories
-$Dancer2::Core::Role::SessionFactory::File::VERSION = '0.151000';
+$Dancer2::Core::Role::SessionFactory::File::VERSION = '0.153000';
 use strict;
 use warnings;
 use Carp 'croak';
@@ -113,7 +113,7 @@ Dancer2::Core::Role::SessionFactory::File - Role for file-based session factorie
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::SessionFactory;
 #ABSTRACT: Role for session factories
-$Dancer2::Core::Role::SessionFactory::VERSION = '0.151000';
+$Dancer2::Core::Role::SessionFactory::VERSION = '0.153000';
 use strict;
 use warnings;
 use Carp 'croak';
@@ -254,7 +254,7 @@ Dancer2::Core::Role::SessionFactory - Role for session factories
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::StandardResponses;
 # ABSTRACT: Role to provide commonly used responses
-$Dancer2::Core::Role::StandardResponses::VERSION = '0.151000';
+$Dancer2::Core::Role::StandardResponses::VERSION = '0.153000';
 use Moo::Role;
 
 sub response {
@@ -39,7 +39,7 @@ Dancer2::Core::Role::StandardResponses - Role to provide commonly used responses
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 METHODS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Role for template engines
 
 package Dancer2::Core::Role::Template;
-$Dancer2::Core::Role::Template::VERSION = '0.151000';
+$Dancer2::Core::Role::Template::VERSION = '0.153000';
 use Dancer2::Core::Types;
 use Dancer2::FileUtils qw'path';
 use Carp 'croak';
@@ -101,9 +101,9 @@ sub render_layout {
 }
 
 sub apply_renderer {
-    my ( $self, $request, $view, $tokens ) = @_;
+    my ( $self, $view, $tokens ) = @_;
     $view = $self->view_pathname($view) if !ref $view;
-    $tokens = $self->_prepare_tokens_options($request,$tokens);
+    $tokens = $self->_prepare_tokens_options( $tokens );
 
     $self->execute_hook( 'engine.template.before_render', $tokens );
 
@@ -116,9 +116,9 @@ sub apply_renderer {
 }
 
 sub apply_layout {
-    my ( $self, $request, $content, $tokens, $options ) = @_;
+    my ( $self, $content, $tokens, $options ) = @_;
 
-    $tokens = $self->_prepare_tokens_options( $request, $tokens );
+    $tokens = $self->_prepare_tokens_options( $tokens );
 
    # If 'layout' was given in the options hashref, use it if it's a true value,
    # or don't use a layout if it was false (0, or undef); if layout wasn't
@@ -150,7 +150,7 @@ sub apply_layout {
 }
 
 sub _prepare_tokens_options {
-    my ( $self, $request, $tokens ) = @_;
+    my ( $self, $tokens ) = @_;
 
     # these are the default tokens provided for template processing
     $tokens ||= {};
@@ -158,9 +158,9 @@ sub _prepare_tokens_options {
     $tokens->{dancer_version} = Dancer2->VERSION;
 
     $tokens->{settings} = $self->settings;
-    $tokens->{request}  = $request;
-    $tokens->{params}   = $request->params;
-    $tokens->{vars}     = $request->vars;
+    $tokens->{request}  = $self->request;
+    $tokens->{params}   = $self->request->params;
+    $tokens->{vars}     = $self->request->vars;
 
     $tokens->{session} = $self->session->data
       if $self->has_session;
@@ -169,7 +169,7 @@ sub _prepare_tokens_options {
 }
 
 sub process {
-    my ( $self, $request, $view, $tokens, $options ) = @_;
+    my ( $self, $view, $tokens, $options ) = @_;
     my ( $content, $full_content );
 
     # it's important that $tokens is not undef, so that things added to it via
@@ -181,11 +181,11 @@ sub process {
 
     $content =
         $view
-      ? $self->apply_renderer( $request, $view, $tokens )
+      ? $self->apply_renderer( $view, $tokens )
       : delete $options->{content};
 
     defined $content
-      and $full_content = $self->apply_layout( $request, $content, $tokens, $options );
+      and $full_content = $self->apply_layout( $content, $tokens, $options );
 
     defined $full_content
       and return $full_content;
@@ -207,7 +207,7 @@ Dancer2::Core::Role::Template - Role for template engines
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Dancer2's route handler
 
 package Dancer2::Core::Route;
-$Dancer2::Core::Route::VERSION = '0.151000';
+$Dancer2::Core::Route::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -228,7 +228,7 @@ Dancer2::Core::Route - Dancer2's route handler
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 ATTRIBUTES
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Runner;
 # ABSTRACT: Top-layer class to start a dancer app
-$Dancer2::Core::Runner::VERSION = '0.151000';
+$Dancer2::Core::Runner::VERSION = '0.153000';
 use Moo;
 use Carp 'croak';
 use Dancer2::Core::MIME;
@@ -260,7 +260,7 @@ Dancer2::Core::Runner - Top-layer class to start a dancer app
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Dancer2::Core::Session;
-$Dancer2::Core::Session::VERSION = '0.151000';
+$Dancer2::Core::Session::VERSION = '0.153000';
 #ABSTRACT: class to represent any session object
 
 use strict;
@@ -71,7 +71,7 @@ Dancer2::Core::Session - class to represent any session object
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Time;
 #ABSTRACT: class to handle common helpers for time manipulations
-$Dancer2::Core::Time::VERSION = '0.151000';
+$Dancer2::Core::Time::VERSION = '0.153000';
 use Moo;
 
 has seconds => (
@@ -134,7 +134,7 @@ Dancer2::Core::Time - class to handle common helpers for time manipulations
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Types;
 # ABSTRACT: Moo types for Dancer2 core.
-$Dancer2::Core::Types::VERSION = '0.151000';
+$Dancer2::Core::Types::VERSION = '0.153000';
 use strict;
 use warnings;
 use Scalar::Util 'blessed', 'looks_like_number';
@@ -148,7 +148,7 @@ Dancer2::Core::Types - Moo types for Dancer2 core.
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core;
 # ABSTRACT: Core libraries for Dancer2 2.0
-$Dancer2::Core::VERSION = '0.151000';
+$Dancer2::Core::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -29,7 +29,7 @@ Dancer2::Core - Core libraries for Dancer2 2.0
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 FUNCTIONS
 
@@ -1,6 +1,6 @@
 package Dancer2::FileUtils;
 # ABSTRACT: File utility helpers
-$Dancer2::FileUtils::VERSION = '0.151000';
+$Dancer2::FileUtils::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -101,7 +101,7 @@ Dancer2::FileUtils - File utility helpers
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Handler::AutoPage;
 # ABSTRACT: Class for handling the AutoPage feature
-$Dancer2::Handler::AutoPage::VERSION = '0.151000';
+$Dancer2::Handler::AutoPage::VERSION = '0.153000';
 use Moo;
 use Carp 'croak';
 use Dancer2::Core::Types;
@@ -40,7 +40,7 @@ sub code {
             return;
         }
 
-        my $ct = $template->process( $app->request, $page );
+        my $ct = $template->process( $page );
         $app->response->header( 'Content-Length', length($ct) );
         return ( $app->request->method eq 'GET' ) ? $ct : '';
     };
@@ -64,7 +64,7 @@ Dancer2::Handler::AutoPage - Class for handling the AutoPage feature
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Handler::File;
 # ABSTRACT: class for handling file content rendering
-$Dancer2::Handler::File::VERSION = '0.151000';
+$Dancer2::Handler::File::VERSION = '0.153000';
 use Carp 'croak';
 use Moo;
 use HTTP::Date;
@@ -147,7 +147,7 @@ Dancer2::Handler::File - class for handling file content rendering
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Capture::Trap;
 # ABSTRACT: a place to store captured Dancer2 logs
-$Dancer2::Logger::Capture::Trap::VERSION = '0.151000';
+$Dancer2::Logger::Capture::Trap::VERSION = '0.153000';
 use Moo;
 use Dancer2::Core::Types;
 
@@ -37,7 +37,7 @@ Dancer2::Logger::Capture::Trap - a place to store captured Dancer2 logs
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Capture;
 # ABSTRACT: Capture dancer logs
-$Dancer2::Logger::Capture::VERSION = '0.151000';
+$Dancer2::Logger::Capture::VERSION = '0.153000';
 use Moo;
 use Dancer2::Logger::Capture::Trap;
 
@@ -35,7 +35,7 @@ Dancer2::Logger::Capture - Capture dancer logs
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Console;
 # ABSTRACT: Console logger
-$Dancer2::Logger::Console::VERSION = '0.151000';
+$Dancer2::Logger::Console::VERSION = '0.153000';
 use Moo;
 
 with 'Dancer2::Core::Role::Logger';
@@ -24,7 +24,7 @@ Dancer2::Logger::Console - Console logger
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Diag;
 # ABSTRACT: Test::More diag() logging engine for Dancer2
-$Dancer2::Logger::Diag::VERSION = '0.151000';
+$Dancer2::Logger::Diag::VERSION = '0.153000';
 use Moo;
 use Test::More;
 
@@ -26,7 +26,7 @@ Dancer2::Logger::Diag - Test::More diag() logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::File;
 # ABSTRACT: file-based logging engine for Dancer2
-$Dancer2::Logger::File::VERSION = '0.151000';
+$Dancer2::Logger::File::VERSION = '0.153000';
 use Carp 'carp';
 use Moo;
 use Dancer2::Core::Types;
@@ -12,33 +12,30 @@ use Fcntl qw(:flock SEEK_END);
 use Dancer2::FileUtils qw(open_file);
 use IO::File;
 
-# FIXME: this is not a good way to do this
 has environment => (
-    is      => 'ro',
-    lazy    => 1,
-    default => sub { $_[0]->app->environment },
+    is       => 'ro',
+    required => 1,
 );
 
-# FIXME: this is not a good way to do this
 has location => (
-    is      => 'ro',
-    lazy    => 1,
-    default => sub { $_[0]->app->config_location },
+    is       => 'ro',
+    required => 1,
 );
 
 has log_dir => (
     is      => 'rw',
-    isa     => Str,
-    lazy    => 1,
-    builder => '_build_log_dir',
-    trigger => sub {
-        my ( $self, $dir ) = @_;
+    isa     => sub {
+        my $dir = shift;
+
         if ( !-d $dir && !mkdir $dir ) {
-            return carp
-              "Log directory \"$dir\" does not exist and unable to create it.";
+            die "log directory \"$dir\" does not exist and unable to create it.";
+        }
+        if ( !-w $dir ) {
+            die "log directory \"$dir\" is not writable."
         }
-        return carp "Log directory \"$dir\" is not writable." if !-w $dir;
     },
+    lazy    => 1,
+    builder => '_build_log_dir',
 );
 
 has file_name => (
@@ -61,7 +58,7 @@ has fh => (
     builder => '_build_fh',
 );
 
-sub _build_log_dir {File::Spec->catdir( $_[0]->location, 'logs' )}
+sub _build_log_dir { File::Spec->catdir( $_[0]->location, 'logs' ) }
 
 sub _build_file_name {$_[0]->environment . ".log"}
 
@@ -114,7 +111,7 @@ Dancer2::Logger::File - file-based logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Note;
 # ABSTRACT: Test::More note() logging engine for Dancer2
-$Dancer2::Logger::Note::VERSION = '0.151000';
+$Dancer2::Logger::Note::VERSION = '0.153000';
 use Moo;
 use Test::More;
 
@@ -26,7 +26,7 @@ Dancer2::Logger::Note - Test::More note() logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Null;
 # ABSTRACT: Blackhole-like silent logging engine for Dancer2
-$Dancer2::Logger::Null::VERSION = '0.151000';
+$Dancer2::Logger::Null::VERSION = '0.153000';
 use Moo;
 with 'Dancer2::Core::Role::Logger';
 
@@ -20,7 +20,7 @@ Dancer2::Logger::Null - Blackhole-like silent logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Manual::Migration;
 # ABSTRACT: Migrating from Dancer to Dancer2
-$Dancer2::Manual::Migration::VERSION = '0.151000';
+$Dancer2::Manual::Migration::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -18,7 +18,7 @@ Dancer2::Manual::Migration - Migrating from Dancer to Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head2 Migration from Dancer1 to Dancer2
 
@@ -151,6 +151,9 @@ Other modules that could be used for testing are:
 
 =head4 Logs
 
+The C<logger_format> in the Logger role (L<Dancer2::Core::Role::Logger>)
+is now C<log_format>.
+
 C<read_logs> can no longer be used, as with L<Dancer2::Test>. Instead,
 L<Dancer2::Logger::Capture> could be used for testing, to capture all
 logs to an object.
@@ -1,6 +1,6 @@
 # ABSTRACT: A gentle introduction to Dancer2
 package Dancer2::Manual;
-$Dancer2::Manual::VERSION = '0.151000';
+$Dancer2::Manual::VERSION = '0.153000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Manual - A gentle introduction to Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -885,6 +885,23 @@ Accesses the configuration of the application:
         return "This is " . config->{appname};
     };
 
+=head2 content
+
+Sets the content for the response.
+
+    get '/' => sub {
+        content 'Hello, world!';
+
+        # the return value of the route is ignored
+        return 'Ignored String';
+    };
+
+Once you set the content using the keyword, your return value (which
+is usually the content) is ignored.
+
+B<WARNING> : If you are using the C<pass> keyword, the last route will be
+in charge of setting the content.
+
 =head2 content_type
 
 Sets the B<content-type> rendered, for the current route handler:
@@ -1181,6 +1198,10 @@ route.  So it's not necessary anymore to use C<return> with pass.
         }
     };
 
+B<WARNING> : You cannot set the content before passing and have it remain,
+even if you use the C<content> keyword or set it directly in the response
+object.
+
 =head2 patch
 
 Defines a route for HTTP B<PATCH> requests to the given URL:
@@ -1,7 +1,7 @@
 # ABSTRACT: a plugin for adding Ajax route handlers
 
 package Dancer2::Plugin::Ajax;
-$Dancer2::Plugin::Ajax::VERSION = '0.151000';
+$Dancer2::Plugin::Ajax::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -63,7 +63,7 @@ Dancer2::Plugin::Ajax - a plugin for adding Ajax route handlers
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Plugin;
 # ABSTRACT: Extending Dancer2's DSL with plugins
-$Dancer2::Plugin::VERSION = '0.151000';
+$Dancer2::Plugin::VERSION = '0.153000';
 use Moo::Role;
 use Carp 'croak', 'carp';
 use Dancer2::Core::DSL;
@@ -251,7 +251,7 @@ Dancer2::Plugin - Extending Dancer2's DSL with plugins
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Plugins;
 # ABSTRACT: Recommended Dancer2 plugins
-$Dancer2::Plugins::VERSION = '0.151000';
+$Dancer2::Plugins::VERSION = '0.153000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Plugins - Recommended Dancer2 plugins
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -0,0 +1,119 @@
+package Dancer2::Policy;
+# ABSTRACT: Dancer core and community policy and standards of conduct
+$Dancer2::Policy::VERSION = '0.153000';
+use strict;
+use warnings;
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Dancer2::Policy - Dancer core and community policy and standards of conduct
+
+=head1 VERSION
+
+version 0.153000
+
+=head1 DESCRIPTION
+
+This document describes various policies (most notably, the standards
+of conduct) for the Dancer core developers and broad community.
+
+This is what we expect from our community and ourselves and these are
+the standards of behavior we set forth in order to make sure the community
+remains a safe space for all of its members, without exception.
+
+=head1 STANDARDS OF CONDUCT
+
+These standards apply anywhere the community comes together as a group.
+This includes, but is not limited to, the Dancer IRC channel, the Dancer
+mailing list, Dancer hackathons, and Dancer conferences.
+
+=over 4
+
+=item *
+
+Always be civil.
+
+=item *
+
+Heed the moderators.
+
+=item *
+
+Abuse is not tolerated.
+
+=back
+
+Civility is simple: stick to the facts while avoiding demeaning remarks and
+sarcasm. It is not enough to be factual. You must also be civil. Responding
+in kind to incivility is not acceptable.
+
+If the list moderators tell you that you are not being civil, carefully
+consider how your words have appeared before responding in any way. You may
+protest, but repeated protest in the face of a repeatedly reaffirmed decision
+is not acceptable.
+
+Unacceptable behavior will result in a public and clearly identified warning.
+Repeated unacceptable behavior will result in removal from the mailing list and
+revocation of any commit bit. The first removal is for one month. Subsequent
+removals will double in length. After six months with no warning, a user's ban
+length is reset. Removals, like warnings, are public.
+
+The list of moderators consists of all active core developers. This includes,
+in alphabetical order, Alberto Simões, David Precious, Mickey Nasriachi,
+Russell Jenkins, Sawyer X, Stefan Hornburg (Racke), Steven Humphrey, and Yanick
+Champoux.
+
+This list might additionally grow to active members of the community who have
+stepped up to help handle abusive behavior. If this should happen, this
+document would be updated to include their names.
+
+Additionally, it's important to understand the self-regulating nature we
+foster at the Dancer community. This means anyone and everyone in the
+community - in the channel, on the list, at an event - has the ability to
+call out unacceptable behavior and incivility to others in the community.
+
+Moderators are responsible for issuing warnings and take disciplinary actions,
+but anyone may - and is encouraged - to publicly make note of unacceptable
+treatment of others.
+
+As a core principle, abuse is never tolerated. One cannot berate, insult,
+debase, deride, put down, or vilify anyone, or act towards anyone in a way
+intending to hurt them.
+
+The community specifically considers as abuse any attempts to otherize anyone,
+whether by their technical skill, knowledge, gender, sexual orientation,
+or any other characteristic.
+
+The community aims to maintain a safe space for everyone, in any forum it
+has. If you ever feel this core principle has been compromised, you are strongly
+urged to contact a moderator. We are always here.
+
+Remember, this is B<your> community, as much as it is anyone else's.
+
+=head1 CREDITS
+
+This policy has been adopted and adapted from the policy available for
+the Perl language development, provided by B<p5p> (the Perl 5 Porters).
+
+The original inspiration policy document can be read at L<perlpolicy>.
+
+=head1 AUTHOR
+
+Dancer Core Developers
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2014 by Alexis Sukrieh.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
@@ -1,7 +1,7 @@
 # ABSTRACT: Serializer for handling Dumper data
 
 package Dancer2::Serializer::Dumper;
-$Dancer2::Serializer::Dumper::VERSION = '0.151000';
+$Dancer2::Serializer::Dumper::VERSION = '0.153000';
 use Moo;
 use Carp 'croak';
 use Data::Dumper;
@@ -55,7 +55,7 @@ Dancer2::Serializer::Dumper - Serializer for handling Dumper data
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Serializer::JSON;
 # ABSTRACT: Serializer for handling JSON data
-$Dancer2::Serializer::JSON::VERSION = '0.151000';
+$Dancer2::Serializer::JSON::VERSION = '0.153000';
 use Moo;
 use JSON ();
 
@@ -57,7 +57,7 @@ Dancer2::Serializer::JSON - Serializer for handling JSON data
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Serializer::Mutable;
 # ABSTRACT: Serialize and deserialize content based on HTTP header
-$Dancer2::Serializer::Mutable::VERSION = '0.151000';
+$Dancer2::Serializer::Mutable::VERSION = '0.153000';
 use Moo;
 use Carp 'croak';
 use Encode;
@@ -77,13 +77,12 @@ sub deserialize {
 
 sub _get_content_type {
     my $self    = shift;
-    my $headers = $self->{'extra_headers'}
-        or return;
+    $self->has_request or return;
 
     # Search for the first HTTP header variable which
     # specifies supported content.
     foreach my $method ( qw<content_type accept accept_type> ) {
-        if ( my $value = $headers->{$method} ) {
+        if ( my $value = $self->request->header($method) ) {
             if ( exists $formats->{$value} ) {
                 $self->set_content_type($value);
                 return $formats->{$value};
@@ -109,7 +108,7 @@ Dancer2::Serializer::Mutable - Serialize and deserialize content based on HTTP h
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Serializer::YAML;
 # ABSTRACT: Serializer for handling YAML data
-$Dancer2::Serializer::YAML::VERSION = '0.151000';
+$Dancer2::Serializer::YAML::VERSION = '0.153000';
 use Moo;
 use Carp 'croak';
 use Encode;
@@ -51,7 +51,7 @@ Dancer2::Serializer::YAML - Serializer for handling YAML data
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Session::Simple;
 # ABSTRACT: in-memory session backend for Dancer2
-$Dancer2::Session::Simple::VERSION = '0.151000';
+$Dancer2::Session::Simple::VERSION = '0.153000';
 use Moo;
 use Dancer2::Core::Types;
 use Carp;
@@ -49,7 +49,7 @@ Dancer2::Session::Simple - in-memory session backend for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Dancer2::Session::YAML;
-$Dancer2::Session::YAML::VERSION = '0.151000';
+$Dancer2::Session::YAML::VERSION = '0.153000';
 # ABSTRACT: YAML-file-based session backend for Dancer2
 
 use Moo;
@@ -39,7 +39,7 @@ Dancer2::Session::YAML - YAML-file-based session backend for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Dancer2::Template::Implementation::ForkedTiny;
-$Dancer2::Template::Implementation::ForkedTiny::VERSION = '0.151000';
+$Dancer2::Template::Implementation::ForkedTiny::VERSION = '0.153000';
 # ABSTRACT: Dancer2 own implementation of Template::Tiny
 
 use 5.00503;
@@ -229,7 +229,7 @@ Dancer2::Template::Implementation::ForkedTiny - Dancer2 own implementation of Te
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Template::Simple;
 # ABSTRACT: Pure Perl 5 template engine for Dancer2
-$Dancer2::Template::Simple::VERSION = '0.151000';
+$Dancer2::Template::Simple::VERSION = '0.153000';
 use strict;
 use warnings;
 use Moo;
@@ -156,7 +156,7 @@ Dancer2::Template::Simple - Pure Perl 5 template engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Template toolkit engine for Dancer2
 
 package Dancer2::Template::TemplateToolkit;
-$Dancer2::Template::TemplateToolkit::VERSION = '0.151000';
+$Dancer2::Template::TemplateToolkit::VERSION = '0.153000';
 use strict;
 use warnings;
 use Carp qw/croak/;
@@ -63,7 +63,7 @@ Dancer2::Template::TemplateToolkit - Template toolkit engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Template::Tiny;
 # ABSTRACT: Template::Tiny engine for Dancer2
-$Dancer2::Template::Tiny::VERSION = '0.151000';
+$Dancer2::Template::Tiny::VERSION = '0.153000';
 use Moo;
 use Carp qw/croak/;
 use Dancer2::Core::Types;
@@ -50,7 +50,7 @@ Dancer2::Template::Tiny - Template::Tiny engine for Dancer2
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Test;
 # ABSTRACT: Useful routines for testing Dancer2 apps
-$Dancer2::Test::VERSION = '0.151000';
+$Dancer2::Test::VERSION = '0.153000';
 use strict;
 use warnings;
 
@@ -621,7 +621,7 @@ Dancer2::Test - Useful routines for testing Dancer2 apps
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Tutorial;
 # ABSTRACT: An example to get you dancing
-$Dancer2::Tutorial::VERSION = '0.151000';
+$Dancer2::Tutorial::VERSION = '0.153000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Tutorial - An example to get you dancing
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 What is Dancer2?
 
@@ -1,6 +1,6 @@
 package Dancer2;
 # ABSTRACT: Lightweight yet powerful web application framework
-$Dancer2::VERSION = '0.151000';
+$Dancer2::VERSION = '0.153000';
 use strict;
 use warnings;
 use List::Util  'first';
@@ -15,7 +15,7 @@ our $AUTHORITY = 'SUKRIA';
 # set version in dist.ini now
 # but we still need a basic version for
 # the tests
-$Dancer2::VERSION ||= '0.150000'; # 2.14.3
+$Dancer2::VERSION ||= '0.153000'; # 2.153.0
 
 our $runner;
 
@@ -32,7 +32,7 @@ sub import {
 
     my @final_args;
     foreach my $arg (@args) {
-        grep +( $arg eq $_ ), qw<:script :syntax>
+        grep +( $arg eq $_ ), qw<:script :syntax :tests>
             and next;
 
         if ( substr( $arg, 0, 1 ) eq '!' ) {
@@ -43,7 +43,7 @@ sub import {
     }
 
     scalar @final_args % 2
-      and die q{parameters must be key/value pairs, ':script' or '!keyword'};
+      and die q{parameters must be key/value pairs or '!keyword'};
 
     my %final_args = @final_args;
 
@@ -118,7 +118,7 @@ Dancer2 - Lightweight yet powerful web application framework
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 DESCRIPTION
 
@@ -33,7 +33,7 @@ dancer2 - Dancer2 command line interface
 
 =head1 VERSION
 
-version 0.151000
+version 0.153000
 
 =head1 SYNOPSIS
 
@@ -68,7 +68,7 @@ do { my $x = {
                                       'MooX::Types::MooseLike' => '0.16',
                                       'MooX::Types::MooseLike::Base' => '0',
                                       'POSIX' => '0',
-                                      'Plack' => '1.0016',
+                                      'Plack' => '1.0029',
                                       'Plack::Builder' => '0',
                                       'Pod::Simple::Search' => '0',
                                       'Pod::Simple::SimpleTree' => '0',
@@ -112,6 +112,7 @@ do { my $x = {
                                    'IO::Handle' => '0',
                                    'IPC::Open3' => '0',
                                    'LWP::Protocol::PSGI' => '0.06',
+                                   'Plack::Response' => '0',
                                    'Plack::Test' => '0',
                                    'Test::Fatal' => '0',
                                    'Test::Memory::Cycle' => '1.04',
@@ -67,6 +67,7 @@ my @files = (
     'lib/Dancer2/Plugin.pm',
     'lib/Dancer2/Plugin/Ajax.pm',
     'lib/Dancer2/Plugins.pod',
+    'lib/Dancer2/Policy.pod',
     'lib/Dancer2/Serializer/Dumper.pm',
     'lib/Dancer2/Serializer/JSON.pm',
     'lib/Dancer2/Serializer/Mutable.pm',
@@ -97,8 +98,24 @@ my @files = (
     't/auto_page.t',
     't/caller.t',
     't/charset_server.t',
+    't/classes/Dancer2-Core-Factory/create.t',
+    't/classes/Dancer2-Core-Hook/base.t',
+    't/classes/Dancer2-Core-Response/new_from.t',
+    't/classes/Dancer2-Core-Role-Engine/base.t',
+    't/classes/Dancer2-Core-Role-Handler/base.t',
+    't/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/bin/.exists',
     't/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/blib/bin/.exists',
     't/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/blib/lib/fakescript.pl',
+    't/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/lib/fake/inner/dir/.exists',
+    't/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/.dancer',
+    't/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/fakescript.pl',
+    't/classes/Dancer2-Core-Role-HasLocation/base.t',
+    't/classes/Dancer2-Core-Role-StandardResponses/base.t',
+    't/classes/Dancer2-Core-Runner/base.t',
+    't/classes/Dancer2-Core-Runner/environment.t',
+    't/classes/Dancer2-Core-Runner/psgi_app.t',
+    't/classes/Dancer2-Core/camelize.t',
+    't/classes/Dancer2/import.t',
     't/config.yml',
     't/config/config.yml',
     't/config/environments/failure.yml',
@@ -121,6 +138,7 @@ my @files = (
     't/deserialize.t',
     't/dispatcher.t',
     't/dsl.t',
+    't/dsl/content.t',
     't/dsl/extend.t',
     't/dsl/extend_config/config.yml',
     't/dsl/halt.t',
@@ -138,6 +156,9 @@ my @files = (
     't/hooks.t',
     't/http_methods.t',
     't/http_status.t',
+    't/issues/gh-634.t',
+    't/issues/gh-723.t',
+    't/issues/gh-730.t',
     't/lib/App1.pm',
     't/lib/App2.pm',
     't/lib/DancerPlugin.pm',
@@ -153,7 +174,6 @@ my @files = (
     't/log_die_before_hook.t',
     't/log_levels.t',
     't/logger.t',
-    't/logger/file.t',
     't/logger_console.t',
     't/lwp-protocol-psgi.t',
     't/memory_cycles.t',
@@ -187,10 +207,30 @@ my @files = (
     't/session_engines.t',
     't/session_forward.t',
     't/session_hooks.t',
+    't/session_in_template.t',
     't/session_lifecycle.t',
     't/session_object.t',
     't/sessions/VBzn5-yKiV0ZEaZqEtEvK_pmMT8n4QQx.yml',
+    't/sessions/VD8wIQAAIErosiPuPzgc7Feo60_y7s2K.yml',
+    't/sessions/VD8xFwAAIfVHBp2nUIRlhPrHBxZFewkg.yml',
+    't/sessions/VD8xPwAAIqUQa3U0CK_Q43bf7JSaXj68.yml',
     't/sessions/VDKr30YvCd7R3WEniUv5Re5999E6SJmQ.yml',
+    't/sessions/VDf4nIP4n0A4Ya5vcE7SaaDntyVZj9oB.yml',
+    't/sessions/VDfsgXhalKhiOdSVDEk4iwyf_j3JJ1lU.yml',
+    't/sessions/VDgFcPJynjsERU0GCt8fE9hhT-R3ErKV.yml',
+    't/sessions/VDgH-lQYfi_XUNztQLT-6ebJ_gzwGZKp.yml',
+    't/sessions/VDgHth9A4cXrh0fLlBodXUMnCXkcPlOO.yml',
+    't/sessions/VDsBvbCel9L5vqAA8X12v_IKYwpqtEIb.yml',
+    't/sessions/VDsC67174msADj1P2kEtWWWWqenpf_Gh.yml',
+    't/sessions/VDsdec7YkN_t5HYgYTY4UTO0rGbd3quL.yml',
+    't/sessions/VDskH-mTqVSrtI7vn3Cfjc22M3sDZ4nf.yml',
+    't/sessions/VDxpkwmXPxXgntfDkSbIJIW3-ZmOV6F2.yml',
+    't/sessions/VDxr8vlFwjuihF5Oq6qfdcX_C-sqJFst.yml',
+    't/sessions/VDxsUBz1JAMQos-edO9ShtnKnIqjRugy.yml',
+    't/sessions/VDxszUJNZJrCm2146wLcBL4Tauj5tlx3.yml',
+    't/sessions/VDxtWd3557qlVPhU5y4QeEnoTzopT4XL.yml',
+    't/sessions/VDxuf7UcBT5V58xfDyZ2akeLCE0stVRe.yml',
+    't/sessions/VEcEMgAADIiqAdXb4PP-YxIqDskws7Qd.yml',
     't/shared_engines.t',
     't/splat.t',
     't/template.t',
@@ -239,6 +279,7 @@ my @files = (
     't/views/folder/page.tt',
     't/views/index.tt',
     't/views/layouts/main.tt',
+    't/views/session_in_template.tt',
     't/views/template_simple_index.tt',
     't/views/tokens.tt'
 );
@@ -0,0 +1,265 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 32;
+use Test::Fatal;
+use Scalar::Util 'refaddr';
+use Plack::Test;
+use HTTP::Request::Common;
+
+BEGIN {
+    require Dancer2;
+    can_ok( Dancer2::, 'runner' );
+    is( Dancer2::->runner, undef, 'No runner by default' );
+}
+
+{
+    package App::CreatingRunner;
+    use Dancer2;
+}
+
+isa_ok( Dancer2->runner, 'Dancer2::Core::Runner', 'Runner created' );
+my $runner_refaddr = refaddr( Dancer2->runner );
+
+{
+    package App::NotRecreatingRunner;
+    use Dancer2;
+}
+
+isa_ok( Dancer2->runner, 'Dancer2::Core::Runner', 'Runner created' );
+is( refaddr( Dancer2->runner ), $runner_refaddr, 'Runner not recreated' );
+
+{
+    {
+        package FakeRunner;
+        sub psgi_app {
+            ::isa_ok( $_[0], 'FakeRunner' );
+            ::is( $_[1], 'psgi_param', 'psgi_app calls Runner->psgi_app' );
+            return 'Got it';
+        }
+    }
+
+    local $Dancer2::runner = bless {}, 'FakeRunner';
+    ::is(
+        Dancer2->psgi_app('psgi_param'),
+        'Got it',
+        'psgi_app works as expected',
+    );
+}
+
+{
+    package App::ScriptAllowed;
+    require Dancer2;
+
+    ::is(
+        ::exception { Dancer2->import(':script') },
+        undef,
+        ':script is allowed',
+    );
+}
+
+{
+    package App::TestsAllowed;
+    require Dancer2;
+
+    ::is(
+        ::exception { Dancer2->import(':tests') },
+        undef,
+        ':tests is allowed',
+    );
+}
+
+{
+    package App::SyntaxAllowed;
+    require Dancer2;
+
+    ::is(
+        ::exception { Dancer2->import(':syntax') },
+        undef,
+        ':syntax is allowed',
+    );
+}
+
+{
+    package App::KeyPairOnly;
+    require Dancer2;
+
+    ::like(
+        ::exception { Dancer2->import('single') },
+        qr{^parameters must be key/value pairs},
+        'Must import key/value pairs',
+    );
+
+    ::like(
+        ::exception { Dancer2->import(qw<three items requested>) },
+        qr{^parameters must be key/value pairs},
+        'Must import key/value pairs',
+    );
+
+    ::is(
+        ::exception { Dancer2->import( '!unless' ) },
+        undef,
+        'Must import key/value pairs unless prefixed by !',
+    );
+
+    ::is(
+        ::exception { Dancer2->import( '!unless', '!prefixed', '!bythis' ) },
+        undef,
+        'Must import key/value pairs unless prefixed by !',
+    );
+}
+
+{
+    package App::GettingDSL;
+    use Dancer2;
+
+    ::can_ok( __PACKAGE__, qw<get post> );
+}
+
+{
+    package App::GettingSelectiveDSL;
+    use Dancer2 '!post';
+
+    # proper way
+    ::can_ok( __PACKAGE__, 'get' );
+
+    # checking this would work too
+    ::ok( __PACKAGE__->can('get'), 'get imported successfully' );
+    ::ok( ! __PACKAGE__->can('post'), 'Can import keywords selectively' );
+}
+
+{
+    package App::Main;
+    use Dancer2;
+    get '/main' => sub {1};
+}
+
+{
+    package App::ComposedToMain;
+    use Dancer2 appname => 'App::Main';
+    get '/alsomain' => sub {1};
+}
+
+{
+    my $runner = Dancer2->runner;
+    isa_ok( $runner, 'Dancer2::Core::Runner' );
+    my $apps = $runner->apps;
+
+    cmp_ok(
+        scalar @{$apps},
+        '==',
+        11,
+        'Correct number of Apps created so far',
+    );
+
+    my @names = sort map +( $_->name ), @{$apps};
+
+    # this is the list of all Apps loaded in this test
+    is_deeply(
+        \@names,
+        [qw<
+            App::CreatingRunner
+            App::GettingDSL
+            App::GettingSelectiveDSL
+            App::KeyPairOnly
+            App::Main
+            App::NotRecreatingRunner
+            App::ScriptAllowed
+            App::StrictAndWarningsAndUTF8
+            App::SyntaxAllowed
+            App::TestsAllowed
+            App::WithSettingsChanged
+        >],
+        'All apps accounted for',
+    );
+
+    my $app = App::Main->to_app;
+    isa_ok( $app, 'CODE' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        is(
+            $cb->( GET '/main' )->content,
+            1,
+            'Got original app response',
+        );
+
+        is(
+            $cb->( GET '/alsomain' )->content,
+            1,
+            'Can compose apps with appname',
+        );
+    };
+}
+
+{
+    package App::WithSettingsChanged;
+    use Dancer2;
+}
+
+{
+    App::WithSettingsChanged->import( with => { layout => 'mobile' } );
+
+    my ($app) = grep +( $_->name eq 'App::WithSettingsChanged' ),
+        @{ Dancer2->runner->{'apps'} };
+
+    ::isa_ok( $app, 'Dancer2::Core::App' );
+    ::is(
+        $app->template_engine->{'layout'},
+        'mobile',
+        'Changed settings using with keyword',
+    );
+}
+
+{
+    package NoStrictNoWarningsNoUTF8;
+    no strict;
+    no warnings;
+    no utf8;
+
+    local $@ = undef;
+
+    eval '$var = 30';
+
+    ::is(
+        $@,
+        '',
+        'no strict (control test)',
+    );
+
+    local $SIG{'__WARN__'} = sub {
+        ::is(
+            $_[0],
+            undef,
+            'no warning (control test)',
+        );
+    };
+
+    eval 'my $var; my $var;';
+}
+
+{
+    package App::StrictAndWarningsAndUTF8;
+    use Dancer2;
+
+    local $@ = undef;
+
+    local $SIG{'__WARN__'} = sub {
+        ::ok(
+            $_[0],
+            'warnings pragma imported',
+        );
+    };
+
+    eval '$var = 30;';
+
+    ::like(
+        $@,
+        qr/^Global symbol/,
+        'strict pragma imported',
+    );
+
+    eval 'my $var; my $var;';
+}
+
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Dancer2::Core;
+use Test::More tests => 4;
+
+my %tests = (
+    'test'       => 'Test',
+    'class_name' => 'ClassName',
+    'class_nAME' => 'ClassNAME',
+    'class_NAME' => 'ClassNAME',
+);
+
+foreach my $test ( keys %tests ) {
+    my $value = $tests{$test};
+
+    is(
+        Dancer2::Core::camelize($test),
+        $value,
+        "$test camelized as $value",
+    );
+}
+
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+use Dancer2::Core::Factory;
+
+my $factory = Dancer2::Core::Factory->new;
+isa_ok( $factory, 'Dancer2::Core::Factory' );
+can_ok( $factory, 'create' );
+
+my $template = Dancer2::Core::Factory->create(
+    'template', 'template_toolkit', layout => 'mylayout'
+);
+
+isa_ok( $template, 'Dancer2::Template::TemplateToolkit' );
+is( $template->{'layout'}, 'mylayout', 'Correct layout set in the template' );
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+use Test::Fatal;
+use Dancer2::Core::Hook;
+
+like(
+    exception { Dancer2::Core::Hook->new( name => 'myname' ) },
+    qr/^Missing required arguments: code/,
+    'Must provide code attribute',
+);
+
+like(
+    exception { Dancer2::Core::Hook->new( code => sub {1} ) },
+    qr/^Missing required arguments: name/,
+    'Must provide name attribute',
+);
+
+is(
+    exception {
+        Dancer2::Core::Hook->new( name => 'myname', code => sub {1} )
+    },
+    undef,
+    'Can create hook with name and code',
+);
+
+{
+    my $hook = Dancer2::Core::Hook->new(
+        name => 'before_template',
+        code => sub {
+            my $input = shift;
+            ::is( $input, 'input', 'Correct input for hook' );
+            return 'output';
+        },
+    );
+
+    isa_ok( $hook, 'Dancer2::Core::Hook' );
+    can_ok( $hook, qw<name code> );
+
+    is(
+        $hook->name,
+        'before_template_render',
+        'before_template becomes before_template_render',
+    );
+
+    isa_ok( $hook->code, 'CODE' );
+
+    is(
+        $hook->code->('input'),
+        'output',
+        'Hook returned proper output',
+    );
+}
+
+{
+    my $hook = Dancer2::Core::Hook->new(
+        name => 'CrashingHook',
+        code => sub { die 'dying' },
+    );
+
+    isa_ok( $hook, 'Dancer2::Core::Hook' );
+
+    like(
+        exception { $hook->code->() },
+        qr/^Hook error: dying/,
+        'Hook crashing caught',
+    );
+}
@@ -0,0 +1,80 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+use Plack::Response;
+use Dancer2::Core::Response;
+
+sub normalize_headers {
+    my $headers = shift;
+
+    my %headers = ();
+    while ( my ( $key, $val ) = splice @{$headers}, 0, 2 ) {
+        $headers{$key} = $val;
+    }
+
+    return %headers;
+}
+
+can_ok( Dancer2::Core::Response::, qw<new_from_array new_from_plack> );
+
+my %default_headers = (
+    'Content-Type' => 'text/plain',
+    'X-Test'       => 'Val',
+);
+
+subtest 'new_from_array' => sub {
+    plan tests => 4;
+
+    my $array    = [ 200, [%default_headers], ['Foo'] ];
+    my $response = Dancer2::Core::Response->new_from_array($array);
+
+    isa_ok( $response, 'Dancer2::Core::Response' );
+    is( $response->status,  200,   'Correct status' );
+    is( $response->content, 'Foo', 'Correct content' );
+
+    # hash randomization
+    my %headers = normalize_headers( $response->headers_to_array );
+
+    is_deeply(
+        \%headers,
+        {
+            'Server' => "Perl Dancer2 $Dancer2::VERSION",
+            %default_headers,
+        },
+        'All headers correct',
+    );
+};
+
+subtest 'new_from_plack' => sub {
+    plan tests => 5;
+
+    my $plack = Plack::Response->new();
+    isa_ok( $plack, 'Plack::Response' );
+
+    $plack->status(200);
+    $plack->body('Bar');
+    foreach my $header_name ( keys %default_headers ) {
+        $plack->header( $header_name => $default_headers{$header_name} );
+    }
+
+    my $response = Dancer2::Core::Response->new_from_plack($plack);
+    isa_ok( $response, 'Dancer2::Core::Response' );
+    is( $response->status,  200,   'Correct status' );
+    is( $response->content, 'Bar', 'Correct content' );
+
+    # hash randomization
+    my %headers = normalize_headers( $response->headers_to_array );
+
+    is_deeply(
+        \%headers,
+        {
+            'Server' => "Perl Dancer2 $Dancer2::VERSION",
+            %default_headers,
+        },
+        'All headers correct',
+    );
+};
+
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+{
+    package App;
+    use Moo;
+    with 'Dancer2::Core::Role::Engine';
+    sub supported_hooks {}
+}
+
+my $app = App->new;
+isa_ok( $app, 'App' );
+can_ok( $app, qw<session config> ); # attributes
+can_ok( $app, qw<set_session clear_session has_session> ); # methods
+ok(
+    $app->DOES('Dancer2::Core::Role::Hookable'),
+    'App consumes Dancer2::Core::Role::Hookable',
+);
+
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+
+{
+    package Handler;
+    use Moo;
+    with 'Dancer2::Core::Role::Handler';
+    sub register {}
+}
+
+my $handler = Handler->new;
+isa_ok( $handler, 'Handler' );
+can_ok( $handler, qw<app>   ); # attributes
+ok(
+    $handler->DOES('Dancer2::Core::Role::Handler'),
+    'Handler consumes Dancer2::Core::Role::Handler',
+);
+
diff --git a/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/bin/.exists b/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/bin/.exists
new file mode 100644
index 00000000..e69de29b
diff --git a/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/lib/fake/inner/dir/.exists b/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerDir/lib/fake/inner/dir/.exists
new file mode 100644
index 00000000..e69de29b
diff --git a/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/.dancer b/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/.dancer
new file mode 100644
index 00000000..e69de29b
diff --git a/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/fakescript.pl b/var/tmp/source/XSAWYERX/Dancer2-0.153000/Dancer2-0.153000/t/classes/Dancer2-Core-Role-HasLocation/FakeDancerFile/fakescript.pl
new file mode 100644
index 00000000..e69de29b
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use File::Spec;
+use File::Basename;
+use Test::More tests => 11;
+
+{
+    package App;
+    use Moo;
+    with 'Dancer2::Core::Role::HasLocation';
+}
+
+note 'Defaults:'; {
+    my $app = App->new();
+    isa_ok( $app, 'App' );
+    can_ok( $app, qw<caller location> ); # attributes
+    can_ok( $app, '_build_location'   ); # methods
+
+    ok(
+        $app->DOES('Dancer2::Core::Role::HasLocation'),
+        'App consumes Dancer2::Core::Role::HasLocation',
+    );
+
+    is(
+        $app->caller,
+        't/classes/Dancer2-Core-Role-HasLocation/base.t',
+        'Default caller',
+    );
+}
+
+my $basedir = dirname( File::Spec->rel2abs(__FILE__) );
+
+note 'With lib/ and bin/:'; {
+    my $app = App->new(
+        caller => File::Spec->catfile(
+            $basedir, qw<FakeDancerDir fake inner dir fakescript.pl>
+        )
+    );
+
+    isa_ok( $app, 'App' );
+
+    my $location = $app->location;
+    $location =~ s/\Q$basedir\E//;
+
+    is(
+        $location,
+        '/FakeDancerDir/',
+        'Got correct location with lib/ and bin/',
+    );
+}
+
+note 'With .dancer file:'; {
+    my $app = App->new(
+        caller => File::Spec->catfile(
+            $basedir, qw<FakeDancerFile script.pl>
+        )
+    );
+
+    isa_ok( $app, 'App' );
+
+    my $location = $app->location;
+    $location =~ s/\Q$basedir\E//;
+
+    is(
+        $location,
+        '/FakeDancerFile',
+        'Got correct location with .dancer file',
+    );
+}
+
+note 'blib/ ignored:'; {
+    my $app = App->new(
+        caller => File::Spec->catfile(
+            $basedir, qw<FakeDancerDir blib lib fakescript.pl>
+        )
+    );
+
+    isa_ok( $app, 'App' );
+
+    my $location = $app->location;
+    $location =~ s/\Q$basedir\E//;
+
+    is(
+        $location,
+        '/FakeDancerDir/',
+        'blib/ dir is ignored',
+    );
+}
@@ -0,0 +1,171 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 36;
+
+{
+    package Handler;
+    use Moo;
+    with 'Dancer2::Core::Role::StandardResponses';
+}
+
+{
+    package App;
+    use Moo;
+    has response => ( is => 'ro', default => sub { Response->new } );
+}
+
+{
+    package Response;
+    use Moo;
+    sub status { shift->{'status'}->(@_) }
+    sub header { shift->{'header'}->(@_) }
+}
+
+note 'Checking our fake app'; {
+    my $app = App->new;
+    isa_ok( $app, 'App'      );
+    can_ok( $app, 'response' );
+    isa_ok( $app->response, 'Response' );
+}
+
+note 'Checking our fake response'; {
+    my $response = Response->new(
+        status => sub {
+            my ( $self, $input ) = @_;
+            ::isa_ok( $self, 'Response' );
+            ::is( $input, 'calling status', 'status called' );
+            return 'foo';
+        },
+
+        header => sub {
+            my ( $self, $input ) = @_;
+            ::isa_ok( $self, 'Response' );
+            ::is( $input, 'calling header', 'header called' );
+            return qw<bar baz>;
+        },
+    );
+
+    isa_ok( $response, 'Response' );
+
+    is_deeply(
+        [ $response->status('calling status') ],
+        [ 'foo' ],
+        'status() works',
+    );
+
+    is_deeply(
+        [ $response->header('calling header') ],
+        [ qw<bar baz> ],
+        'header() works',
+    );
+}
+
+my $handler = Handler->new;
+isa_ok( $handler, 'Handler' );
+can_ok( $handler, qw<response response_400 response_403 response_404> );
+
+note '->response'; {
+    # set up status and header
+    my $app = App->new(
+        response => Response->new(
+            status => sub {
+                my ( $self, $code ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $code, '400', 'Correct status code' );
+            },
+
+            header => sub {
+                my ( $self, $hdr_name, $hdr_content ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $hdr_name, 'Content-Type', 'Correct header name' );
+                ::is( $hdr_content, 'text/plain', 'Correct header value' );
+            },
+        )
+    );
+
+    is(
+        $handler->response( $app, 400, 'Some Message' ),
+        'Some Message',
+        'Correct response created',
+    );
+}
+
+note '->response_400'; {
+    # set up status and header
+    my $app = App->new(
+        response => Response->new(
+            status => sub {
+                my ( $self, $code ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $code, '400', 'Correct status code' );
+            },
+
+            header => sub {
+                my ( $self, $hdr_name, $hdr_content ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $hdr_name, 'Content-Type', 'Correct header name' );
+                ::is( $hdr_content, 'text/plain', 'Correct header value' );
+            },
+        )
+    );
+
+    is(
+        $handler->response_400($app),
+        'Bad Request',
+        'Correct response 400 created',
+    );
+}
+
+note '->response_403'; {
+    # set up status and header
+    my $app = App->new(
+        response => Response->new(
+            status => sub {
+                my ( $self, $code ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $code, '403', 'Correct status code' );
+            },
+
+            header => sub {
+                my ( $self, $hdr_name, $hdr_content ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $hdr_name, 'Content-Type', 'Correct header name' );
+                ::is( $hdr_content, 'text/plain', 'Correct header value' );
+            },
+        )
+    );
+
+    is(
+        $handler->response_403($app),
+        'Unauthorized',
+        'Correct response 403 created',
+    );
+}
+
+note '->response_404'; {
+    # set up status and header
+    my $app = App->new(
+        response => Response->new(
+            status => sub {
+                my ( $self, $code ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $code, '404', 'Correct status code' );
+            },
+
+            header => sub {
+                my ( $self, $hdr_name, $hdr_content ) = @_;
+                ::isa_ok( $self, 'Response' );
+                ::is( $hdr_name, 'Content-Type', 'Correct header name' );
+                ::is( $hdr_content, 'text/plain', 'Correct header value' );
+            },
+        )
+    );
+
+    is(
+        $handler->response_404($app),
+        'Not Found',
+        'Correct response 404 created',
+    );
+}
@@ -0,0 +1,246 @@
+use strict;
+use warnings;
+use Test::More tests => 40;
+use Dancer2::Core::Runner;
+
+is( $Dancer2::runner, undef, 'No runner defined in Dancer2 yet' );
+
+{
+    my $runner = Dancer2::Core::Runner->new();
+    isa_ok( $runner, 'Dancer2::Core::Runner' );
+}
+
+note 'MIME types'; {
+    my $runner = Dancer2::Core::Runner->new();
+    can_ok( $runner, 'mime_type' );
+    isa_ok( $runner->mime_type, 'Dancer2::Core::MIME' );
+}
+
+ok( $Dancer2::runner, 'Have a runner (probably) in $Dancer2::runner' );
+isa_ok( $Dancer2::runner, 'Dancer2::Core::Runner', 'Runner now defined' );
+
+note 'BUILD setting $Carp::Verbose';
+{
+    my $runner = Dancer2::Core::Runner->new();
+    is( $runner->config->{'traces'}, 0, 'traces not turned on (default' );
+    is( $Carp::Verbose, 0, 'Carp Verbose not turned on (default)' );
+}
+
+{
+    local $ENV{DANCER_TRACES} = 1;
+    my $runner = Dancer2::Core::Runner->new();
+    is( $runner->config->{'traces'}, 1, 'traces turned on' );
+    is( $Carp::Verbose, 1, 'Carp Verbose turned on (using DANCER_TRACES)' );
+}
+
+note 'server'; {
+    my $runner = Dancer2::Core::Runner->new(
+        host => '1.2.3.4', port => 9543, timeout => 3,
+    );
+    can_ok( $runner, qw<server _build_server run> );
+
+    my $server = $runner->server;
+    isa_ok( $server, 'HTTP::Server::PSGI' );
+    can_ok( $server, 'run' );
+    foreach my $attr ( qw<host port timeout> ) {
+        is( $server->{$attr}, $runner->$attr, "$attr set correctly in Server" );
+    }
+
+    is(
+        $server->{'server_software'},
+        "Perl Dancer2 $Dancer2::VERSION",
+        'server_software set correctly in Server',
+    );
+}
+
+note 'Environment';
+{
+    my $runner = Dancer2::Core::Runner->new();
+
+    is(
+        $runner->environment,
+        'development',
+        'Default environment',
+    );
+}
+
+{
+    local $ENV{DANCER_ENVIRONMENT} = 'foo';
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->environment,
+        'foo',
+        'Successfully set envinronment using DANCER_ENVIRONMENT',
+    );
+
+    $runner->config->{'apphandler'} = 'Standalone';
+}
+
+{
+    local $ENV{PLACK_ENV} = 'bar';
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->environment,
+        'bar',
+        'Successfully set environment using PLACK_ENV',
+    );
+
+    is(
+        $runner->config->{'apphandler'},
+        'PSGI',
+        'apphandler set to PSGI under PLACK_ENV',
+    );
+}
+
+{
+    local $ENV{DANCER_APPHANDLER} = 'baz';
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'apphandler'},
+        'baz',
+        'apphandler set via DANCER_APPHANDLER',
+    );
+}
+
+note 'Server tokens';
+{
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'server_tokens'},
+        1,
+        'Default server_tokens',
+    );
+}
+
+{
+    local $ENV{DANCER_SERVER_TOKENS} = 0;
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'server_tokens'},
+        0,
+        'Successfully set server_tokens using DANCER_SERVER_TOKENS',
+    );
+}
+
+note 'Startup info';
+{
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'startup_info'},
+        1,
+        'Default startup_info',
+    );
+}
+
+{
+    local $ENV{DANCER_STARTUP_INFO} = 0;
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'startup_info'},
+        0,
+        'Successfully set startup_info using DANCER_STARTUP_INFO',
+    );
+}
+
+note 'Warnings';
+{
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'warnings'},
+        0,
+        'Default warnings',
+    );
+}
+
+{
+    local $ENV{DANCER_WARNINGS} = 1;
+    my $runner = Dancer2::Core::Runner->new();
+    is(
+        $runner->config->{'warnings'},
+        1,
+        'Successfully set warnings using DANCER_WARNINGS',
+    );
+}
+
+{
+    {
+        package App::Fake;
+        use Moo;
+        has name => (
+            is      => 'ro',
+            default => sub {__PACKAGE__},
+        );
+
+        has postponed_hooks => (
+            is      => 'ro',
+            default => sub { +{
+                before => 'that',
+                after  => 'this',
+            } },
+        );
+    }
+    my $runner = Dancer2::Core::Runner->new();
+    my $app    = App::Fake->new();
+    can_ok( $runner, qw<register_application add_postponed_hooks> );
+
+    is_deeply(
+        $runner->apps,
+        [],
+        'Apps are empty at first',
+    );
+
+    is_deeply(
+        $runner->postponed_hooks,
+        +{},
+        'No postponed hooks at first',
+    );
+
+    $runner->register_application($app);
+
+    is_deeply(
+        $runner->apps,
+        [$app],
+        'Runner registered application',
+    );
+
+    is_deeply(
+        $runner->postponed_hooks,
+        { 'App::Fake' => $app->postponed_hooks },
+        'Runner registered the App\'s postponed hooks',
+    );
+}
+
+{
+    my $runner = Dancer2::Core::Runner->new();
+    can_ok( $runner, qw<start start_server> );
+
+    $runner->config->{'apphandler'} = 'PSGI';
+    my $app = $runner->start;
+    isa_ok( $app, 'CODE' );
+
+    {
+        package Server::Fake;
+        sub new { bless {}, 'Server::Fake' }
+        sub run {
+            my ( $self, $app ) = @_;
+            ::isa_ok( $self, 'Server::Fake' );
+            ::isa_ok( $app, 'CODE' );
+
+            return 'OK';
+        }
+    }
+
+    $runner->{'server'} = Server::Fake->new;
+    my $res = $runner->start_server($app);
+    is( $res, 'OK', 'start_server works' );
+}
+
+{
+    my $runner = Dancer2::Core::Runner->new();
+    can_ok( $runner, 'start' );
+
+    $runner->config->{'apphandler'} = 'PSGI';
+    my $app = $runner->start;
+    isa_ok( $app, 'CODE' );
+}
+
@@ -0,0 +1,38 @@
+use strict;
+use warnings;
+use Test::More tests => 6;
+use Dancer2::Core::Runner;
+
+{
+    my $runner = Dancer2::Core::Runner->new();
+    isa_ok( $runner, 'Dancer2::Core::Runner' );
+
+    is(
+        $runner->environment,
+        'development',
+        'Default environment',
+    );
+}
+
+{
+    local $ENV{DANCER_ENVIRONMENT} = 'foo';
+    my $runner = Dancer2::Core::Runner->new();
+    isa_ok( $runner, 'Dancer2::Core::Runner' );
+    is(
+        $runner->environment,
+        'foo',
+        'Successfully set envinronment using DANCER_ENVIRONMENT',
+    );
+}
+
+{
+    local $ENV{PLACK_ENV} = 'bar';
+    my $runner = Dancer2::Core::Runner->new();
+    isa_ok( $runner, 'Dancer2::Core::Runner' );
+    is(
+        $runner->environment,
+        'bar',
+        'Successfully set environment using PLACK_ENV',
+    );
+}
+
@@ -0,0 +1,92 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 25;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{ package App1; use Dancer2; get '/1' => sub {1}; }
+{ package App2; use Dancer2; get '/2' => sub {2}; }
+{ package App3; use Dancer2; get '/3' => sub {3}; }
+
+sub is_available {
+    my ( $cb, @apps ) = @_;
+    foreach my $app (@apps) {
+        is( $cb->( GET "/$app" )->content, $app, "App$app available" );
+    }
+}
+
+sub isnt_available {
+    my ( $cb, @apps ) = @_;
+    foreach my $app (@apps) {
+        is(
+            $cb->( GET "/$app" )->code,
+            404,
+            "App$app is not available",
+        );
+    }
+}
+
+note 'All Apps'; {
+    my $app = Dancer2->psgi_app;
+    isa_ok( $app, 'CODE', 'Got PSGI app' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        is_available( $cb, 1, 2, 3 );
+    };
+}
+
+note 'Specific Apps by parameters'; {
+    my @apps = @{ Dancer2->runner->apps }[ 0, 2 ];
+    is( scalar @apps, 2, 'Took two apps from the Runner' );
+    my $app = Dancer2->psgi_app(\@apps);
+    isa_ok( $app, 'CODE', 'Got PSGI app' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        is_available( $cb, 1, 3 );
+        isnt_available( $cb, 2 );
+    };
+}
+
+note 'Specific Apps via App objects'; {
+    my $app = App2->psgi_app;
+    isa_ok( $app, 'CODE', 'Got PSGI app' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        is_available( $cb, 2 );
+        isnt_available( $cb, 1, 3 );
+    };
+};
+
+note 'Specific apps by App names'; {
+    my $app = Dancer2->psgi_app( [ 'App1', 'App3' ] );
+    isa_ok( $app, 'CODE', 'Got PSGI app' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        isnt_available( $cb, 2 );
+        is_available( $cb, 1, 3 );
+    };
+}
+
+note 'Specific apps by App names with regular expression, v1'; {
+    my $app = Dancer2->psgi_app( [ qr/^App1$/, qr/^App3$/ ] );
+    isa_ok( $app, 'CODE', 'Got PSGI app' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        isnt_available( $cb, 2 );
+        is_available( $cb, 1, 3 );
+    };
+}
+
+note 'Specific apps by App names with regular expression, v2'; {
+    my $app = Dancer2->psgi_app( [ qr/^App(2|3)$/ ] );
+    isa_ok( $app, 'CODE', 'Got PSGI app' );
+    test_psgi $app, sub {
+        my $cb = shift;
+        isnt_available( $cb, 1 );
+        is_available( $cb, 2, 3 );
+    };
+}
+
@@ -0,0 +1,77 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 9;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{
+    package App::SetContent;
+    use Dancer2;
+    get '/' => sub {
+        content 'OK';
+
+        'Not OK';
+    };
+}
+
+{
+    package App::PassSuccess;
+    use Dancer2;
+
+    get '/' => sub {
+        content 'Missing';
+        pass;
+    };
+
+    get '/' => sub {
+        'There';
+    };
+}
+
+{
+    package App::PassFail;
+    use Dancer2;
+
+    get '/' => sub {
+        content 'Missing';
+        pass;
+    };
+
+    get '/' => sub {};
+}
+
+{
+    my $app = App::SetContent->to_app;
+    isa_ok( $app, 'CODE' );
+
+    my $test = Plack::Test->create($app);
+    my $res  = $test->request( GET '/' );
+
+    is( $res->code,    200,  'Reached route'   );
+    is( $res->content, 'OK', 'Correct content' );
+}
+
+{
+    my $app = App::PassSuccess->to_app;
+    isa_ok( $app, 'CODE' );
+
+    my $test = Plack::Test->create($app);
+    my $res  = $test->request( GET '/' );
+
+    is( $res->code,    200,     'Reached route'   );
+    is( $res->content, 'There', 'Correct content' );
+}
+
+{
+    my $app = App::PassFail->to_app;
+    isa_ok( $app, 'CODE' );
+
+    my $test = Plack::Test->create($app);
+    my $res  = $test->request( GET '/' );
+
+    is( $res->code,    200, 'Reached route'   );
+    is( $res->content, '',  'Correct content' );
+}
+
@@ -0,0 +1,120 @@
+use strict;
+use warnings;
+
+use Test::More tests=> 3;
+use File::Temp qw/tempdir/;
+use File::Spec;
+
+my $log_dir = tempdir( CLEANUP => 1 );
+
+{
+    package LogDirSpecified;
+    use Dancer2;
+
+    set engines => {
+        logger => {
+            File => {
+                log_dir   => $log_dir,
+                file_name => 'test_log.log',
+            }
+        }
+    };
+    set logger  => 'file';
+}
+
+{
+    package NonExistLogDirSpecified;
+    use Dancer2;
+
+    set engines => {
+        logger => {
+            File => {
+                log_dir   => "$log_dir/notexist",
+                file_name => 'test_log.log',
+            }
+        }
+    };
+    set logger  => 'file';
+}
+
+{
+    package LogDirNotSpecified;
+    use Dancer2;
+
+    set logger  => 'file';
+}
+
+my $check_cb = sub {
+    my ( $app, $dir, $file ) = @_;
+    my $logger = $app->logger_engine;
+
+    isa_ok( $logger, 'Dancer2::Logger::File' );
+    is(
+        $logger->environment,
+        $app->environment,
+        'Logger got correct environment',
+    );
+
+    is(
+        $logger->location,
+        $app->config_location,
+        'Logger got correct location',
+    );
+
+    is(
+        $logger->log_dir,
+        $dir,
+        'Logger got correct log directory',
+    );
+
+    is(
+        $logger->file_name,
+        $file,
+        'Logger got correct filename',
+    );
+
+    is(
+        $logger->log_file,
+        File::Spec->catfile( $dir, $file ),
+        'Logger got correct log file',
+    );
+};
+
+subtest 'test Logger::File with log_dir specified' => sub {
+    plan tests => 6;
+    my $app = [
+        grep { $_->name eq 'LogDirSpecified' } @{ Dancer2->runner->apps }
+    ]->[0];
+
+    $check_cb->( $app, $log_dir, 'test_log.log' );
+};
+
+subtest 'test Logger::File with log_dir NOT specified' => sub {
+    plan tests => 6;
+    my $app = [
+        grep { $_->name eq 'LogDirNotSpecified' } @{ Dancer2->runner->apps }
+    ]->[0];
+
+    $check_cb->(
+        $app,
+        File::Spec->catdir( $app->config_location, 'logs' ),
+        $app->environment . '.log',
+    );
+};
+
+subtest 'test Logger::File with non-existent log_dir specified' => sub {
+    plan tests => 6;
+
+    my $app = [
+        grep { $_->name eq 'NonExistLogDirSpecified'} @{ Dancer2->runner->apps }
+    ]->[0];
+
+    my $logger = $app->logger_engine;
+
+    $check_cb->(
+        $app,
+        "$log_dir/notexist",
+        'test_log.log',
+    );
+};
+
@@ -0,0 +1,57 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 4;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{
+    package App;
+    use Dancer2;
+    get '/' => sub {'OK'};
+}
+
+{
+    package App::Extended;
+    use Dancer2;
+    prefix '/test';
+    get '/'  => sub {'Also OK'};
+    post '/' => sub {
+        my $params = params;
+        ::isa_ok( $params, 'HASH' );
+        ::is( $params->{'foo'}, 'bar', 'Got params' );
+        return $params->{'foo'};
+    };
+}
+
+my $app = Dancer2->psgi_app;
+isa_ok( $app, 'CODE' );
+
+my $test = Plack::Test->create($app);
+
+subtest 'GET /' => sub {
+    plan tests => 2;
+    my $res = $test->request( GET '/' );
+    is( $res->code,    200,  'Correct code'    );
+    is( $res->content, 'OK', 'Correct content' );
+};
+
+subtest 'GET /test/' => sub {
+    plan tests => 2;
+    my $res = $test->request( GET '/test/' );
+    is( $res->code,     200,      'Correct code'    );
+    is( $res->content, 'Also OK', 'Correct content' );
+};
+
+subtest 'Missing POST params' => sub {
+    plan tests => 4;
+    my $res = $test->request(
+        POST '/test/',
+        { foo => 'bar' },
+    );
+
+    is( $res->code,    200,   'Correct code'    );
+    is( $res->content, 'bar', 'Correct content' );
+};
+
@@ -0,0 +1,72 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{
+    package App;
+    use Dancer2;
+
+    get '/' => sub { request->is_behind_proxy };
+}
+
+my $app = App->to_app;
+isa_ok( $app, 'CODE' );
+
+my $test = Plack::Test->create($app);
+
+subtest 'Runner config' => sub {
+    plan tests => 5;
+
+    is(
+        Dancer2->runner->config->{'behind_proxy'},
+        0,
+        'No default behind_proxy',
+    );
+
+    is(
+        scalar @{ Dancer2->runner->apps },
+        1,
+        'Single app registered',
+    );
+
+    isa_ok(
+        Dancer2->runner->apps->[0],
+        'Dancer2::Core::App',
+        'Correct app registered',
+    );
+
+    is(
+        Dancer2->runner->apps->[0]->setting('behind_proxy'),
+        0,
+        'behind_proxy not defined by default in an app',
+    );
+
+    Dancer2->runner->apps->[0]->config->{'behind_proxy'} = 1;
+
+    is(
+        Dancer2->runner->apps->[0]->setting('behind_proxy'),
+        1,
+        'Set behind_proxy locally in the app to one',
+    );
+
+};
+
+subtest 'Using App-level settings' => sub {
+    plan tests => 3;
+
+    is(
+        Dancer2->runner->config->{'behind_proxy'},
+        0,
+        'Runner\'s behind_proxy is still the default',
+    );
+
+    my $res = $test->request( GET '/' );
+    is( $res->code,    200, '[GET /] Correct code'         );
+    is( $res->content, '1', '[GET /] Local value achieved' );
+};
+
@@ -1,10 +0,0 @@
-#!#!/usr/bin/perl
-use strict;
-use warnings;
-
-use Test::More tests => 2;
-use Dancer2::Logger::File;
-
-my $logger = Dancer2::Logger::File->new();
-isa_ok( $logger, 'Dancer2::Logger::File' );
-can_ok( $logger, qw<environment location log_dir file_name log_file fh> );
@@ -87,7 +87,7 @@ sub get_app_for_engine {
     hook 'engine.session.after_retrieve' => sub {
        my ($response) = @_;
        is ref($response), 'Dancer2::Core::Session',
-                            'Correct response type returned in before_retrieve';
+                            'Correct response type returned in after_retrieve';
     };
     #this returns dancer app. We'll register it with LWP::Protocol::PSGI
     dance;
@@ -120,6 +120,16 @@ foreach my $engine (@engines) {
         is $test_flags->{'engine.session.after_destroy'}, undef, "session.after_destroy not called";
     };
 
+    subtest 'verify Handler::File (static content) does not retrieve session' => sub {
+        my $r = $ua->get("http://localhost:3000/file.txt");
+
+        # These should not change from previous subtest
+        is $test_flags->{'engine.session.before_create'}, 1, "session.before_create not called";
+        is $test_flags->{'engine.session.after_create'}, 1, "session.after_create not called";
+        is $test_flags->{'engine.session.before_retrieve'}, undef, "session.before_retrieve not called";
+        is $test_flags->{'engine.session.after_retrieve'}, undef, "session.after_retrieve not called";
+    };
+
     $r = $ua->get("http://localhost:3000/get_session");
     is $r->content, "ok", "get_session ran ok";
 
@@ -0,0 +1,79 @@
+use strict;
+use warnings;
+use Test::More;
+
+use YAML;
+use Test::TCP 1.13;
+use File::Temp 0.22;
+use LWP::UserAgent;
+use HTTP::Date qw/str2time/;
+use File::Spec;
+
+my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
+
+Test::TCP::test_tcp(
+    client => sub {
+        my $port = shift;
+
+        my $ua = LWP::UserAgent->new;
+        $ua->cookie_jar( { file => "$tempdir/.cookies.txt" } );
+
+        my $res = $ua->get("http://127.0.0.1:$port/");
+        ok $res->is_success;
+        is $res->content, "session.name \n";
+
+        $res = $ua->get("http://127.0.0.1:$port/set_session/test_name");
+        ok $res->is_success;
+        is $res->content, "session.name test_name\n";
+
+        $res = $ua->get("http://127.0.0.1:$port/destroy_session");
+        ok $res->is_success;
+        is $res->content, "session.name \n";
+
+        File::Temp::cleanup();
+    },
+    server => sub {
+        my $port = shift;
+
+        use Dancer2;
+
+        get '/' => sub {
+            template 'session_in_template'
+        };
+
+        get '/set_session/*' => sub {
+            my ($name) = splat;
+            session name => $name;
+            template 'session_in_template';
+        };
+
+        get '/destroy_session' => sub {
+            # Need to call the 'session' keyword, so app->setup_session
+            # is called and the session attribute in the engines is populated
+            my $name = session 'name';
+            # Destroying the session should remove the session object from
+            # all engines.
+            app->destroy_session;
+            template 'session_in_template';
+        };
+
+        setting appdir => $tempdir;
+        setting(
+            engines => {
+                session => { 'Simple' => { session_dir => 't/sessions' } }
+            }
+        );
+        setting( session => 'Simple' );
+
+        set(show_errors  => 1,
+            startup_info => 0,
+            environment  => 'production',
+            port         => $port
+        );
+
+        # we're overiding a RO attribute only for this test!
+        Dancer2->runner->{'port'} = $port;
+        start;
+    },
+);
+done_testing;
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1,2 @@
+---
+name: damian
@@ -0,0 +1 @@
+session.name [% session.name %]