The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Build.PL 84
Changes 028
MANIFEST 211
META.json 6260
META.yml 6260
Makefile.PL 106
lib/Dancer2/CLI/Command/gen.pm 75
lib/Dancer2/CLI/Command/version.pm 22
lib/Dancer2/CLI.pm 22
lib/Dancer2/Config.pod 62
lib/Dancer2/Cookbook.pod 22
lib/Dancer2/Core/.Request.pm.swp --
lib/Dancer2/Core/App.pm 67
lib/Dancer2/Core/Cookie.pm 22
lib/Dancer2/Core/DSL.pm 22
lib/Dancer2/Core/Dispatcher.pm 22
lib/Dancer2/Core/Error.pm 22
lib/Dancer2/Core/Factory.pm 22
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 22
lib/Dancer2/Core/Role/ConfigReader.pm 22
lib/Dancer2/Core/Role/DSL.pm 22
lib/Dancer2/Core/Role/Engine.pm 22
lib/Dancer2/Core/Role/Handler.pm 22
lib/Dancer2/Core/Role/HasLocation.pm 23
lib/Dancer2/Core/Role/Headers.pm 22
lib/Dancer2/Core/Role/Hookable.pm 22
lib/Dancer2/Core/Role/Logger.pm 710
lib/Dancer2/Core/Role/Serializer.pm 22
lib/Dancer2/Core/Role/SessionFactory/File.pm 96
lib/Dancer2/Core/Role/SessionFactory.pm 86
lib/Dancer2/Core/Role/StandardResponses.pm 22
lib/Dancer2/Core/Role/Template.pm 22
lib/Dancer2/Core/Route.pm 73
lib/Dancer2/Core/Runner.pm 32
lib/Dancer2/Core/Session.pm 63
lib/Dancer2/Core/Time.pm 33
lib/Dancer2/Core/Types.pm 22
lib/Dancer2/Core.pm 22
lib/Dancer2/FileUtils.pm 22
lib/Dancer2/Handler/AutoPage.pm 22
lib/Dancer2/Handler/File.pm 1022
lib/Dancer2/Logger/Capture/Trap.pm 48
lib/Dancer2/Logger/Capture.pm 36
lib/Dancer2/Logger/Console.pm 22
lib/Dancer2/Logger/Diag.pm 22
lib/Dancer2/Logger/File.pm 22
lib/Dancer2/Logger/Note.pm 22
lib/Dancer2/Logger/Null.pm 22
lib/Dancer2/Manual/Migration.pod 5166
lib/Dancer2/Manual/Testing.pod 22
lib/Dancer2/Manual.pod 26
lib/Dancer2/Plugin.pm 22
lib/Dancer2/Plugins.pod 22
lib/Dancer2/Policy.pod 22
lib/Dancer2/Serializer/Dumper.pm 22
lib/Dancer2/Serializer/JSON.pm 22
lib/Dancer2/Serializer/Mutable.pm 22
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 42
lib/Dancer2/Template/TemplateToolkit.pm 53
lib/Dancer2/Template/Tiny.pm 22
lib/Dancer2/Test.pm 22
lib/Dancer2/Tutorial.pod 22
lib/Dancer2.pm 38
script/dancer2 11
share/skel/bin/+app.pl 13
share/skel/environments/production.yml 32
t/00-report-prereqs.dd 42
t/author-no-tabs.t 111
t/classes/Dancer2/import.t 30
t/classes/Dancer2-Core/camelize.t 30
t/classes/Dancer2-Core-Factory/new.t 30
t/classes/Dancer2-Core-Hook/new.t 30
t/classes/Dancer2-Core-Request/new.t 30
t/classes/Dancer2-Core-Response/new_from.t 30
t/classes/Dancer2-Core-Role-Engine/with.t 30
t/classes/Dancer2-Core-Role-Handler/with.t 30
t/classes/Dancer2-Core-Role-HasLocation/with.t 30
t/classes/Dancer2-Core-Role-Headers/with.t 30
t/classes/Dancer2-Core-Role-Serializer/with.t 52
t/classes/Dancer2-Core-Role-StandardResponses/with.t 30
t/classes/Dancer2-Core-Route/base.t 20
t/classes/Dancer2-Core-Route/match.t 10
t/classes/Dancer2-Core-Runner/environment.t 30
t/classes/Dancer2-Core-Runner/new.t 241
t/classes/Dancer2-Core-Runner/psgi_app.t 30
t/deserialize.t 01
t/dsl/content.t 20
t/dsl/extend.t 20
t/dsl/halt.t 10
t/dsl/pass.t 10
t/dsl/path.t 30
t/dsl/to_app.t 10
t/issues/gh-596.t 30
t/issues/gh-634.t 10
t/issues/gh-639/fails/issue.t 30
t/issues/gh-639/succeeds/issue.t 30
t/issues/gh-650/gh-650.t 042
t/issues/gh-650/views/environment_setting.tt 01
t/issues/gh-723.t 20
t/issues/gh-730.t 30
t/issues/gh-799.t 064
t/lib/PluginWithImport.pm 21
t/logger.t 313
t/lwp-protocol-psgi.t 350
t/session_config.t 11278
t/session_engines.t 9784
t/session_forward.t 8696
t/session_hooks.t 120107
t/session_in_template.t 7575
t/session_lifecycle.t 171160
t/sessions/VIlt7wAAceLduiKWlnAkCQpsRFe9RwmE.yml 02
t/sessions/VIltdAAAcGUtpuNeagm8uMqOmg1iO5BG.yml 02
t/sessions/VIxX-gAAaW6BYt4htdZy0O9_g5J3WdHM.yml 02
t/sessions/VIxY0wAAan1F1Maz4h8_pCnhMdtstSHX.yml 02
t/sessions/VIxi3AAAfpilI1rk9Tg_5c29HVaYBclB.yml 02
t/sessions/VIxiTQAAfYHVHQ5txQKuXTwZ7alch-Gc.yml 02
t/sessions/VIxj4wAAAakb1qv0OYF9_oA_WrIqImY7.yml 02
t/sessions/VIxkLgAABBzH8FV-MYjgAOQrJuLhWOkM.yml 02
t/shared_engines.t 4945
128 files changed (This is a version diff) 11921337
@@ -20,7 +20,7 @@ my %module_build_args = (
     "Dancer Core Developers"
   ],
   "dist_name" => "Dancer2",
-  "dist_version" => "0.156001",
+  "dist_version" => "0.157000",
   "license" => "perl",
   "module_name" => "Dancer2",
   "recommends" => {
@@ -59,10 +59,10 @@ my %module_build_args = (
     "HTTP::Date" => 0,
     "HTTP::Headers" => 0,
     "HTTP::Server::PSGI" => 0,
+    "HTTP::Tiny" => 0,
     "Hash::Merge::Simple" => 0,
     "IO::File" => 0,
     "JSON" => 0,
-    "LWP::UserAgent" => 0,
     "List::Util" => 0,
     "MIME::Base64" => "3.13",
     "MIME::Types" => 0,
@@ -115,19 +115,17 @@ my %module_build_args = (
     "File::Temp" => "0.22",
     "FindBin" => 0,
     "HTTP::Body" => 0,
+    "HTTP::Cookies" => 0,
     "HTTP::Request" => 0,
     "HTTP::Request::Common" => 0,
     "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",
     "Test::MockTime" => 0,
     "Test::More" => "0.92",
-    "Test::Script" => 0,
-    "Test::TCP" => "1.13",
     "YAML" => 0,
     "lib" => 0,
     "perl" => "5.006",
@@ -144,11 +142,11 @@ my %fallback_build_requires = (
   "File::Temp" => "0.22",
   "FindBin" => 0,
   "HTTP::Body" => 0,
+  "HTTP::Cookies" => 0,
   "HTTP::Request" => 0,
   "HTTP::Request::Common" => 0,
   "IO::Handle" => 0,
   "IPC::Open3" => 0,
-  "LWP::Protocol::PSGI" => "0.06",
   "Module::Build" => "0.3601",
   "Plack::Response" => 0,
   "Plack::Test" => 0,
@@ -156,8 +154,6 @@ my %fallback_build_requires = (
   "Test::Memory::Cycle" => "1.04",
   "Test::MockTime" => 0,
   "Test::More" => "0.92",
-  "Test::Script" => 0,
-  "Test::TCP" => "1.13",
   "YAML" => 0,
   "lib" => 0,
   "perl" => "5.006",
@@ -1,3 +1,31 @@
+0.157000  2014-12-14 18:23:33+01:00 Europe/Amsterdam
+
+    [ BUG FIXES ]
+    * GH #799: Set current request earlier so log formats using requests
+      will work. (Sawyer X)
+    * GH #650: Provide default environment to app for templating.
+      (Dávid Kovács, Chi Trinh)
+    * GH #800: Better portability code, for different Windows situations.
+      (Christian Walde)
+    * Less littering of the test directories with session files. (Sawyer X)
+
+    [ ENHANCEMENT ]
+    * GH #810: strict && warnings in the app.pl. (Sawyer X)
+    * Use to_app keyword in skeleton. (Sawyer X)
+    * GH #801: Under production, server tokens are disabled. (Sawyer X)
+    * GH #588, #779: Remove LWP::UserAgent in favor of HTTP::Tiny.
+      (Dávid Kovács, simbabque, Sawyer X)
+    * Remove all usages of Test::TCP in favor of Plack::Test. (Sawyer X)
+
+    [ DOCUMENTATION ]
+    * GH #802: Remove indication of warnings configuration option
+      and add explanation in migration document. (Sawyer X)
+    * GH #806: Link in main docs to the migration document. (Gabor Szabo)
+    * GH #807: Update migration document with more session data,
+      changes to app.pl, and Template::Toolkit configuration. (Gabor Szabo)
+    * GH #813: Update migration document with information on encoding and
+      usage of Plack::Request internally. (Gabor Szabo, Sawyer X)
+
 0.156001  2014-12-08 23:03:43+01:00 Europe/Amsterdam
 
     [ DOCUMENTATION ]
@@ -16,7 +16,6 @@ lib/Dancer2/CLI/Command/version.pm
 lib/Dancer2/Config.pod
 lib/Dancer2/Cookbook.pod
 lib/Dancer2/Core.pm
-lib/Dancer2/Core/.Request.pm.swp
 lib/Dancer2/Core/App.pm
 lib/Dancer2/Core/Cookie.pm
 lib/Dancer2/Core/DSL.pm
@@ -189,10 +188,13 @@ t/issues/gh-639/fails/issue.t
 t/issues/gh-639/succeeds/.dancer
 t/issues/gh-639/succeeds/config.yml
 t/issues/gh-639/succeeds/issue.t
+t/issues/gh-650/gh-650.t
+t/issues/gh-650/views/environment_setting.tt
 t/issues/gh-723.t
 t/issues/gh-730.t
 t/issues/gh-794.t
 t/issues/gh-797.t
+t/issues/gh-799.t
 t/lib/App1.pm
 t/lib/App2.pm
 t/lib/DancerPlugin.pm
@@ -209,7 +211,6 @@ t/log_die_before_hook.t
 t/log_levels.t
 t/logger.t
 t/logger_console.t
-t/lwp-protocol-psgi.t
 t/memory_cycles.t
 t/mime.t
 t/multi_apps.t
@@ -259,6 +260,14 @@ t/sessions/VINylQAATxmWhwaQwYTVls-P09SzyCsc.yml
 t/sessions/VINziwAAUHovk3nfMmkf2GHI6RNrE38c.yml
 t/sessions/VIOBYgAAZD-3UeYHGxJmpPkpI8hOgUvW.yml
 t/sessions/VISIVwAASGBJcMXNsII2nVrChuLAP7pm.yml
+t/sessions/VIlt7wAAceLduiKWlnAkCQpsRFe9RwmE.yml
+t/sessions/VIltdAAAcGUtpuNeagm8uMqOmg1iO5BG.yml
+t/sessions/VIxX-gAAaW6BYt4htdZy0O9_g5J3WdHM.yml
+t/sessions/VIxY0wAAan1F1Maz4h8_pCnhMdtstSHX.yml
+t/sessions/VIxi3AAAfpilI1rk9Tg_5c29HVaYBclB.yml
+t/sessions/VIxiTQAAfYHVHQ5txQKuXTwZ7alch-Gc.yml
+t/sessions/VIxj4wAAAakb1qv0OYF9_oA_WrIqImY7.yml
+t/sessions/VIxkLgAABBzH8FV-MYjgAOQrJuLhWOkM.yml
 t/shared_engines.t
 t/template.t
 t/template_default_tokens.t
@@ -70,10 +70,10 @@
             "HTTP::Date" : "0",
             "HTTP::Headers" : "0",
             "HTTP::Server::PSGI" : "0",
+            "HTTP::Tiny" : "0",
             "Hash::Merge::Simple" : "0",
             "IO::File" : "0",
             "JSON" : "0",
-            "LWP::UserAgent" : "0",
             "List::Util" : "0",
             "MIME::Base64" : "3.13",
             "MIME::Types" : "0",
@@ -130,19 +130,17 @@
             "File::Temp" : "0.22",
             "FindBin" : "0",
             "HTTP::Body" : "0",
+            "HTTP::Cookies" : "0",
             "HTTP::Request" : "0",
             "HTTP::Request::Common" : "0",
             "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",
             "Test::MockTime" : "0",
             "Test::More" : "0.92",
-            "Test::Script" : "0",
-            "Test::TCP" : "1.13",
             "YAML" : "0",
             "lib" : "0",
             "perl" : "5.006",
@@ -154,231 +152,231 @@
    "provides" : {
       "Dancer2" : {
          "file" : "lib/Dancer2.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::CLI" : {
          "file" : "lib/Dancer2/CLI.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::CLI::Command::gen" : {
          "file" : "lib/Dancer2/CLI/Command/gen.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::CLI::Command::version" : {
          "file" : "lib/Dancer2/CLI/Command/version.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core" : {
          "file" : "lib/Dancer2/Core.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::App" : {
          "file" : "lib/Dancer2/Core/App.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Cookie" : {
          "file" : "lib/Dancer2/Core/Cookie.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::DSL" : {
          "file" : "lib/Dancer2/Core/DSL.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Dispatcher" : {
          "file" : "lib/Dancer2/Core/Dispatcher.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Error" : {
          "file" : "lib/Dancer2/Core/Error.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Factory" : {
          "file" : "lib/Dancer2/Core/Factory.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::HTTP" : {
          "file" : "lib/Dancer2/Core/HTTP.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Hook" : {
          "file" : "lib/Dancer2/Core/Hook.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::MIME" : {
          "file" : "lib/Dancer2/Core/MIME.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Request" : {
          "file" : "lib/Dancer2/Core/Request.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Request::Upload" : {
          "file" : "lib/Dancer2/Core/Request/Upload.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Response" : {
          "file" : "lib/Dancer2/Core/Response.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::ConfigReader" : {
          "file" : "lib/Dancer2/Core/Role/ConfigReader.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::DSL" : {
          "file" : "lib/Dancer2/Core/Role/DSL.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Engine" : {
          "file" : "lib/Dancer2/Core/Role/Engine.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Handler" : {
          "file" : "lib/Dancer2/Core/Role/Handler.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::HasLocation" : {
          "file" : "lib/Dancer2/Core/Role/HasLocation.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Headers" : {
          "file" : "lib/Dancer2/Core/Role/Headers.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Hookable" : {
          "file" : "lib/Dancer2/Core/Role/Hookable.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Logger" : {
          "file" : "lib/Dancer2/Core/Role/Logger.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Serializer" : {
          "file" : "lib/Dancer2/Core/Role/Serializer.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::SessionFactory" : {
          "file" : "lib/Dancer2/Core/Role/SessionFactory.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::SessionFactory::File" : {
          "file" : "lib/Dancer2/Core/Role/SessionFactory/File.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::StandardResponses" : {
          "file" : "lib/Dancer2/Core/Role/StandardResponses.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Role::Template" : {
          "file" : "lib/Dancer2/Core/Role/Template.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Route" : {
          "file" : "lib/Dancer2/Core/Route.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Runner" : {
          "file" : "lib/Dancer2/Core/Runner.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Session" : {
          "file" : "lib/Dancer2/Core/Session.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Time" : {
          "file" : "lib/Dancer2/Core/Time.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Core::Types" : {
          "file" : "lib/Dancer2/Core/Types.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::FileUtils" : {
          "file" : "lib/Dancer2/FileUtils.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Handler::AutoPage" : {
          "file" : "lib/Dancer2/Handler/AutoPage.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Handler::File" : {
          "file" : "lib/Dancer2/Handler/File.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::Capture" : {
          "file" : "lib/Dancer2/Logger/Capture.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::Capture::Trap" : {
          "file" : "lib/Dancer2/Logger/Capture/Trap.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::Console" : {
          "file" : "lib/Dancer2/Logger/Console.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::Diag" : {
          "file" : "lib/Dancer2/Logger/Diag.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::File" : {
          "file" : "lib/Dancer2/Logger/File.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::Note" : {
          "file" : "lib/Dancer2/Logger/Note.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Logger::Null" : {
          "file" : "lib/Dancer2/Logger/Null.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Plugin" : {
          "file" : "lib/Dancer2/Plugin.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Serializer::Dumper" : {
          "file" : "lib/Dancer2/Serializer/Dumper.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Serializer::JSON" : {
          "file" : "lib/Dancer2/Serializer/JSON.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Serializer::Mutable" : {
          "file" : "lib/Dancer2/Serializer/Mutable.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Serializer::YAML" : {
          "file" : "lib/Dancer2/Serializer/YAML.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Session::Simple" : {
          "file" : "lib/Dancer2/Session/Simple.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Session::YAML" : {
          "file" : "lib/Dancer2/Session/YAML.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Template::Implementation::ForkedTiny" : {
          "file" : "lib/Dancer2/Template/Implementation/ForkedTiny.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Template::Simple" : {
          "file" : "lib/Dancer2/Template/Simple.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Template::TemplateToolkit" : {
          "file" : "lib/Dancer2/Template/TemplateToolkit.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Template::Tiny" : {
          "file" : "lib/Dancer2/Template/Tiny.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       },
       "Dancer2::Test" : {
          "file" : "lib/Dancer2/Test.pm",
-         "version" : "0.156001"
+         "version" : "0.157000"
       }
    },
    "release_status" : "stable",
@@ -395,6 +393,6 @@
       "x_IRC" : "irc://irc.perl.org/#dancer",
       "x_WebIRC" : "https://chat.mibbit.com/#dancer@irc.perl.org"
    },
-   "version" : "0.156001"
+   "version" : "0.157000"
 }
 
@@ -9,11 +9,11 @@ build_requires:
   File::Temp: 0.22
   FindBin: 0
   HTTP::Body: 0
+  HTTP::Cookies: 0
   HTTP::Request: 0
   HTTP::Request::Common: 0
   IO::Handle: 0
   IPC::Open3: 0
-  LWP::Protocol::PSGI: 0.06
   Module::Build: 0.3601
   Plack::Response: 0
   Plack::Test: 0
@@ -21,8 +21,6 @@ build_requires:
   Test::Memory::Cycle: 1.04
   Test::MockTime: 0
   Test::More: 0.92
-  Test::Script: 0
-  Test::TCP: 1.13
   YAML: 0
   lib: 0
   perl: 5.006
@@ -42,175 +40,175 @@ name: Dancer2
 provides:
   Dancer2:
     file: lib/Dancer2.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::CLI:
     file: lib/Dancer2/CLI.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::CLI::Command::gen:
     file: lib/Dancer2/CLI/Command/gen.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::CLI::Command::version:
     file: lib/Dancer2/CLI/Command/version.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core:
     file: lib/Dancer2/Core.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::App:
     file: lib/Dancer2/Core/App.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Cookie:
     file: lib/Dancer2/Core/Cookie.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::DSL:
     file: lib/Dancer2/Core/DSL.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Dispatcher:
     file: lib/Dancer2/Core/Dispatcher.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Error:
     file: lib/Dancer2/Core/Error.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Factory:
     file: lib/Dancer2/Core/Factory.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::HTTP:
     file: lib/Dancer2/Core/HTTP.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Hook:
     file: lib/Dancer2/Core/Hook.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::MIME:
     file: lib/Dancer2/Core/MIME.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Request:
     file: lib/Dancer2/Core/Request.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Request::Upload:
     file: lib/Dancer2/Core/Request/Upload.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Response:
     file: lib/Dancer2/Core/Response.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::ConfigReader:
     file: lib/Dancer2/Core/Role/ConfigReader.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::DSL:
     file: lib/Dancer2/Core/Role/DSL.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Engine:
     file: lib/Dancer2/Core/Role/Engine.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Handler:
     file: lib/Dancer2/Core/Role/Handler.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::HasLocation:
     file: lib/Dancer2/Core/Role/HasLocation.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Headers:
     file: lib/Dancer2/Core/Role/Headers.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Hookable:
     file: lib/Dancer2/Core/Role/Hookable.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Logger:
     file: lib/Dancer2/Core/Role/Logger.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Serializer:
     file: lib/Dancer2/Core/Role/Serializer.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::SessionFactory:
     file: lib/Dancer2/Core/Role/SessionFactory.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::SessionFactory::File:
     file: lib/Dancer2/Core/Role/SessionFactory/File.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::StandardResponses:
     file: lib/Dancer2/Core/Role/StandardResponses.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Role::Template:
     file: lib/Dancer2/Core/Role/Template.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Route:
     file: lib/Dancer2/Core/Route.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Runner:
     file: lib/Dancer2/Core/Runner.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Session:
     file: lib/Dancer2/Core/Session.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Time:
     file: lib/Dancer2/Core/Time.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Core::Types:
     file: lib/Dancer2/Core/Types.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::FileUtils:
     file: lib/Dancer2/FileUtils.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Handler::AutoPage:
     file: lib/Dancer2/Handler/AutoPage.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Handler::File:
     file: lib/Dancer2/Handler/File.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::Capture:
     file: lib/Dancer2/Logger/Capture.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::Capture::Trap:
     file: lib/Dancer2/Logger/Capture/Trap.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::Console:
     file: lib/Dancer2/Logger/Console.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::Diag:
     file: lib/Dancer2/Logger/Diag.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::File:
     file: lib/Dancer2/Logger/File.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::Note:
     file: lib/Dancer2/Logger/Note.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Logger::Null:
     file: lib/Dancer2/Logger/Null.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Plugin:
     file: lib/Dancer2/Plugin.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Serializer::Dumper:
     file: lib/Dancer2/Serializer/Dumper.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Serializer::JSON:
     file: lib/Dancer2/Serializer/JSON.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Serializer::Mutable:
     file: lib/Dancer2/Serializer/Mutable.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Serializer::YAML:
     file: lib/Dancer2/Serializer/YAML.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Session::Simple:
     file: lib/Dancer2/Session/Simple.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Session::YAML:
     file: lib/Dancer2/Session/YAML.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Template::Implementation::ForkedTiny:
     file: lib/Dancer2/Template/Implementation/ForkedTiny.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Template::Simple:
     file: lib/Dancer2/Template/Simple.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Template::TemplateToolkit:
     file: lib/Dancer2/Template/TemplateToolkit.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Template::Tiny:
     file: lib/Dancer2/Template/Tiny.pm
-    version: 0.156001
+    version: 0.157000
   Dancer2::Test:
     file: lib/Dancer2/Test.pm
-    version: 0.156001
+    version: 0.157000
 recommends:
   CGI::Deurl::XS: 0
   Crypt::URandom: 0
@@ -245,10 +243,10 @@ requires:
   HTTP::Date: 0
   HTTP::Headers: 0
   HTTP::Server::PSGI: 0
+  HTTP::Tiny: 0
   Hash::Merge::Simple: 0
   IO::File: 0
   JSON: 0
-  LWP::UserAgent: 0
   List::Util: 0
   MIME::Base64: 3.13
   MIME::Types: 0
@@ -293,4 +291,4 @@ resources:
   bugtracker: https://github.com/PerlDancer/Dancer2/issues
   homepage: http://perldancer.org/
   repository: git://github.com/PerlDancer/Dancer2.git
-version: 0.156001
+version: 0.157000
@@ -54,10 +54,10 @@ my %WriteMakefileArgs = (
     "HTTP::Date" => 0,
     "HTTP::Headers" => 0,
     "HTTP::Server::PSGI" => 0,
+    "HTTP::Tiny" => 0,
     "Hash::Merge::Simple" => 0,
     "IO::File" => 0,
     "JSON" => 0,
-    "LWP::UserAgent" => 0,
     "List::Util" => 0,
     "MIME::Base64" => "3.13",
     "MIME::Types" => 0,
@@ -103,27 +103,25 @@ my %WriteMakefileArgs = (
     "File::Temp" => "0.22",
     "FindBin" => 0,
     "HTTP::Body" => 0,
+    "HTTP::Cookies" => 0,
     "HTTP::Request" => 0,
     "HTTP::Request::Common" => 0,
     "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",
     "Test::MockTime" => 0,
     "Test::More" => "0.92",
-    "Test::Script" => 0,
-    "Test::TCP" => "1.13",
     "YAML" => 0,
     "lib" => 0,
     "utf8" => 0,
     "vars" => 0
   },
-  "VERSION" => "0.156001",
+  "VERSION" => "0.157000",
   "test" => {
-    "TESTS" => "t/*.t t/classes/Dancer2-Core-Factory/*.t t/classes/Dancer2-Core-Hook/*.t t/classes/Dancer2-Core-Request/*.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-Headers/*.t t/classes/Dancer2-Core-Role-Serializer/*.t t/classes/Dancer2-Core-Role-StandardResponses/*.t t/classes/Dancer2-Core-Route/*.t t/classes/Dancer2-Core-Runner/*.t t/classes/Dancer2-Core/*.t t/classes/Dancer2/*.t t/dsl/*.t t/issues/*.t t/issues/gh-639/fails/*.t t/issues/gh-639/succeeds/*.t t/roles/*.t t/route-pod-coverage/*.t t/scope_problems/*.t t/template_tiny/*.t"
+    "TESTS" => "t/*.t t/classes/Dancer2-Core-Factory/*.t t/classes/Dancer2-Core-Hook/*.t t/classes/Dancer2-Core-Request/*.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-Headers/*.t t/classes/Dancer2-Core-Role-Serializer/*.t t/classes/Dancer2-Core-Role-StandardResponses/*.t t/classes/Dancer2-Core-Route/*.t t/classes/Dancer2-Core-Runner/*.t t/classes/Dancer2-Core/*.t t/classes/Dancer2/*.t t/dsl/*.t t/issues/*.t t/issues/gh-639/fails/*.t t/issues/gh-639/succeeds/*.t t/issues/gh-650/*.t t/roles/*.t t/route-pod-coverage/*.t t/scope_problems/*.t t/template_tiny/*.t"
   }
 );
 
@@ -152,18 +150,18 @@ my %FallbackPrereqs = (
   "File::Temp" => "0.22",
   "FindBin" => 0,
   "HTTP::Body" => 0,
+  "HTTP::Cookies" => 0,
   "HTTP::Date" => 0,
   "HTTP::Headers" => 0,
   "HTTP::Request" => 0,
   "HTTP::Request::Common" => 0,
   "HTTP::Server::PSGI" => 0,
+  "HTTP::Tiny" => 0,
   "Hash::Merge::Simple" => 0,
   "IO::File" => 0,
   "IO::Handle" => 0,
   "IPC::Open3" => 0,
   "JSON" => 0,
-  "LWP::Protocol::PSGI" => "0.06",
-  "LWP::UserAgent" => 0,
   "List::Util" => 0,
   "MIME::Base64" => "3.13",
   "MIME::Types" => 0,
@@ -199,8 +197,6 @@ my %FallbackPrereqs = (
   "Test::Memory::Cycle" => "1.04",
   "Test::MockTime" => 0,
   "Test::More" => "0.92",
-  "Test::Script" => 0,
-  "Test::TCP" => "1.13",
   "Try::Tiny" => 0,
   "URI" => 0,
   "URI::Escape" => 0,
@@ -1,13 +1,13 @@
 # ABSTRACT: create new Dancer2 application
 package Dancer2::CLI::Command::gen;
-$Dancer2::CLI::Command::gen::VERSION = '0.156001';
+$Dancer2::CLI::Command::gen::VERSION = '0.157000';
 use strict;
 use warnings;
 
 use App::Cmd::Setup -command;
 
+use HTTP::Tiny;
 use File::Find;
-use LWP::UserAgent;
 use File::Path 'mkpath';
 use File::Spec::Functions;
 use File::ShareDir 'dist_dir';
@@ -259,12 +259,10 @@ Please check http://search.cpan.org/dist/Dancer2/ for updates.
 sub _send_http_request {
     my $url = shift;
 
-    my $ua = LWP::UserAgent->new;
-    $ua->timeout(5);
-    $ua->env_proxy();
+    my $ua = HTTP::Tiny->new( timeout => 5 );
 
     my $response = $ua->get($url);
-    return $response->is_success ? $response->content : undef;
+    return $response->{'success'} ? $response->{'content'} : undef;
 }
 
 1;
@@ -281,7 +279,7 @@ Dancer2::CLI::Command::gen - create new Dancer2 application
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::CLI::Command::version;
 # ABSTRACT: display version
-$Dancer2::CLI::Command::version::VERSION = '0.156001';
+$Dancer2::CLI::Command::version::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::CLI;
 # ABSTRACT: Dancer2 cli application
-$Dancer2::CLI::VERSION = '0.156001';
+$Dancer2::CLI::VERSION = '0.157000';
 use App::Cmd::Setup -app;
 
 1;
@@ -17,7 +17,7 @@ Dancer2::CLI - Dancer2 cli application
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Config;
 # ABSTRACT: Configure Dancer2 to suit your needs
-$Dancer2::Config::VERSION = '0.156001';
+$Dancer2::Config::VERSION = '0.157000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Config - Configure Dancer2 to suit your needs
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -284,10 +284,6 @@ versions and the environment (or "dancefloor").
 
 Conforms to the environment variable C<DANCER_STARTUP_INFO>.
 
-=head3 warnings (boolean)
-
-If set to true, tells Dancer2 to consider all warnings as blocking errors.
-
 =head3 traces (boolean)
 
 If set to true, Dancer2 will display full stack traces when a warning or a
@@ -1,6 +1,6 @@
 package Dancer2::Cookbook;
 # ABSTRACT: Example-driven quick-start to the Dancer2 web framework
-$Dancer2::Cookbook::VERSION = '0.156001';
+$Dancer2::Cookbook::VERSION = '0.157000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Cookbook - Example-driven quick-start to the Dancer2 web framework
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
diff --git a/var/tmp/source/XSAWYERX/Dancer2-0.156001/Dancer2-0.156001/lib/Dancer2/Core/.Request.pm.swp b/var/tmp/source/XSAWYERX/Dancer2-0.156001/Dancer2-0.156001/lib/Dancer2/Core/.Request.pm.swp
deleted file mode 100644
index b7d14719..00000000
Binary files a/var/tmp/source/XSAWYERX/Dancer2-0.156001/Dancer2-0.156001/lib/Dancer2/Core/.Request.pm.swp and /dev/null differ
@@ -1,6 +1,6 @@
 # ABSTRACT: encapsulation of Dancer2 packages
 package Dancer2::Core::App;
-$Dancer2::Core::App::VERSION = '0.156001';
+$Dancer2::Core::App::VERSION = '0.157000';
 use Moo;
 use Carp               'croak';
 use Scalar::Util       'blessed';
@@ -531,6 +531,7 @@ sub _build_default_config {
         logger         => ( $ENV{DANCER_LOGGER}       || 'console' ),
         views          => ( $ENV{DANCER_VIEWS}
                             || path( $self->config_location, 'views' ) ),
+        environment    => $self->environment,
         appdir         => $self->location,
         public_dir     => $public,
         static_handler => ( -d $public ),
@@ -1098,6 +1099,10 @@ DISPATCH:
         my $http_method = lc $request->method;
         my $path_info   =    $request->path_info;
 
+        # Add request to app and engines
+        $self->set_request($request);
+        $_->set_request( $request ) for $self->defined_engines;
+
         $self->log( core => "looking for $http_method $path_info" );
 
         ROUTE:
@@ -1111,10 +1116,6 @@ 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.
             if ( my $sess = Dancer2->runner->{'internal_sessions'}{$cname} ) {
@@ -1311,7 +1312,7 @@ Dancer2::Core::App - encapsulation of Dancer2 packages
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Cookie;
 # ABSTRACT: A cookie representing class
-$Dancer2::Core::Cookie::VERSION = '0.156001';
+$Dancer2::Core::Cookie::VERSION = '0.157000';
 use Moo;
 use URI::Escape;
 use Dancer2::Core::Types;
@@ -106,7 +106,7 @@ Dancer2::Core::Cookie - A cookie representing class
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Dancer2's Domain Specific Language (DSL)
 
 package Dancer2::Core::DSL;
-$Dancer2::Core::DSL::VERSION = '0.156001';
+$Dancer2::Core::DSL::VERSION = '0.157000';
 use Moo;
 use Carp;
 use Class::Load 'load_class';
@@ -400,7 +400,7 @@ Dancer2::Core::DSL - Dancer2's Domain Specific Language (DSL)
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =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.156001';
+$Dancer2::Core::Dispatcher::VERSION = '0.157000';
 use Moo;
 
 use Dancer2::Core::Types;
@@ -70,7 +70,7 @@ Dancer2::Core::Dispatcher - Class for dispatching request to the appropriate rou
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Error;
 # ABSTRACT: Class representing fatal errors
-$Dancer2::Core::Error::VERSION = '0.156001';
+$Dancer2::Core::Error::VERSION = '0.157000';
 use Moo;
 use Carp;
 use Dancer2::Core::Types;
@@ -496,7 +496,7 @@ Dancer2::Core::Error - Class representing fatal errors
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Factory;
 # ABSTRACT: Instantiate components by type and name
-$Dancer2::Core::Factory::VERSION = '0.156001';
+$Dancer2::Core::Factory::VERSION = '0.157000';
 use Moo;
 use Dancer2::Core;
 use Class::Load 'try_load_class';
@@ -33,7 +33,7 @@ Dancer2::Core::Factory - Instantiate components by type and name
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,7 +1,7 @@
 # ABSTRACT: helper for rendering HTTP status codes for Dancer2
 
 package Dancer2::Core::HTTP;
-$Dancer2::Core::HTTP::VERSION = '0.156001';
+$Dancer2::Core::HTTP::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -134,7 +134,7 @@ Dancer2::Core::HTTP - helper for rendering HTTP status codes for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 FUNCTIONS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Hook;
 # ABSTRACT: Manipulate hooks with Dancer2
-$Dancer2::Core::Hook::VERSION = '0.156001';
+$Dancer2::Core::Hook::VERSION = '0.157000';
 use Moo;
 use Dancer2::Core::Types;
 use Carp;
@@ -51,7 +51,7 @@ Dancer2::Core::Hook - Manipulate hooks with Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Class to ease manipulation of MIME types
 
 package Dancer2::Core::MIME;
-$Dancer2::Core::MIME::VERSION = '0.156001';
+$Dancer2::Core::MIME::VERSION = '0.157000';
 use Moo;
 
 use MIME::Types;
@@ -90,7 +90,7 @@ Dancer2::Core::MIME - Class to ease manipulation of MIME types
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Request::Upload;
 # ABSTRACT: Class representing file upload requests
-$Dancer2::Core::Request::Upload::VERSION = '0.156001';
+$Dancer2::Core::Request::Upload::VERSION = '0.157000';
 use Moo;
 
 use Carp;
@@ -91,7 +91,7 @@ Dancer2::Core::Request::Upload - Class representing file upload requests
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Dancer2::Core::Request;
-$Dancer2::Core::Request::VERSION = '0.156001';
+$Dancer2::Core::Request::VERSION = '0.157000';
 # ABSTRACT: Interface for accessing incoming requests
 
 use Moo;
@@ -684,7 +684,7 @@ Dancer2::Core::Request - Interface for accessing incoming requests
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Response object for Dancer2
 
 package Dancer2::Core::Response;
-$Dancer2::Core::Response::VERSION = '0.156001';
+$Dancer2::Core::Response::VERSION = '0.157000';
 use Moo;
 
 use Encode;
@@ -206,7 +206,7 @@ Dancer2::Core::Response - Response object for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 ATTRIBUTES
 
@@ -1,6 +1,6 @@
 # ABSTRACT: Config role for Dancer2 core objects
 package Dancer2::Core::Role::ConfigReader;
-$Dancer2::Core::Role::ConfigReader::VERSION = '0.156001';
+$Dancer2::Core::Role::ConfigReader::VERSION = '0.157000';
 use Moo::Role;
 
 use File::Spec;
@@ -274,7 +274,7 @@ Dancer2::Core::Role::ConfigReader - Config role for Dancer2 core objects
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::DSL;
 # ABSTRACT: Role for DSL
-$Dancer2::Core::Role::DSL::VERSION = '0.156001';
+$Dancer2::Core::Role::DSL::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Engine;
 # ABSTRACT: Role for engines
-$Dancer2::Core::Role::Engine::VERSION = '0.156001';
+$Dancer2::Core::Role::Engine::VERSION = '0.157000';
 use Moo::Role;
 use Dancer2::Core::Types;
 
@@ -42,7 +42,7 @@ Dancer2::Core::Role::Engine - Role for engines
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Handler;
 # ABSTRACT: Role for Handlers
-$Dancer2::Core::Role::Handler::VERSION = '0.156001';
+$Dancer2::Core::Role::Handler::VERSION = '0.157000';
 use Moo::Role;
 use Dancer2::Core::Types;
 
@@ -26,7 +26,7 @@ Dancer2::Core::Role::Handler - Role for Handlers
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 ATTRIBUTES
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::HasLocation;
 # ABSTRACT: Role for application location "guessing"
-$Dancer2::Core::Role::HasLocation::VERSION = '0.156001';
+$Dancer2::Core::Role::HasLocation::VERSION = '0.157000';
 use Moo::Role;
 use Dancer2::Core::Types;
 use Dancer2::FileUtils;
@@ -17,6 +17,7 @@ has caller => (
     isa     => Str,
     default => quote_sub( q{
         my ( $caller, $script ) = CORE::caller;
+        $script = File::Spec->abs2rel( $script ) if File::Spec->file_name_is_absolute( $script );
         $script;
     } ),
 );
@@ -87,7 +88,7 @@ Dancer2::Core::Role::HasLocation - Role for application location "guessing"
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Role for handling headers
 
 package Dancer2::Core::Role::Headers;
-$Dancer2::Core::Role::Headers::VERSION = '0.156001';
+$Dancer2::Core::Role::Headers::VERSION = '0.157000';
 use Moo::Role;
 use Dancer2::Core::Types;
 use HTTP::Headers;
@@ -52,7 +52,7 @@ Dancer2::Core::Role::Headers - Role for handling headers
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Hookable;
 # ABSTRACT: Role for hookable objects
-$Dancer2::Core::Role::Hookable::VERSION = '0.156001';
+$Dancer2::Core::Role::Hookable::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Logger;
 # ABSTRACT: Role for logger engines
-$Dancer2::Core::Role::Logger::VERSION = '0.156001';
+$Dancer2::Core::Role::Logger::VERSION = '0.157000';
 use Dancer2::Core::Types;
 
 use Moo::Role;
@@ -30,8 +30,9 @@ has auto_encoding_charset => (
 );
 
 has app_name => (
-    is  => 'ro',
-    isa => Str,
+    is      => 'ro',
+    isa     => Str,
+    default => sub {'-'},
 );
 
 has log_format => (
@@ -87,7 +88,7 @@ sub format_message {
             );
         }
         elsif ( $type eq 'h' ) {
-            return $request->header( $block ) || '-';
+            return ( $request && $request->header($block) ) || '-';
         }
         else {
             Carp::carp("{$block}$type not supported");
@@ -116,8 +117,10 @@ sub format_message {
         m => sub {$message},
         f => sub { $stack[1] || '-' },
         l => sub { $stack[2] || '-' },
-        h => sub { $request->remote_host || $request->address || '-' },
-        i => sub { $request->id || '-' },
+        h => sub {
+            ( $request && $request->remote_host || $request->address ) || '-'
+        },
+        i => sub { ( $request && $request->id ) || '-' },
     };
 
     my $char_mapping = sub {
@@ -193,7 +196,7 @@ Dancer2::Core::Role::Logger - Role for logger engines
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::Serializer;
 # ABSTRACT: Role for Serializer engines
-$Dancer2::Core::Role::Serializer::VERSION = '0.156001';
+$Dancer2::Core::Role::Serializer::VERSION = '0.157000';
 use Moo::Role;
 use Try::Tiny;
 use Dancer2::Core::Types;
@@ -91,7 +91,7 @@ Dancer2::Core::Role::Serializer - Role for Serializer engines
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,17 +1,14 @@
 package Dancer2::Core::Role::SessionFactory::File;
-#ABSTRACT: Role for file-based session factories
-$Dancer2::Core::Role::SessionFactory::File::VERSION = '0.156001';
-use strict;
-use warnings;
+# ABSTRACT: Role for file-based session factories
+$Dancer2::Core::Role::SessionFactory::File::VERSION = '0.157000';
+use Moo::Role;
+with 'Dancer2::Core::Role::SessionFactory';
+
 use Carp 'croak';
 use Dancer2::Core::Types;
 use Dancer2::FileUtils qw(path set_file_mode);
 use Fcntl ':flock';
 
-use Moo::Role;
-
-with 'Dancer2::Core::Role::SessionFactory';
-
 #--------------------------------------------------------------------------#
 # Required by classes consuming this role
 #--------------------------------------------------------------------------#
@@ -113,7 +110,7 @@ Dancer2::Core::Role::SessionFactory::File - Role for file-based session factorie
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,8 +1,9 @@
 package Dancer2::Core::Role::SessionFactory;
-#ABSTRACT: Role for session factories
-$Dancer2::Core::Role::SessionFactory::VERSION = '0.156001';
-use strict;
-use warnings;
+# ABSTRACT: Role for session factories
+$Dancer2::Core::Role::SessionFactory::VERSION = '0.157000';
+use Moo::Role;
+with 'Dancer2::Core::Role::Engine';
+
 use Carp 'croak';
 use Class::Load 'try_load_class';
 use Dancer2::Core::Session;
@@ -11,9 +12,6 @@ use Digest::SHA 'sha1';
 use List::Util 'shuffle';
 use MIME::Base64 'encode_base64url';
 
-use Moo::Role;
-with 'Dancer2::Core::Role::Engine';
-
 sub supported_hooks {
     qw/
       engine.session.before_retrieve
@@ -260,7 +258,7 @@ Dancer2::Core::Role::SessionFactory - Role for session factories
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Role::StandardResponses;
 # ABSTRACT: Role to provide commonly used responses
-$Dancer2::Core::Role::StandardResponses::VERSION = '0.156001';
+$Dancer2::Core::Role::StandardResponses::VERSION = '0.157000';
 use Moo::Role;
 use Dancer2::Core::HTTP;
 
@@ -35,7 +35,7 @@ Dancer2::Core::Role::StandardResponses - Role to provide commonly used responses
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 METHODS
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Role for template engines
 
 package Dancer2::Core::Role::Template;
-$Dancer2::Core::Role::Template::VERSION = '0.156001';
+$Dancer2::Core::Role::Template::VERSION = '0.157000';
 use Dancer2::Core::Types;
 use Dancer2::FileUtils qw'path';
 use Carp 'croak';
@@ -223,7 +223,7 @@ Dancer2::Core::Role::Template - Role for template engines
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,10 +1,6 @@
-# ABSTRACT: Dancer2's route handler
-
 package Dancer2::Core::Route;
-$Dancer2::Core::Route::VERSION = '0.156001';
-use strict;
-use warnings;
-
+# ABSTRACT: Dancer2's route handler
+$Dancer2::Core::Route::VERSION = '0.157000';
 use Moo;
 use Dancer2::Core::Types;
 use Carp 'croak';
@@ -227,7 +223,7 @@ Dancer2::Core::Route - Dancer2's route handler
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 ATTRIBUTES
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Runner;
 # ABSTRACT: Top-layer class to start a dancer app
-$Dancer2::Core::Runner::VERSION = '0.156001';
+$Dancer2::Core::Runner::VERSION = '0.157000';
 use Moo;
 use Carp 'croak';
 use Dancer2::Core::MIME;
@@ -93,7 +93,6 @@ sub _build_config {
     return {
         behind_proxy     => 0,
         apphandler       => ( $ENV{DANCER_APPHANDLER} || 'Standalone' ),
-        warnings         => ( $ENV{DANCER_WARNINGS}   || 0 ),
         traces           => ( $ENV{DANCER_TRACES}     || 0 ),
         host             => ( $ENV{DANCER_SERVER}     || '0.0.0.0' ),
         port             => ( $ENV{DANCER_PORT}       || '3000' ),
@@ -260,7 +259,7 @@ Dancer2::Core::Runner - Top-layer class to start a dancer app
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 AUTHOR
 
@@ -1,9 +1,6 @@
 package Dancer2::Core::Session;
-$Dancer2::Core::Session::VERSION = '0.156001';
-#ABSTRACT: class to represent any session object
-
-use strict;
-use warnings;
+# ABSTRACT: class to represent any session object
+$Dancer2::Core::Session::VERSION = '0.157000';
 use Moo;
 use Dancer2::Core::Types;
 use Dancer2::Core::Time;
@@ -71,7 +68,7 @@ Dancer2::Core::Session - class to represent any session object
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Time;
-#ABSTRACT: class to handle common helpers for time manipulations
-$Dancer2::Core::Time::VERSION = '0.156001';
+# ABSTRACT: class to handle common helpers for time manipulations
+$Dancer2::Core::Time::VERSION = '0.157000';
 use Moo;
 
 has seconds => (
@@ -134,7 +134,7 @@ Dancer2::Core::Time - class to handle common helpers for time manipulations
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Core::Types;
 # ABSTRACT: Moo types for Dancer2 core.
-$Dancer2::Core::Types::VERSION = '0.156001';
+$Dancer2::Core::Types::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Core;
 # ABSTRACT: Core libraries for Dancer2 2.0
-$Dancer2::Core::VERSION = '0.156001';
+$Dancer2::Core::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -29,7 +29,7 @@ Dancer2::Core - Core libraries for Dancer2 2.0
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 FUNCTIONS
 
@@ -1,6 +1,6 @@
 package Dancer2::FileUtils;
 # ABSTRACT: File utility helpers
-$Dancer2::FileUtils::VERSION = '0.156001';
+$Dancer2::FileUtils::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -101,7 +101,7 @@ Dancer2::FileUtils - File utility helpers
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Handler::AutoPage;
 # ABSTRACT: Class for handling the AutoPage feature
-$Dancer2::Handler::AutoPage::VERSION = '0.156001';
+$Dancer2::Handler::AutoPage::VERSION = '0.157000';
 use Moo;
 use Carp 'croak';
 use Dancer2::Core::Types;
@@ -71,7 +71,7 @@ Dancer2::Handler::AutoPage - Class for handling the AutoPage feature
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Handler::File;
 # ABSTRACT: class for handling file content rendering
-$Dancer2::Handler::File::VERSION = '0.156001';
+$Dancer2::Handler::File::VERSION = '0.157000';
 use Carp 'croak';
 use Moo;
 use HTTP::Date;
@@ -82,14 +82,8 @@ sub code {
             $path =~ s/^\Q$prefix\E//;
         }
 
-        my @tokens =
-          File::Spec->splitdir( join '',
-            ( File::Spec->splitpath($path) )[ 1, 2 ] );
-        if ( grep $_ eq '..', @tokens ) {
-            return $self->standard_response( $app, 403 );
-        }
-
-        my $file_path = path( $self->public_dir, @tokens );
+        my $file_path = $self->merge_paths( $path, $self->public_dir );
+        return $self->standard_response( $app, 403 ) if !defined $file_path;
 
         if ( !-f $file_path ) {
             $app->response->has_passed(1);
@@ -135,6 +129,24 @@ sub code {
     };
 }
 
+sub merge_paths {
+    my ( undef, $path, $public_dir ) = @_;
+
+    my ( $volume, $dirs, $file ) = File::Spec->splitpath( $path );
+    my @tokens = File::Spec->splitdir( "$dirs$file" );
+    my $updir = File::Spec->updir;
+    return if grep $_ eq $updir, @tokens;
+
+    my ( $pub_vol, $pub_dirs, $pub_file ) = File::Spec->splitpath( $public_dir );
+    my @pub_tokens = File::Spec->splitdir( "$pub_dirs$pub_file" );
+    return if length $volume and length $pub_vol and $volume ne $pub_vol;
+
+    my @final_vol = ( length $pub_vol ? $pub_vol : length $volume ? $volume : () );
+    my @file_path = ( @final_vol, @pub_tokens, @tokens );
+    my $file_path = path( @file_path );
+    return $file_path;
+}
+
 1;
 
 __END__
@@ -149,7 +161,7 @@ Dancer2::Handler::File - class for handling file content rendering
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =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.156001';
+$Dancer2::Logger::Capture::Trap::VERSION = '0.157000';
 use Moo;
 use Dancer2::Core::Types;
 
@@ -11,8 +11,12 @@ has storage => (
 );
 
 sub store {
-    my ( $self, $level, $message ) = @_;
-    push @{ $self->storage }, { level => $level, message => $message };
+    my ( $self, $level, $message, $fmt_string ) = @_;
+    push @{ $self->storage }, {
+        level     => $level,
+        message   => $message,
+        formatted => $fmt_string,
+    };
 }
 
 sub read {
@@ -37,7 +41,7 @@ Dancer2::Logger::Capture::Trap - a place to store captured Dancer2 logs
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Capture;
 # ABSTRACT: Capture dancer logs
-$Dancer2::Logger::Capture::VERSION = '0.156001';
+$Dancer2::Logger::Capture::VERSION = '0.157000';
 use Moo;
 use Dancer2::Logger::Capture::Trap;
 
@@ -17,7 +17,10 @@ sub _build_trapper { Dancer2::Logger::Capture::Trap->new }
 sub log {
     my ( $self, $level, $message ) = @_;
 
-    $self->trapper->store( $level => $message );
+    $self->trapper->store(
+        $level, $message, $self->format_message( $level => $message )
+    );
+
     return;
 }
 
@@ -35,7 +38,7 @@ Dancer2::Logger::Capture - Capture dancer logs
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Console;
 # ABSTRACT: Console logger
-$Dancer2::Logger::Console::VERSION = '0.156001';
+$Dancer2::Logger::Console::VERSION = '0.157000';
 use Moo;
 
 with 'Dancer2::Core::Role::Logger';
@@ -24,7 +24,7 @@ Dancer2::Logger::Console - Console logger
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Diag;
 # ABSTRACT: Test::More diag() logging engine for Dancer2
-$Dancer2::Logger::Diag::VERSION = '0.156001';
+$Dancer2::Logger::Diag::VERSION = '0.157000';
 use Moo;
 use Test::More;
 
@@ -26,7 +26,7 @@ Dancer2::Logger::Diag - Test::More diag() logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::File;
 # ABSTRACT: file-based logging engine for Dancer2
-$Dancer2::Logger::File::VERSION = '0.156001';
+$Dancer2::Logger::File::VERSION = '0.157000';
 use Carp 'carp';
 use Moo;
 use Dancer2::Core::Types;
@@ -111,7 +111,7 @@ Dancer2::Logger::File - file-based logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Note;
 # ABSTRACT: Test::More note() logging engine for Dancer2
-$Dancer2::Logger::Note::VERSION = '0.156001';
+$Dancer2::Logger::Note::VERSION = '0.157000';
 use Moo;
 use Test::More;
 
@@ -26,7 +26,7 @@ Dancer2::Logger::Note - Test::More note() logging engine for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Logger::Null;
 # ABSTRACT: Blackhole-like silent logging engine for Dancer2
-$Dancer2::Logger::Null::VERSION = '0.156001';
+$Dancer2::Logger::Null::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Manual::Migration;
 # ABSTRACT: Migrating from Dancer to Dancer2
-$Dancer2::Manual::Migration::VERSION = '0.156001';
+$Dancer2::Manual::Migration::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -18,13 +18,47 @@ Dancer2::Manual::Migration - Migrating from Dancer to Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 Migration from Dancer 1 to Dancer2
 
 This document covers some changes that users will need to be aware of
 while upgrading from L<Dancer> (version 1) to L<Dancer2>.
 
+=head2 Launcher script bin/app.pl
+
+The default launcher script C<bin/app.pl> in L<Dancer> looked like this:
+
+    #!/usr/bin/env perl
+    use Dancer;
+    use MyApp;
+    dance;
+
+In L<Dancer2> it looks like this:
+
+    #!/usr/bin/env perl
+
+    use strict;
+    use warnings;
+    use FindBin;
+    use lib "$FindBin::Bin/../lib";
+
+    use MyApp;
+    MyApp->to_app;
+
+So you need to remove the C<use Dancer;> part, replace the C<dance;> command
+by C<< MyApp->to_app; >> (where MyApp is the name of your application), and
+add the following lines:
+
+    use strict;
+    use warnings;
+    use FindBin;
+    use lib "$FindBin::Bin/../lib";
+
+There is a L<Dancer Advent Calendar|http://advent.perldancer.org> article
+L<< covering the C<to_app> keyword|http://advent.perldancer.org/2014/9 >>
+and its usage.
+
 =head2 Apps
 
 1. In L<Dancer2>, each module is a B<separate application> with its own
@@ -91,6 +125,36 @@ Thus, these modules can be used for speed improvement provided:
 
 =back
 
+=head2 Request
+
+The request object (L<Dancer2::Core::Request>) is now deferring much of
+its code to L<Plack::Request> to be consistent with the known interface
+to L<PSGI> requests.
+
+Currently the following attributes pass directly to L<Plack::Request>:
+
+C<address>, C<remote_host>, C<protocol>, C<port>, C<method>, C<user>,
+C<request_uri>, C<script_name>, C<content_length>, C<content_type>,
+C<content_encoding>, C<referer>, and C<user_agent>.
+
+If previous attributes returned I<undef> for no value beforehand, they
+will return whatever L<Plack::Request> defines now, which just might be
+an empty list.
+
+For example:
+
+    my %data = (
+        referer    => request->referer,
+        user_agent => request->user_agent,
+    );
+
+should be replaced by:
+
+    my %data = (
+        referer    => request->referer    || '',
+        user_agent => request->user_agent || '',
+    );
+
 =head2 Plugins: plugin_setting
 
 C<plugin_setting> returns the configuration of the plugin. It can only be
@@ -118,7 +182,6 @@ For example:
 
     use strict;
     use warnings;
-
     use Test::More tests => 2;
     use Plack::Test;
     use HTTP::Request::Common;
@@ -203,11 +266,34 @@ server and reads the configuration options in your command line utilities.
 
 =head2 Engines
 
-Engines now receive a logger that consumes L<Dancer2::Core::Role::Logger> in
-order to log errors. The attribute is called C<logger>.
+=over 4
+
+=item * Engines receive a logging callback
+
+Engines now receive a logging callback named C<log_cb>. Engines can use it
+to log anything in run-time, without having to worry about what logging
+engine is used.
+
+This is provided as a callback because the logger might be changed in
+run-time and we want engines to be able to always reach the current one
+without having a reference back to the core application object.
 
 The logger engine doesn't have the attribute since it is the logger itself.
 
+=item * Engines handle encoding consistently
+
+All engines are now expected to handle encoding on their own. User code
+is expected to be in internal Perl representation.
+
+Therefore, all serializers, for example, should deserialize to the Perl
+representation. Templates, in turn, encode to UTF-8 if requested by the
+user, or by default.
+
+One side-effect of this is that C<from_yaml> will call L<YAML>'s C<Load>
+function with decoded input.
+
+=back
+
 =head3 Serializers
 
 You no longer need to implement the C<loaded> method. It is simply
@@ -215,6 +301,29 @@ unnecessary.
 
 =head2 Configuration
 
+=head3 warnings
+
+The C<warnings> configuration option, along with the environment variable
+C<DANCER_WARNINGS>, have been removed and have no effect whatsoever.
+
+They were added when someone requested to be able to load Dancer without
+the L<warnings> pragma, which it adds, just like L<Moose>, L<Moo>, and
+other modules provide.
+
+If you want this to happen now (which you probably shouldn't be doing),
+you can always control it lexically:
+
+    use Dancer2;
+    no warnings;
+
+You can also use Dancer2 within a narrower scope:
+
+    { use Dancer2 }
+    use strict;
+    # warnings are not turned on
+
+However, having L<warnings> turned it is very recommended.
+
 =head3 server_tokens
 
 The configuration C<server_tokens> has been introduced in the reverse (but
@@ -222,6 +331,53 @@ more sensible, and Plack-compatible) form as C<no_server_tokens>.
 
 C<DANCER_SERVER_TOKENS> changed to C<DANCER_NO_SERVER_TOKENS>.
 
+=head3 engines
+
+If you want to use Template::Toolkit instead of the built-in simple templating
+engine you used to enable the following line in the config.yml file.
+
+    template: "template_toolkit"
+
+That was enough to get started. The start_tag and end_tag it used were the same as in
+the simple template <% and %> respectively.
+
+If you wanted to further customize the Template::Toolkit you could also enable or add
+the following:
+
+    engines:
+      template_toolkit:
+         encoding:  'utf8'
+         start_tag: '[%'
+         end_tag:   '%]'
+
+In Dancer 2 you can also enable Template::Toolkit with the same configuration option:
+
+    template: "template_toolkit"
+
+But the default start_tag and end_tag are now [% and %], so if you used the default in Dancer 1
+now you will have to explicitly change the start_tag and end_tag values.
+The configuration also got an extral level of depth. Under the C<engine> key there is a C<template>
+key and the C<template_toolkit> key comes below that. As in this example:
+
+    engines:
+      template:
+        template_toolkit:
+          start_tag: '<%'
+          end_tag:   '%>'
+
+In a nutshell, if you used to have
+
+    template: "template_toolkit"
+
+You need to replace it with
+
+    template: "template_toolkit"
+    engines:
+      template:
+        template_toolkit:
+          start_tag: '<%'
+          end_tag:   '%>'
+
 =head2 Keywords
 
 =head3 load
@@ -236,6 +392,11 @@ This keyword doesn't exist in Dancer2.
 
 =head3 session
 
+In L<Dancer> a session was created and a cookie was sent just by rendering a page
+using the C<template> function. In L<Dancer2> one needs to actully set a value in
+a session object using the C<session> function in order to create the session
+and send the cookie.
+
 The session keyword has multiple states:
 
 =over 4
@@ -1,6 +1,6 @@
 package Dancer2::Manual::Testing;
 # ABSTRACT: Writing tests for Dancer2
-$Dancer2::Manual::Testing::VERSION = '0.156001';
+$Dancer2::Manual::Testing::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -18,7 +18,7 @@ Dancer2::Manual::Testing - Writing tests for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 Basic application testing
 
@@ -1,6 +1,6 @@
 # ABSTRACT: A gentle introduction to Dancer2
 package Dancer2::Manual;
-$Dancer2::Manual::VERSION = '0.156001';
+$Dancer2::Manual::VERSION = '0.157000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Manual - A gentle introduction to Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1611,6 +1611,10 @@ You can call it as a method on the class or as a DSL:
 
     my $app = to_app;
 
+There is a
+L<Dancer Advent Calendar article|http://advent.perldancer.org/2014/9> covering
+this keyword and its usage further.
+
 =head2 psgi_app
 
 Provides the same functionality as C<to_app> but uses the deprecated
@@ -1,6 +1,6 @@
 package Dancer2::Plugin;
 # ABSTRACT: Extending Dancer2's DSL with plugins
-$Dancer2::Plugin::VERSION = '0.156001';
+$Dancer2::Plugin::VERSION = '0.157000';
 use Moo::Role;
 use Carp 'croak', 'carp';
 use Dancer2::Core::DSL;
@@ -253,7 +253,7 @@ Dancer2::Plugin - Extending Dancer2's DSL with plugins
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Plugins;
 # ABSTRACT: Recommended Dancer2 plugins
-$Dancer2::Plugins::VERSION = '0.156001';
+$Dancer2::Plugins::VERSION = '0.157000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Plugins - Recommended Dancer2 plugins
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Policy;
 # ABSTRACT: Dancer core and community policy and standards of conduct
-$Dancer2::Policy::VERSION = '0.156001';
+$Dancer2::Policy::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -18,7 +18,7 @@ Dancer2::Policy - Dancer core and community policy and standards of conduct
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,7 +1,7 @@
 # ABSTRACT: Serializer for handling Dumper data
 
 package Dancer2::Serializer::Dumper;
-$Dancer2::Serializer::Dumper::VERSION = '0.156001';
+$Dancer2::Serializer::Dumper::VERSION = '0.157000';
 use Moo;
 use Carp 'croak';
 use Data::Dumper;
@@ -53,7 +53,7 @@ Dancer2::Serializer::Dumper - Serializer for handling Dumper data
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Serializer::JSON;
 # ABSTRACT: Serializer for handling JSON data
-$Dancer2::Serializer::JSON::VERSION = '0.156001';
+$Dancer2::Serializer::JSON::VERSION = '0.157000';
 use Moo;
 use JSON ();
 
@@ -55,7 +55,7 @@ Dancer2::Serializer::JSON - Serializer for handling JSON data
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Serializer::Mutable;
 # ABSTRACT: Serialize and deserialize content based on HTTP header
-$Dancer2::Serializer::Mutable::VERSION = '0.156001';
+$Dancer2::Serializer::Mutable::VERSION = '0.157000';
 use Moo;
 use Carp 'croak';
 use Encode;
@@ -104,7 +104,7 @@ Dancer2::Serializer::Mutable - Serialize and deserialize content based on HTTP h
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Serializer::YAML;
 # ABSTRACT: Serializer for handling YAML data
-$Dancer2::Serializer::YAML::VERSION = '0.156001';
+$Dancer2::Serializer::YAML::VERSION = '0.157000';
 use Moo;
 use Carp 'croak';
 use Encode;
@@ -49,7 +49,7 @@ Dancer2::Serializer::YAML - Serializer for handling YAML data
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,6 +1,6 @@
 package Dancer2::Session::Simple;
 # ABSTRACT: in-memory session backend for Dancer2
-$Dancer2::Session::Simple::VERSION = '0.156001';
+$Dancer2::Session::Simple::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Dancer2::Session::YAML;
-$Dancer2::Session::YAML::VERSION = '0.156001';
+$Dancer2::Session::YAML::VERSION = '0.157000';
 # 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.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Dancer2::Template::Implementation::ForkedTiny;
-$Dancer2::Template::Implementation::ForkedTiny::VERSION = '0.156001';
+$Dancer2::Template::Implementation::ForkedTiny::VERSION = '0.157000';
 # 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.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,8 +1,6 @@
 package Dancer2::Template::Simple;
 # ABSTRACT: Pure Perl 5 template engine for Dancer2
-$Dancer2::Template::Simple::VERSION = '0.156001';
-use strict;
-use warnings;
+$Dancer2::Template::Simple::VERSION = '0.157000';
 use Moo;
 use Dancer2::FileUtils 'read_file_content';
 
@@ -156,7 +154,7 @@ Dancer2::Template::Simple - Pure Perl 5 template engine for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,11 +1,9 @@
 # ABSTRACT: Template toolkit engine for Dancer2
 
 package Dancer2::Template::TemplateToolkit;
-$Dancer2::Template::TemplateToolkit::VERSION = '0.156001';
-use strict;
-use warnings;
-use Carp qw/croak/;
+$Dancer2::Template::TemplateToolkit::VERSION = '0.157000';
 use Moo;
+use Carp qw/croak/;
 use Dancer2::Core::Types;
 use Template;
 
@@ -63,7 +61,7 @@ Dancer2::Template::TemplateToolkit - Template toolkit engine for Dancer2
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Template::Tiny;
 # ABSTRACT: Template::Tiny engine for Dancer2
-$Dancer2::Template::Tiny::VERSION = '0.156001';
+$Dancer2::Template::Tiny::VERSION = '0.157000';
 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.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Test;
 # ABSTRACT: Useful routines for testing Dancer2 apps
-$Dancer2::Test::VERSION = '0.156001';
+$Dancer2::Test::VERSION = '0.157000';
 use strict;
 use warnings;
 
@@ -621,7 +621,7 @@ Dancer2::Test - Useful routines for testing Dancer2 apps
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,6 +1,6 @@
 package Dancer2::Tutorial;
 # ABSTRACT: An example to get you dancing
-$Dancer2::Tutorial::VERSION = '0.156001';
+$Dancer2::Tutorial::VERSION = '0.157000';
 __END__
 
 =pod
@@ -13,7 +13,7 @@ Dancer2::Tutorial - An example to get you dancing
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 What is Dancer2?
 
@@ -1,6 +1,6 @@
 package Dancer2;
 # ABSTRACT: Lightweight yet powerful web application framework
-$Dancer2::VERSION = '0.156001';
+$Dancer2::VERSION = '0.157000';
 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.156000'; # 2.156.0
+$Dancer2::VERSION ||= '0.157000';
 
 our $runner;
 
@@ -118,7 +118,7 @@ Dancer2 - Lightweight yet powerful web application framework
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 DESCRIPTION
 
@@ -183,6 +183,11 @@ Refer to L<Dancer2::Plugins> for a partial list of available Dancer2
 plugins. Note that although we try to keep this list up to date we
 expect plugin authors to tell us about new modules.
 
+=item * Dancer2 Migration guide
+
+L<Dancer2::Manual::Migration> provides the most up-to-date instruction on
+how to convert a Dancer (1) based application to Dancer2.
+
 =back
 
 =head1 METHODS
@@ -33,7 +33,7 @@ dancer2 - Dancer2 command line interface
 
 =head1 VERSION
 
-version 0.156001
+version 0.157000
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,9 @@
 #!/usr/bin/env perl
 
+use strict;
+use warnings;
 use FindBin;
 use lib "$FindBin::Bin/../lib";
 
 use [% appname %];
-[% appname %]->dance;
+[% appname %]->to_app;
@@ -12,6 +12,5 @@ warnings: 0
 # hide errors
 show_errors: 0
 
-# cache route resolution for maximum performance
-route_cache: 1
-
+# disable server tokens in production environments
+no_server_token: 1
@@ -55,10 +55,10 @@ do { my $x = {
                                       'HTTP::Date' => '0',
                                       'HTTP::Headers' => '0',
                                       'HTTP::Server::PSGI' => '0',
+                                      'HTTP::Tiny' => '0',
                                       'Hash::Merge::Simple' => '0',
                                       'IO::File' => '0',
                                       'JSON' => '0',
-                                      'LWP::UserAgent' => '0',
                                       'List::Util' => '0',
                                       'MIME::Base64' => '3.13',
                                       'MIME::Types' => '0',
@@ -115,19 +115,17 @@ do { my $x = {
                                    'File::Temp' => '0.22',
                                    'FindBin' => '0',
                                    'HTTP::Body' => '0',
+                                   'HTTP::Cookies' => '0',
                                    'HTTP::Request' => '0',
                                    'HTTP::Request::Common' => '0',
                                    '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',
                                    'Test::MockTime' => '0',
                                    'Test::More' => '0.92',
-                                   'Test::Script' => '0',
-                                   'Test::TCP' => '1.13',
                                    'YAML' => '0',
                                    'lib' => '0',
                                    'perl' => '5.006',
@@ -171,10 +171,13 @@ my @files = (
     't/issues/gh-639/succeeds/.dancer',
     't/issues/gh-639/succeeds/config.yml',
     't/issues/gh-639/succeeds/issue.t',
+    't/issues/gh-650/gh-650.t',
+    't/issues/gh-650/views/environment_setting.tt',
     't/issues/gh-723.t',
     't/issues/gh-730.t',
     't/issues/gh-794.t',
     't/issues/gh-797.t',
+    't/issues/gh-799.t',
     't/lib/App1.pm',
     't/lib/App2.pm',
     't/lib/DancerPlugin.pm',
@@ -191,7 +194,6 @@ my @files = (
     't/log_levels.t',
     't/logger.t',
     't/logger_console.t',
-    't/lwp-protocol-psgi.t',
     't/memory_cycles.t',
     't/mime.t',
     't/multi_apps.t',
@@ -239,6 +241,14 @@ my @files = (
     't/sessions/VINziwAAUHovk3nfMmkf2GHI6RNrE38c.yml',
     't/sessions/VIOBYgAAZD-3UeYHGxJmpPkpI8hOgUvW.yml',
     't/sessions/VISIVwAASGBJcMXNsII2nVrChuLAP7pm.yml',
+    't/sessions/VIlt7wAAceLduiKWlnAkCQpsRFe9RwmE.yml',
+    't/sessions/VIltdAAAcGUtpuNeagm8uMqOmg1iO5BG.yml',
+    't/sessions/VIxX-gAAaW6BYt4htdZy0O9_g5J3WdHM.yml',
+    't/sessions/VIxY0wAAan1F1Maz4h8_pCnhMdtstSHX.yml',
+    't/sessions/VIxi3AAAfpilI1rk9Tg_5c29HVaYBclB.yml',
+    't/sessions/VIxiTQAAfYHVHQ5txQKuXTwZ7alch-Gc.yml',
+    't/sessions/VIxj4wAAAakb1qv0OYF9_oA_WrIqImY7.yml',
+    't/sessions/VIxkLgAABBzH8FV-MYjgAOQrJuLhWOkM.yml',
     't/shared_engines.t',
     't/template.t',
     't/template_default_tokens.t',
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 32;
 use Test::Fatal;
 use Scalar::Util 'refaddr';
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Dancer2::Core;
 use Test::More tests => 4;
 
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 5;
 
 use_ok('Dancer2::Core::Factory');
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 12;
 use Test::Fatal;
 
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 9;
 use Test::Fatal;
 use Plack::Test;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 3;
 use Plack::Response;
 use Dancer2::Core::Response;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 4;
 
 {
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 3;
 
 {
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use File::Spec;
 use File::Basename;
 use Test::More tests => 11;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 6;
 
 {
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 5;
 use Test::Fatal;
 
@@ -83,7 +80,7 @@ subtest 'Unsuccessful' => sub {
 
         my $msg = $errors->[0];
         isa_ok( $msg, 'HASH' );
-        is( scalar keys %{$msg}, 2, 'Two items in the error' );
+        is( scalar keys %{$msg}, 3, 'Two items in the error' );
 
         is( $msg->{'level'}, 'core', 'Correct level' );
         like(
@@ -113,7 +110,7 @@ subtest 'Unsuccessful' => sub {
 
         my $msg = $errors->[0];
         isa_ok( $msg, 'HASH' );
-        is( scalar keys %{$msg}, 2, 'Two items in the error' );
+        is( scalar keys %{$msg}, 3, 'Two items in the error' );
 
         is( $msg->{'level'}, 'core', 'Correct level' );
         like(
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 24;
 
 {
@@ -1,7 +1,5 @@
-#!/usr/bin/perl
 use strict;
 use warnings;
-
 use Test::More;
 use Test::Fatal;
 use Dancer2::Core::Route;
@@ -2,7 +2,6 @@ use strict;
 use warnings;
 use Test::More;
 use Test::Fatal;
-
 use Dancer2::Core::Request;
 use Dancer2::Core::Route;
 
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 6;
 use Dancer2::Core::Runner;
 
@@ -1,9 +1,6 @@
-#!perl
-
 use strict;
 use warnings;
-
-use Test::More tests => 41;
+use Test::More tests => 39;
 
 use_ok('Dancer2::Core::Runner');
 
@@ -146,26 +143,6 @@ note '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;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 25;
 use Plack::Test;
 use HTTP::Request::Common;
@@ -196,6 +196,7 @@ note 'Check serialization errors'; {
         is( scalar @{$errors}, 1, 'One error caught' );
 
         my $msg = $errors->[0];
+        delete $msg->{'formatted'};
         isa_ok( $msg, 'HASH' );
         is( scalar keys %{$msg}, 2, 'Two items in the error' );
 
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 use Test::More tests => 9;
@@ -1,5 +1,3 @@
-#!/usr/bin/env perl
-
 # define a sample DSL extension that will be used in the rest of these test
 # This extends Dancer2::Core::DSL but provides an extra keyword
 #
@@ -1,6 +1,5 @@
 use strict;
 use warnings;
-
 use Test::More;
 use Plack::Test;
 use HTTP::Request::Common;
@@ -1,6 +1,5 @@
 use strict;
 use warnings;
-
 use Test::More;
 use Plack::Test;
 use HTTP::Request::Common;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 4;
 use Plack::Test;
 use Plack::Request;
@@ -1,4 +1,3 @@
-#!perl
 use strict;
 use warnings;
 use Plack::Test;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 2;
 use Plack::Test;
 use HTTP::Request::Common;
@@ -1,6 +1,5 @@
 use strict;
 use warnings;
-
 use Test::More tests=> 3;
 use File::Temp qw/tempdir/;
 use File::Spec;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 1;
 use Test::Fatal;
 
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 1;
 use Test::Fatal;
 
@@ -0,0 +1,42 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{
+    package MyApp;
+
+    use Dancer2;
+
+    set template => 'template_toolkit';
+
+    get '/foo' => sub {
+        template 'environment_setting'
+    };
+    get '/bar' => sub {
+        set environment => 'development';
+        template 'environment_setting'
+    };
+}
+
+my $app = Dancer2->psgi_app;
+is( ref $app, 'CODE', 'Got app' );
+
+test_psgi $app, sub {
+    my $cb = shift;
+    my $res;
+
+    $res = $cb->(GET '/foo');
+    is $res->code, 200, 'Successful request';
+    like $res->content, qr/development/, 'Correct content';
+
+    $res = $cb->(GET '/bar');
+    is $res->code, 200, 'Successful request';
+    like $res->content, qr/development/, 'Correct content';
+};
+
+done_testing();
@@ -0,0 +1 @@
+[% settings.environment %]
@@ -1,5 +1,3 @@
-#!perl
-
 use strict;
 use warnings;
 use Test::More tests => 4;
@@ -1,8 +1,5 @@
-#!perl
-
 use strict;
 use warnings;
-
 use Test::More tests => 3;
 use Plack::Test;
 use HTTP::Request::Common;
@@ -0,0 +1,64 @@
+use strict;
+use warnings;
+use Test::More tests => 1;
+use Test::Fatal;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{
+    package App;
+    use Dancer2;
+
+    set log     => 'core';
+    set engines => {
+        logger => { Capture => { log_format => '%{x-test}h %i' } },
+    };
+
+    set logger => 'Capture';
+
+    get '/' => sub {
+        my $req = app->request;
+        ::isa_ok( $req, 'Dancer2::Core::Request' );
+
+        my $logger = app->engine('logger');
+        ::isa_ok( $logger, 'Dancer2::Logger::Capture' );
+        ::can_ok( $logger, 'format_message' );
+
+        my $trap = $logger->trapper;
+        ::isa_ok( $trap, 'Dancer2::Logger::Capture::Trap' );
+        my $msg = $trap->read;
+        ::is_deeply(
+            $msg,
+            [
+                {
+                    level     => 'core',
+                    message   => 'looking for get /',
+                    formatted => "- 1\n",
+                },
+
+                {
+                    level     => 'core',
+                    message   => 'Entering hook core.app.before_request',
+                    formatted => "- 1\n",
+                },
+            ],
+            'Messages logged successfully',
+        );
+
+        ::can_ok( $logger, 'format_message' );
+        my $fmt_str = $logger->format_message(
+            $msg->[0]{'debug'}, $msg->[0]{'message'}
+        );
+
+        ::is( $fmt_str, "- 1\n", 'Correct formatted message created' );
+
+        return;
+    };
+}
+
+my $test = Plack::Test->create( App->to_app );
+
+subtest 'Logger can access request' => sub {
+    my $res = $test->request( GET '/' );
+    ok( $res->is_success, 'Successful request' );
+};
@@ -1,6 +1,5 @@
 package t::lib::PluginWithImport;
-
-#ABSTRACT: a plugin that implement its own import method
+# ABSTRACT: a plugin that implement its own import method
 
 =head1 DESCRIPTION
 
@@ -44,9 +44,19 @@ subtest 'log level and capture' => sub {
     debug "I like pie.";
 
     my $trap = dancer_app->engine('logger')->trapper;
-    is_deeply $trap->read,
-      [ { level => "warning", message => "Danger!  Warning!" },
-        { level => "info",    message => "Tango, Foxtrot" },
+    my $msg  = $trap->read;
+    delete $msg->[0]{'formatted'};
+    delete $msg->[1]{'formatted'};
+    is_deeply $msg,
+      [
+        {
+            level => "warning",
+            message => "Danger!  Warning!",
+        },
+        {
+            level => "info",
+            message => "Tango, Foxtrot",
+        },
       ];
 
     # each call to read cleans the trap
@@ -1,35 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use Test::More;
-use LWP::UserAgent;
-
-eval "use LWP::Protocol::PSGI";
-plan skip_all => "LWP::Protocol::PSGI is needed for this test" if $@;
-
-plan tests => 5;
-
-my $psgi_app = do {
-    use Dancer2;
-
-    set apphandler => 'PSGI';
-
-    get '/search' => sub {
-        my $q = param('q');
-        is( $q, 'foo', 'Correct parameter to Google' );
-        return 'bar';
-    };
-
-    dance;
-};
-
-# Register the $psgi_app to handle all LWP requests
-LWP::Protocol::PSGI->register($psgi_app);
-my $ua  = LWP::UserAgent->new;
-isa_ok( $ua, 'LWP::UserAgent' );
-
-my $res = $ua->get("http://www.google.com/search?q=foo");
-isa_ok( $res, 'HTTP::Response' );
-
-ok( $res->is_success, 'Request is successful' );
-is( $res->content, 'bar', 'Correct response content' );
@@ -1,120 +1,86 @@
 use strict;
 use warnings;
 use Test::More;
+use Plack::Test;
+use HTTP::Cookies;
+use HTTP::Request::Common;
+
+{
+    package App;
+    use Dancer2;
+
+    setting(
+        engines => {
+            session => {
+                Simple => {
+                    cookie_name     => 'dancer.sid',
+                    cookie_path     => '/foo',
+                    cookie_duration => '1 hour',
+                    is_http_only    => 0, # will not show up in cookie
+                },
+            },
+        }
+    );
 
-use YAML;
-use Test::TCP 1.13;
-use File::Temp 0.22;
-use LWP::UserAgent;
-use HTTP::Date qw/str2time/;
-use File::Spec;
-
-sub extract_cookie {
-    my ($res) = @_;
-    my @cookies = $res->header('set-cookie');
-    for my $c (@cookies) {
-        next unless $c =~ /dancer\.sid/;    # custom
-        my @parts = split /;\s+/, $c;
-        my %hash =
-          map { my ( $k, $v ) = split /\s*=\s*/; $v ||= 1; ( lc($k), $v ) }
-          @parts;
-        $hash{expires} = str2time( $hash{expires} )
-          if $hash{expires};
-        return \%hash;
-    }
-    return;
-}
+    setting( session => 'Simple' );
 
-my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
-
-for my $session_expires ( 3600, '1h', '1 hour' ) {
-    Test::TCP::test_tcp(
-        client => sub {
-            my $port = shift;
-
-            my $ua = LWP::UserAgent->new;
-            $ua->cookie_jar( { file => "$tempdir/.cookies.txt" } );
-
-            my ( $res, $cookie );
-
-            # set value into session
-            $res = $ua->get("http://127.0.0.1:$port/foo/set_session/larry");
-            ok $res->is_success, "/foo/set_session/larry";
-            $cookie = extract_cookie($res);
-            my $err;
-            ok $cookie, "session cookie set"
-              or $err++;
-            ok $cookie->{expires} - time > 3540,
-              "cookie expiration is in future"
-              or $err++;
-            is $cookie->{domain}, '127.0.0.1', "cookie domain set"
-              or $err++;
-            is $cookie->{path}, '/foo', "cookie path set"
-              or $err++;
-            is $cookie->{httponly}, undef, "cookie has not set HttpOnly";
-            diag explain $cookie
-              if $err;
-
-            # read value back
-            $res = $ua->get("http://127.0.0.1:$port/foo/read_session");
-            ok $res->is_success, "/foo/read_session";
-            like $res->content, qr/name='larry'/, "session value looks good";
-
-            File::Temp::cleanup();
-        },
-        server => sub {
-            my $port = shift;
-
-            use Dancer2;
-
-            get '/has_session' => sub {
-                return app->has_session;
-            };
-
-            get '/foo/set_session/*' => sub {
-                my ($name) = splat;
-                session name => $name;
-            };
-
-            get '/foo/read_session' => sub {
-                my $name = session('name') || '';
-                "name='$name'";
-            };
-
-            get '/foo/destroy_session' => sub {
-                my $name = session('name') || '';
-                app->destroy_session;
-                return "destroyed='$name'";
-            };
-
-            setting appdir => $tempdir;
-            setting(
-                engines => {
-                    session => {
-                        Simple => {
-                            cookie_name     => 'dancer.sid',
-                            cookie_domain   => '127.0.0.1',
-                            cookie_path     => '/foo',
-                            cookie_duration => $session_expires,
-##                    is_secure => 0, # can't easily test without https test server
-                            is_http_only => 0,    # will not show up in cookie
-                        },
-                    },
-                }
-            );
-            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;
-        },
-    );
+    get '/has_session' => sub {
+        return app->has_session;
+    };
+
+    get '/foo/set_session/*' => sub {
+        my ($name) = splat;
+        session name => $name;
+    };
+
+    get '/foo/read_session' => sub {
+        my $name = session('name') || '';
+        "name='$name'";
+    };
 
+    get '/foo/destroy_session' => sub {
+        my $name = session('name') || '';
+        app->destroy_session;
+        return "destroyed='$name'";
+    };
 }
+
+my $test = Plack::Test->create( App->to_app );
+my $url  = 'http://localhost';
+
+my $jar = HTTP::Cookies->new;
+
+subtest 'Set session' => sub {
+    my $res = $test->request( GET "$url/foo/set_session/larry" );
+    ok( $res->is_success, '/foo/set_session/larry' );
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, 'session cookie set' );
+
+    my ( $expires, $domain, $path, $opts );
+    my $cookie = $jar->scan( sub {
+        ( $expires, $domain, $path, $opts ) = @_[ 8, 4, 3 ];
+    } );
+
+    my $httponly = $opts->{'HttpOnly'};
+
+    ok $expires - time > 3540,
+      "cookie expiration is in future";
+
+    is $domain, 'localhost.local', "cookie domain set";
+    is $path, '/foo', "cookie path set";
+    is $httponly, undef, "cookie has not set HttpOnly";
+
+    # read value back
+};
+
+subtest 'Read session' => sub {
+    my $req = GET "$url/foo/read_session";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    ok $res->is_success, "/foo/read_session";
+    like $res->content, qr/name='larry'/, "session value looks good";
+};
+
 done_testing;
@@ -1,109 +1,96 @@
 use strict;
 use warnings;
 use Test::More;
-
 use YAML;
-use Test::TCP 1.13;
-use File::Temp 0.22;
-use LWP::UserAgent;
-use File::Spec;
-
-my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
+use Plack::Test;
+use HTTP::Cookies;
+use HTTP::Request::Common;
 
 my @clients = qw(one two three);
-my @engines = qw(YAML Simple);
 my $SESSION_DIR;
 
-if ( $ENV{DANCER_TEST_COOKIE} ) {
-    push @engines, "cookie";
-    setting( session_cookie_key => "secret/foo*@!" );
+{
+    package App;
+    use Dancer2;
+    my @to_destroy;
+
+    hook 'engine.session.before_destroy' => sub {
+        my $session = shift;
+        push @to_destroy, $session;
+    };
+
+    get '/set_session/*' => sub {
+        my ($name) = splat;
+        session name => $name;
+    };
+
+    get '/read_session' => sub {
+        my $name = session('name') || '';
+        "name='$name'";
+    };
+
+    get '/clear_session' => sub {
+        session name => undef;
+        return exists( session->data->{'name'} ) ? "failed" : "cleared";
+    };
+
+    get '/cleanup' => sub {
+        app->destroy_session;
+        return scalar(@to_destroy);
+    };
+
+    setting session => 'Simple';
+
+    set(
+        show_errors  => 1,
+        environment  => 'production',
+    );
 }
 
-foreach my $engine (@engines) {
-
-
-    note "Testing engine $engine";
-    Test::TCP::test_tcp(
-        client => sub {
-            my $port = shift;
-
-            foreach my $client (@clients) {
-                my $ua = LWP::UserAgent->new;
-                $ua->cookie_jar( { file => "$tempdir/.cookies.txt" } );
-
-                my $res = $ua->get("http://127.0.0.1:$port/read_session");
-                like $res->content, qr/name=''/,
-                  "empty session for client $client";
-
-                $res = $ua->get("http://127.0.0.1:$port/set_session/$client");
-                ok( $res->is_success, "set_session for client $client" );
-
-                $res = $ua->get("http://127.0.0.1:$port/read_session");
-                like $res->content, qr/name='$client'/,
-                  "session looks good for client $client";
-
-                $res = $ua->get("http://127.0.0.1:$port/clear_session");
-                like $res->content, qr/cleared/, "deleted session key";
-
-                $res = $ua->get("http://127.0.0.1:$port/cleanup");
-                ok( $res->is_success, "cleanup done for $client" );
-
-                ok( $res->content, "session hook triggered" );
-
-            }
-
-            File::Temp::cleanup();
-        },
-        server => sub {
-            my $port = shift;
-
-            use Dancer2;
-
-            my @to_destroy;
-
-            hook 'engine.session.before_destroy' => sub {
-                my $session = shift;
-                push @to_destroy, $session;
-            };
-
-            get '/set_session/*' => sub {
-                my ($name) = splat;
-                session name => $name;
-            };
-
-            get '/read_session' => sub {
-                my $name = session('name') || '';
-                "name='$name'";
-            };
-
-            get '/clear_session' => sub {
-                session name => undef;
-                return exists( session->data->{name} ) ? "failed" : "cleared";
-            };
-
-            get '/cleanup' => sub {
-                app->destroy_session;
-                return scalar(@to_destroy);
-            };
-
-            setting appdir => $tempdir;
-            setting(
-                engines => {
-                    session => { $engine => { session_dir => 't/sessions' } }
-                }
-            );
-            setting( session => $engine );
-
-            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;
-        },
-    );
+my $test = Plack::Test->create( App->to_app );
+my $url  = "http://localhost";
+
+foreach my $client (@clients) {
+    my $jar = HTTP::Cookies->new;
+
+    subtest "[$client] Empty session" => sub {
+        my $res = $test->request( GET "$url/read_session" );
+        like $res->content, qr/name=''/,
+          "empty session for client $client";
+        $jar->extract_cookies($res);
+    };
+
+    subtest "[$client] set_session" => sub {
+        my $req = GET "$url/set_session/$client";
+        $jar->add_cookie_header($req);
+        my $res = $test->request($req);
+        ok( $res->is_success, "set_session for client $client" );
+        $jar->extract_cookies($res);
+    };
+
+    subtest "[$client] session for client" => sub {
+        my $req = GET "$url/read_session";
+        $jar->add_cookie_header($req);
+        my $res = $test->request($req);
+        like $res->content, qr/name='$client'/,
+          "session looks good for client $client";
+        $jar->extract_cookies($res);
+    };
+
+    subtest "[$client] delete session" => sub {
+        my $req = GET "$url/clear_session";
+        $jar->add_cookie_header($req);
+        my $res = $test->request($req);
+        like $res->content, qr/cleared/, "deleted session key";
+    };
+
+    subtest "[$client] cleanup" => sub {
+        my $req = GET "$url/cleanup";
+        $jar->add_cookie_header($req);
+        my $res = $test->request($req);
+        ok( $res->is_success, "cleanup done for $client" );
+        ok( $res->content, "session hook triggered" );
+    };
 }
+
 done_testing;
@@ -1,12 +1,9 @@
-use Test::More;
 use strict;
 use warnings;
-use LWP::UserAgent;
-use LWP::Protocol::PSGI;
-
-use File::Temp;
-
-my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
+use Test::More;
+use Plack::Test;
+use HTTP::Cookies;
+use HTTP::Request::Common;
 
 {
     package Test::Forward::Single;
@@ -77,82 +74,99 @@ my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
 }
 
 # base uri for all requests.
-my $base = "http://localhost:3000";
-
-note "Forwards within a single app"; {
-    # Register single app as the handler for all LWP requests.
-    LWP::Protocol::PSGI->register( Test::Forward::Single->to_app );
-    my $ua = LWP::UserAgent->new;
-    my $cookies_store = "$tempdir/.cookies.txt";
-    $ua->cookie_jar( { file => $cookies_store } );
+my $base = 'http://localhost';
+
+subtest 'Forwards within a single app' => sub {
+    my $test = Plack::Test->create( Test::Forward::Single->to_app );
+    my $jar  = HTTP::Cookies->new;
+
+    {
+        my $res = $test->request( GET "$base/main" );
+        is(
+            $res->content,
+            q{Single/main:Single/outer:Single/inner},
+            'session value preserved after chained forwards',
+        );
+
+        $jar->extract_cookies($res);
+    }
+
+    {
+        my $req = GET "$base/inner";
+        $jar->add_cookie_header($req);
+
+        my $res = $test->request($req);
+        is(
+            $res->content,
+            q{Single/main:Single/outer:Single/inner},
+            'session values preserved between calls',
+        );
+
+        $jar->extract_cookies($res);
+    }
+
+    {
+        my $req = GET "$base/clear";
+        $jar->add_cookie_header($req);
+
+        my $res = $test->request( GET "$base/clear" );
+        $jar->extract_cookies($res);
+    }
+
+    {
+        my $req = GET "$base/outer";
+        $jar->add_cookie_header($req);
+
+        my $res = $test->request( GET "$base/outer" );
+        is(
+            $res->content,
+            q{:Single/outer:Single/inner},
+            'session value preserved after forward from route',
+        );
+
+        $jar->extract_cookies($res);
+    }
+};
+
+subtest 'Forwards between multiple apps using the same cookie name' => sub {
+    my $test = Plack::Test->create( Dancer2->psgi_app );
+    my $jar  = HTTP::Cookies->new;
+
+    {
+        my $res = $test->request( GET "$base/same/main" );
+        is(
+            $res->content,
+            q{SameCookieName/main:Single/outer:Single/inner},
+            'session value preserved after chained forwards between apps',
+        );
+
+        $jar->extract_cookies($res);
+    }
+
+    {
+        my $req = GET "$base/outer";
+        $jar->add_cookie_header($req);
+
+        my $res = $test->request($req);
+        is(
+            $res->content,
+            q{SameCookieName/main:Single/outer:Single/inner},
+            'session value preserved after forward from route',
+        );
+    }
+};
+
+subtest 'Forwards between multiple apps using different cookie names' => sub {
+    my $test = Plack::Test->create( Dancer2->psgi_app );
+    my $jar  = HTTP::Cookies->new;
+    my $res  = $test->request( GET "$base/other/main" );
 
-    my $res = $ua->get("$base/main");
-    is(
-        $res->content,
-        q{Single/main:Single/outer:Single/inner},
-        'session value preserved after chained forwards',
-    );
-
-    $res = $ua->get("$base/inner");
-    is(
-        $res->content,
-        q{Single/main:Single/outer:Single/inner},
-        'session values preserved between calls',
-    );
-
-    $res = $ua->get("$base/clear");
-
-    $res = $ua->get("$base/outer");
-    is(
-        $res->content,
-        q{:Single/outer:Single/inner},
-        'session value preserved after forward from route',
-    );
-
-    # cleanup.
-    -e $cookies_store and unlink $cookies_store;
-}
-
-# Register all apps as the handler for all LWP requests.
-LWP::Protocol::PSGI->register( Dancer2->psgi_app );
-note "Forwards between multiple apps using the same cookie name"; {
-    my $ua = LWP::UserAgent->new;
-    my $cookies_store = "$tempdir/.cookies.txt";
-    $ua->cookie_jar( { file => $cookies_store } );
-
-    my $res = $ua->get("$base/same/main");
-    is(
-        $res->content,
-        q{SameCookieName/main:Single/outer:Single/inner},
-        'session value preserved after chained forwards between apps',
-    );
-
-    $res = $ua->get("$base/outer");
-    is(
-        $res->content,
-        q{SameCookieName/main:Single/outer:Single/inner},
-        'session value preserved after forward from route',
-    );
-
-    # cleanup.
-    -e $cookies_store and unlink $cookies_store;
-}
-
-note "Forwards between multiple apps using different cookie names"; {
-    my $ua = LWP::UserAgent->new;
-    my $cookies_store = "$tempdir/.cookies.txt";
-    $ua->cookie_jar( { file => $cookies_store } );
-
-    my $res = $ua->get("$base/other/main");
     is(
         $res->content,
         q{:Single/outer:Single/inner},
         'session value only from forwarded app',
     );
-
-    # cleanup.
-    -e $cookies_store and unlink $cookies_store;
-}
+};
 
 # we need to make sure B doesn't override A when forwarding to C
 # A -> B -> C
@@ -166,20 +180,16 @@ note "Forwards between multiple apps using different cookie names"; {
 # if A -> Single, B -> OtherCookieName, C -> SameCookieName
 # call A, create session, then forward to B, create session,
 # then forward to C, check has values as in A and C
-note "Forwards between multiple apps using multiple different cookie names"; {
-    my $ua = LWP::UserAgent->new;
-    my $cookies_store = "$tempdir/.cookies.txt";
-    $ua->cookie_jar( { file => $cookies_store } );
+subtest 'Forwards between multiple apps using multiple different cookie names' => sub {
+    my $test = Plack::Test->create( Dancer2->psgi_app );
+    my $jar  = HTTP::Cookies->new;
+    my $res  = $test->request( GET "$base/same/bad_chain" );
 
-    my $res = $ua->get("$base/same/bad_chain");
     is(
         $res->content,
         q{SameCookieName/bad_chain:Single/outer:Single/inner},
         'session value only from apps with same session cookie name',
     );
-
-    # cleanup.
-    -e $cookies_store and unlink $cookies_store;
-}
+};
 
 done_testing;
@@ -1,16 +1,9 @@
 use strict;
 use warnings;
 use Test::More;
-
-use File::Temp 0.22;
-use YAML;
-
-use LWP::UserAgent;
-
-eval "use LWP::Protocol::PSGI";
-plan skip_all => "LWP::Protocol::PSGI is needed for this test" if $@;
-
-my @engines = qw(Simple);
+use Plack::Test;
+use HTTP::Cookies;
+use HTTP::Request::Common;
 
 my @hooks_to_test = qw(
   engine.session.before_retrieve
@@ -25,143 +18,137 @@ my @hooks_to_test = qw(
   engine.session.before_flush
   engine.session.after_flush
 );
-#we'll set a flag here when each hook is called. Then our test will then verify this
-my $test_flags = {};
-my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
 
-#I need this to make sure it works with LWP::Protocol::PSGI See GH#447
-BEGIN {
-    $ENV{DANCER_APPHANDLER} = 'PSGI';
-}
+# we'll set a flag here when each hook is called. Then our test will then verify this
+my $test_flags = {};
 
-sub get_app_for_engine {
-    my $engine = shift;
+{
+    package App;
     use Dancer2;
 
-    #Possibly this doesn't seem to have a real effect. See GH#447
-    setting apphandler => 'PSGI';
-    setting appdir => $tempdir;
-    setting(
-            engines => { #we'll need this for YAML sessions
-                session => { engine => {session_dir => 't/sessions'}}
-            }
+    set(
+        show_errors => 1,
+        envoriment  => 'production'
     );
-    set(show_errors  => 1,
-        startup_info => 0,
-        envoriment   => 'production'
-    );
-    setting(session => $engine);
+
+    setting( session => 'Simple' );
 
     for my $hook (@hooks_to_test) {
         hook $hook => sub {
-         $test_flags->{$hook} ||= 0;
-         $test_flags->{$hook}++;
+            $test_flags->{$hook} ||= 0;
+            $test_flags->{$hook}++;
         }
     }
 
     get '/set_session' => sub {
-       session foo => 'bar'; #setting causes a session flush
-       return "ok";
+        session foo => 'bar'; #setting causes a session flush
+        return "ok";
     };
+
     get '/get_session' => sub {
-      is session->read('foo'), 'bar', "Got the right session back";
-      return "ok";
+        ::is session->read('foo'), 'bar', "Got the right session back";
+        return "ok";
     };
+
     get '/destroy_session' => sub {
-      app->destroy_session;
-      return "ok";
+        app->destroy_session;
+        return "ok";
     };
 
     #setup each hook again and test whether they return the correct type
     #there is unfortunately quite some duplication here.
     hook 'engine.session.before_create' => sub {
-       my ($response) = @_;
-       is ref($response), 'Dancer2::Core::Session',
-                           'Correct response type returned in before_create';
+        my ($response) = @_;
+        ::isa_ok( $response, 'Dancer2::Core::Session' );
     };
+
     hook 'engine.session.after_create' => sub {
-       my ($response) = @_;
-       is ref($response), 'Dancer2::Core::Session',
-                            'Correct response type returned in after_create';
+        my ($response) = @_;
+        ::isa_ok( $response, 'Dancer2::Core::Session' );
     };
+
     hook 'engine.session.after_retrieve' => sub {
-       my ($response) = @_;
-       is ref($response), 'Dancer2::Core::Session',
-                            'Correct response type returned in after_retrieve';
+        my ($response) = @_;
+        ::isa_ok( $response, 'Dancer2::Core::Session' );
     };
-    #this returns dancer app. We'll register it with LWP::Protocol::PSGI
-    dance;
 }
 
-foreach my $engine (@engines) {
-    note "Testing against $engine engine";
-
-    $test_flags = {};
-
-    #This will hijack lwp requests to localhost:3000 and send them to our dancer app
-    LWP::Protocol::PSGI->register(get_app_for_engine($engine)); #if I set to hijack a particular <host:port> the connection is refused.
-
-    my $ua = LWP::UserAgent->new;
-    $ua->cookie_jar({file => "$tempdir/.cookies.$engine.txt"});
-
-    my $r = $ua->get("http://localhost:3000/set_session");
-    is $r->content, "ok", "set_session ran ok";
-
-    #we verify whether the hooks were called correctly.
-    subtest 'verify hooks for session create and session flush' => sub {
-        is $test_flags->{'engine.session.before_create'}, 1, "session.before_create called";
-        is $test_flags->{'engine.session.after_create'}, 1, "session.after_create called";
-        is $test_flags->{'engine.session.before_flush'}, 1, "session.before_flush called";
-        is $test_flags->{'engine.session.after_flush'}, 1, "session.after_flush 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";
-        is $test_flags->{'engine.session.before_destroy'}, undef, "session.before_destroy not called";
-        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";
-
-    subtest 'verify hooks for session retrieve' => sub {
-        is $test_flags->{'engine.session.before_retrieve'}, 1, "session.before_retrieve called";
-        is $test_flags->{'engine.session.after_retrieve'}, 1, "session.after_retrieve called";
-
-        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_flush'}, 1, "session.before_flush not called";
-        is $test_flags->{'engine.session.after_flush'}, 1, "session.after_flush not called";
-        is $test_flags->{'engine.session.before_destroy'}, undef, "session.before_destroy not called";
-        is $test_flags->{'engine.session.after_destroy'}, undef, "session.after_destroy not called";
-    };
-
-    $r = $ua->get("http://localhost:3000/destroy_session");
-    is $r->content, "ok", "destroy_session ran ok";
-
-    subtest 'verify session destroy hooks' => sub {
-        is $test_flags->{'engine.session.before_destroy'}, 1, "session.before_destroy called";
-        is $test_flags->{'engine.session.after_destroy'}, 1, "session.after_destroy called";
-        #not sure if before and after retrieve should be called when the session is destroyed. But this happens.
-        is $test_flags->{'engine.session.before_retrieve'}, 2, "session.before_retrieve called";
-        is $test_flags->{'engine.session.after_retrieve'}, 2, "session.after_retrieve called";
-
-        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_flush'}, 1, "session.before_flush not called";
-        is $test_flags->{'engine.session.after_flush'}, 1, "session.after_flush not called";
-    };
-
-    File::Temp::cleanup();
-}
+my $test = Plack::Test->create( App->to_app );
+my $jar  = HTTP::Cookies->new;
+my $url  = "http://localhost";
+
+is_deeply( $test_flags, {}, 'Make sure flag hash is clear' );
+
+subtest set_session => sub {
+    my $res = $test->request( GET "$url/set_session" );
+    is $res->content, "ok", "set_session ran ok";
+    $jar->extract_cookies($res);
+};
+
+# we verify whether the hooks were called correctly.
+subtest 'verify hooks for session create and session flush' => sub {
+    is $test_flags->{'engine.session.before_create'}, 1, "session.before_create called";
+    is $test_flags->{'engine.session.after_create'}, 1, "session.after_create called";
+    is $test_flags->{'engine.session.before_flush'}, 1, "session.before_flush called";
+    is $test_flags->{'engine.session.after_flush'}, 1, "session.after_flush 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";
+    is $test_flags->{'engine.session.before_destroy'}, undef, "session.before_destroy not called";
+    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 $req = GET "$url/file.txt";
+    $jar->add_cookie_header($req);
+    my $res = $test->request($req);
+    $jar->extract_cookies($res);
+
+    # 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";
+};
+
+subtest get_session => sub {
+    my $req = GET "$url/get_session";
+    $jar->add_cookie_header($req);
+    my $res = $test->request($req);
+    is $res->content, "ok", "get_session ran ok";
+    $jar->extract_cookies($res);
+};
+
+subtest 'verify hooks for session retrieve' => sub {
+    is $test_flags->{'engine.session.before_retrieve'}, 1, "session.before_retrieve called";
+    is $test_flags->{'engine.session.after_retrieve'}, 1, "session.after_retrieve called";
+
+    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_flush'}, 1, "session.before_flush not called";
+    is $test_flags->{'engine.session.after_flush'}, 1, "session.after_flush not called";
+    is $test_flags->{'engine.session.before_destroy'}, undef, "session.before_destroy not called";
+    is $test_flags->{'engine.session.after_destroy'}, undef, "session.after_destroy not called";
+};
+
+subtest destroy_session => sub {
+    my $req = GET "$url/destroy_session";
+    $jar->add_cookie_header($req);
+    my $res = $test->request($req);
+    is $res->content, "ok", "destroy_session ran ok";
+};
+
+subtest 'verify session destroy hooks' => sub {
+    is $test_flags->{'engine.session.before_destroy'}, 1, "session.before_destroy called";
+    is $test_flags->{'engine.session.after_destroy'}, 1, "session.after_destroy called";
+    #not sure if before and after retrieve should be called when the session is destroyed. But this happens.
+    is $test_flags->{'engine.session.before_retrieve'}, 2, "session.before_retrieve called";
+    is $test_flags->{'engine.session.after_retrieve'}, 2, "session.after_retrieve called";
+
+    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_flush'}, 1, "session.before_flush not called";
+    is $test_flags->{'engine.session.after_flush'}, 1, "session.after_flush not called";
+};
 
 done_testing;
@@ -2,78 +2,78 @@ 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;
+use Plack::Test;
+use HTTP::Request::Common;
+use HTTP::Cookies;
+
+{
+    package TestApp;
+
+    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(
+        engines => {
+            session => { 'Simple' => { session_dir => 't/sessions' } }
+        }
+    );
+    setting( session => 'Simple' );
+}
+
+my $app = TestApp->to_app;
+is( ref $app, 'CODE', 'Got app' );
+
+my $test = Plack::Test->create($app);
+my $jar = HTTP::Cookies->new();
+
+{
+    my $res = $test->request( GET '/' );
+
+    ok $res->is_success, 'Successful request';
+    is $res->content, "session.name \n";
+
+    $jar->extract_cookies($res);
+}
+
+{
+    my $request = GET '/set_session/test_name';
+    $jar->add_cookie_header($request);
+
+    my $res = $test->request($request);
+    ok $res->is_success, 'Successful request';
+    is $res->content, "session.name test_name\n";
+
+    $jar->extract_cookies($res);
+}
+
+{
+    my $request = GET '/destroy_session';
+    $jar->add_cookie_header($request);
+
+    my $res = $test->request($request);
+    ok $res->is_success, 'Successful request';
+    is $res->content, "session.name \n";
+
+    $jar->extract_cookies($res);
+}
+
+done_testing();
@@ -1,180 +1,169 @@
 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;
-
-sub extract_cookie {
-    my ($res) = @_;
-    my @cookies = $res->header('set-cookie');
-    for my $c (@cookies) {
-        next unless $c =~ /dancer\.session/;
-        my @parts = split /;\s+/, $c;
-        my %hash =
-          map { my ( $k, $v ) = split /\s*=\s*/; $v ||= 1; ( lc($k), $v ) }
-          @parts;
-        $hash{expires} = str2time( $hash{expires} )
-          if $hash{expires};
-        return \%hash;
-    }
-    return;
+use Plack::Test;
+use HTTP::Request::Common;
+use HTTP::Cookies;
+
+{
+    package App;
+    use Dancer2;
+
+    set session     => 'Simple';
+    set show_errors => 1;
+
+    get '/no_session_data' => sub {
+        return "session not modified";
+    };
+
+    get '/set_session/*' => sub {
+        my ($name) = splat;
+        session name => $name;
+    };
+
+    get '/read_session' => sub {
+        my $name = session('name') || '';
+        "name='$name'";
+    };
+
+    get '/destroy_session' => sub {
+        my $name = session('name') || '';
+        app->destroy_session;
+        return "destroyed='$name'";
+    };
+
+    get '/churn_session' => sub {
+        app->destroy_session;
+        session name => 'damian';
+        return "churned";
+    };
 }
 
-my $tempdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 );
+my $url  = 'http://localhost';
+my $jar  = HTTP::Cookies->new();
+my $test = Plack::Test->create( App->to_app );
 
-my @engines = qw(YAML Simple);
+subtest 'No cookie set if session not referenced' => sub {
+    my $res = $test->request( GET "$url/no_session_data" );
+    ok $res->is_success, "/no_session_data"
+      or diag explain $res;
 
-if ( $ENV{DANCER_TEST_COOKIE} ) {
-    push @engines, "cookie";
-    setting( session_cookie_key => "secret/foo*@!" );
-}
+    $jar->extract_cookies($res);
+    ok( !$jar->as_string, 'No cookie set' );
+};
+
+subtest 'No empty session created if session read attempted' => sub {
+    my $res = $test->request( GET "$url/read_session" );
+    ok $res->is_success, "/read_session";
+
+    $jar->extract_cookies($res);
+    ok( !$jar->as_string, 'No cookie set' );
+};
+
+my $sid1;
+subtest 'Set value into session' => sub {
+    my $res = $test->request( GET "$url/set_session/larry" );
+    ok $res->is_success, "/set_session/larry";
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, 'Cookie set' );
+
+    # extract SID
+    $jar->scan( sub { $sid1 = $_[2] } );
+    ok( $sid1, 'Got SID from cookie' );
+};
+
+subtest 'Read value back' => sub {
+    # read value back
+    my $req = GET "$url/read_session";
+    $jar->add_cookie_header($req);
+    my $res = $test->request($req);
+    ok $res->is_success, "/read_session";
+
+    $jar->clear;
+    ok( !$jar->as_string, 'Jar cleared' );
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, 'session cookie set again' );
+    like $res->content, qr/name='larry'/, "session value looks good";
+};
+
+subtest 'Session cookie persists even if we do not touch sessions' => sub {
+    my $req = GET "$url/no_session_data";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    ok $res->is_success, "/no_session_data";
+
+    $jar->clear;
+    ok( !$jar->as_string, 'Jar cleared' );
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, 'session cookie set again' );
+};
+
+subtest 'Destroy session and check that cookies expiration is set' => sub {
+    my $req = GET "$url/destroy_session";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    ok $res->is_success, "/destroy_session";
+
+    ok( $jar->as_string, 'We have a cookie before reading response' );
+    $jar->extract_cookies($res);
+    ok( ! $jar->as_string, 'Cookie was removed from jar' );
+};
+
+subtest 'Session cookie not sent after session destruction' => sub {
+    my $req = GET "$url/no_session_data";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    ok $res->is_success, "/no_session_data";
+
+    ok( !$jar->as_string, 'Jar is empty' );
+    $jar->extract_cookies($res);
+    ok( !$jar->as_string, 'Jar still empty (no new session cookie)' );
+};
+
+my $sid2;
+subtest 'Set value into session again' => sub {
+    my $res = $test->request( GET "$url/set_session/curly" );
+    ok $res->is_success, "/set_session/larry";
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, 'session cookie set' );
+
+    # extract SID
+    $jar->scan( sub { $sid2 = $_[2] } );
+    isnt $sid2, $sid1, "New session has different ID";
+};
+
+subtest 'Destroy and create a session in one request' => sub {
+    my $req = GET "$url/churn_session";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    ok $res->is_success, "/churn_session";
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, 'session cookie set' );
+
+    my $sid3;
+    $jar->scan( sub { $sid3 = $_[2] } );
+    isnt $sid3, $sid2, "Changed session has different ID";
+};
+
+subtest 'Read value back' => sub {
+    my $req = GET "$url/read_session";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    ok $res->is_success, "/read_session";
+
+    $jar->extract_cookies($res);
+    ok( $jar->as_string, "session cookie set" );
+    like $res->content, qr/name='damian'/, "session value looks good";
+};
 
-foreach my $engine (@engines) {
-
-    note "Testing engine $engine";
-    Test::TCP::test_tcp(
-        client => sub {
-            my $port = shift;
-
-            my $ua = LWP::UserAgent->new;
-            $ua->cookie_jar( { file => "$tempdir/.cookies.txt" } );
-
-            # no session cookie set if session not referenced
-            my $res = $ua->get("http://127.0.0.1:$port/no_session_data");
-            ok $res->is_success, "/no_session_data"
-              or diag explain $res;
-            my $cookie = extract_cookie($res);
-            ok !$cookie, "no cookie set"
-              or diag explain $cookie;
-
-            # no empty session created if session read attempted
-            $res = $ua->get("http://127.0.0.1:$port/read_session");
-            ok $res->is_success, "/read_session";
-            $cookie = extract_cookie($res);
-            ok !$cookie, "no cookie set"
-              or diag explain $cookie;
-
-            # set value into session
-            $res = $ua->get("http://127.0.0.1:$port/set_session/larry");
-            ok $res->is_success, "/set_session/larry";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-            my $sid1 = $cookie->{"dancer.session"};
-
-            # read value back
-            $res = $ua->get("http://127.0.0.1:$port/read_session");
-            ok $res->is_success, "/read_session";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-            like $res->content, qr/name='larry'/, "session value looks good";
-
-            # session cookie should persist even if we don't touch sessions
-            $res = $ua->get("http://127.0.0.1:$port/no_session_data");
-            ok $res->is_success, "/no_session_data";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-
-            # destroy session and check that cookies expiration is set
-            $res = $ua->get("http://127.0.0.1:$port/destroy_session");
-            ok $res->is_success, "/destroy_session";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-            is $cookie->{"dancer.session"}, $sid1, "correct cookie expired";
-            ok $cookie->{expires} < time, "session cookie is expired";
-
-            # shouldn't be sent session cookie after session destruction
-            $res = $ua->get("http://127.0.0.1:$port/no_session_data");
-            ok $res->is_success, "/no_session_data";
-            $cookie = extract_cookie($res);
-            ok !$cookie, "no cookie set"
-              or diag explain $cookie;
-
-            # set value into session again
-            $res = $ua->get("http://127.0.0.1:$port/set_session/curly");
-            ok $res->is_success, "/set_session/larry";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-            my $sid2 = $cookie->{"dancer.session"};
-            isnt $sid2, $sid1, "New session has different ID";
-
-            # destroy and create a session in one request
-            $res = $ua->get("http://127.0.0.1:$port/churn_session");
-            ok $res->is_success, "/churn_session";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-            my $sid3 = $cookie->{"dancer.session"};
-            isnt $sid3, $sid2, "Changed session has different ID";
-
-            # read value back
-            $res = $ua->get("http://127.0.0.1:$port/read_session");
-            ok $res->is_success, "/read_session";
-            $cookie = extract_cookie($res);
-            ok $cookie, "session cookie set"
-              or diag explain $cookie;
-            like $res->content, qr/name='damian'/, "session value looks good";
-
-            File::Temp::cleanup();
-        },
-        server => sub {
-            my $port = shift;
-
-            use Dancer2;
-
-            get '/no_session_data' => sub {
-                return "session not modified";
-            };
-
-            get '/set_session/*' => sub {
-                my ($name) = splat;
-                session name => $name;
-            };
-
-            get '/read_session' => sub {
-                my $name = session('name') || '';
-                "name='$name'";
-            };
-
-            get '/destroy_session' => sub {
-                my $name = session('name') || '';
-                app->destroy_session;
-                return "destroyed='$name'";
-            };
-
-            get '/churn_session' => sub {
-                app->destroy_session;
-                session name => 'damian';
-                return "churned";
-            };
-
-            setting appdir => $tempdir;
-            setting(
-                engines => {
-                    session => { $engine => { session_dir => 't/sessions' } }
-                }
-            );
-            setting( session => $engine );
-
-            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
@@ -1,54 +1,50 @@
 use strict;
 use warnings;
-
-use File::Spec;
-use File::Temp 0.22;
-use LWP::UserAgent;
 use Test::More;
-use Test::TCP 1.13;
-use YAML;
-
-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/main");
-        like $res->content, qr{42}, "session is set in main";
-
-        $res = $ua->get("http://127.0.0.1:$port/in_foo");
-        like $res->content, qr{42}, "session is set in foo";
-
-        my $engine = t::lib::Foo->dsl->engine('session');
-        is $engine->{__marker__}, 1,
-          "the session engine in subapp is the same";
-
-        File::Temp::cleanup();
-    },
-    server => sub {
-        my $port = shift;
-
-        BEGIN {
-            use Dancer2;
-            set session => 'Simple';
-            engine('session')->{'__marker__'} = 1;
-        }
-
-        use t::lib::Foo with => { session => engine('session') };
-
-        get '/main' => sub {
-            session( 'test' => 42 );
-        };
-
-        setting appdir => $tempdir;
-        # we're overiding a RO attribute only for this test!
-        Dancer2->runner->{'port'} = $port;
-        start;
-    },
-);
+use Plack::Test;
+use HTTP::Cookies;
+use HTTP::Request::Common;
+
+{
+    package App;
+
+    # call stuff before next use() statement
+    BEGIN {
+        use Dancer2;
+        set session => 'Simple';
+        engine('session')->{'__marker__'} = 1;
+    }
+
+    use t::lib::Foo with => { session => engine('session') };
+
+    get '/main' => sub {
+        session( 'test' => 42 );
+    };
+}
+
+my $jar = HTTP::Cookies->new;
+my $url = 'http://localhost';
+
+{
+    my $test = Plack::Test->create( App->to_app );
+    my $res  = $test->request( GET "$url/main" );
+    like $res->content, qr{42}, "session is set in main";
+    $jar->extract_cookies($res);
+
+    ok( $jar->as_string, 'Got cookie' );
+}
+
+{
+    my $test = Plack::Test->create( t::lib::Foo->to_app );
+    my $req  = GET "$url/in_foo";
+    $jar->add_cookie_header($req);
+
+    my $res = $test->request($req);
+    like $res->content, qr{42}, "session is set in foo";
+}
+
+my $engine = t::lib::Foo->dsl->engine('session');
+is $engine->{__marker__}, 1,
+  "the session engine in subapp is the same";
 
 done_testing;