summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgregor herrmann <gregoa@debian.org>2023-12-15 22:18:44 +0100
committergregor herrmann <gregoa@debian.org>2023-12-15 22:18:44 +0100
commit135085ecb17d937720d07ee0a48be9bc09a762f8 (patch)
treeccdaa24298e86de49543f382fda0257834b02248
parentc0077477aeae4eb2fb72717c540bc1d4b6dde385 (diff)
parent62ade3e319199604546971f641cc34b82a279a36 (diff)
Update upstream source from tag 'upstream/1.1.0+dfsg'
Update to upstream version '1.1.0+dfsg' with Debian dir a6a8790bab9264a1f5f2c48bcb3604d09c94d48a
-rw-r--r--Changes17
-rw-r--r--MANIFEST6
-rw-r--r--META.json122
-rw-r--r--META.yml120
-rw-r--r--Makefile.PL4
-rw-r--r--lib/Dancer2.pm4
-rw-r--r--lib/Dancer2/CLI.pm4
-rw-r--r--lib/Dancer2/CLI/Gen.pm4
-rw-r--r--lib/Dancer2/CLI/Version.pm4
-rw-r--r--lib/Dancer2/Config.pod2
-rw-r--r--lib/Dancer2/Cookbook.pod2
-rw-r--r--lib/Dancer2/Core.pm4
-rw-r--r--lib/Dancer2/Core/App.pm82
-rw-r--r--lib/Dancer2/Core/Cookie.pm4
-rw-r--r--lib/Dancer2/Core/DSL.pm34
-rw-r--r--lib/Dancer2/Core/Dispatcher.pm4
-rw-r--r--lib/Dancer2/Core/Error.pm4
-rw-r--r--lib/Dancer2/Core/Factory.pm4
-rw-r--r--lib/Dancer2/Core/HTTP.pm4
-rw-r--r--lib/Dancer2/Core/Hook.pm4
-rw-r--r--lib/Dancer2/Core/MIME.pm4
-rw-r--r--lib/Dancer2/Core/Request.pm23
-rw-r--r--lib/Dancer2/Core/Request/Upload.pm4
-rw-r--r--lib/Dancer2/Core/Response.pm4
-rw-r--r--lib/Dancer2/Core/Response/Delayed.pm4
-rw-r--r--lib/Dancer2/Core/Role/ConfigReader.pm4
-rw-r--r--lib/Dancer2/Core/Role/DSL.pm4
-rw-r--r--lib/Dancer2/Core/Role/Engine.pm4
-rw-r--r--lib/Dancer2/Core/Role/Handler.pm4
-rw-r--r--lib/Dancer2/Core/Role/HasLocation.pm4
-rw-r--r--lib/Dancer2/Core/Role/Hookable.pm4
-rw-r--r--lib/Dancer2/Core/Role/Logger.pm4
-rw-r--r--lib/Dancer2/Core/Role/Serializer.pm4
-rw-r--r--lib/Dancer2/Core/Role/SessionFactory.pm4
-rw-r--r--lib/Dancer2/Core/Role/SessionFactory/File.pm4
-rw-r--r--lib/Dancer2/Core/Role/StandardResponses.pm4
-rw-r--r--lib/Dancer2/Core/Role/Template.pm4
-rw-r--r--lib/Dancer2/Core/Route.pm10
-rw-r--r--lib/Dancer2/Core/Runner.pm4
-rw-r--r--lib/Dancer2/Core/Session.pm4
-rw-r--r--lib/Dancer2/Core/Time.pm4
-rw-r--r--lib/Dancer2/Core/Types.pm4
-rw-r--r--lib/Dancer2/DeprecationPolicy.pod2
-rw-r--r--lib/Dancer2/FileUtils.pm4
-rw-r--r--lib/Dancer2/Handler/AutoPage.pm4
-rw-r--r--lib/Dancer2/Handler/File.pm4
-rw-r--r--lib/Dancer2/Logger/Capture.pm4
-rw-r--r--lib/Dancer2/Logger/Capture/Trap.pm4
-rw-r--r--lib/Dancer2/Logger/Console.pm4
-rw-r--r--lib/Dancer2/Logger/Diag.pm4
-rw-r--r--lib/Dancer2/Logger/File.pm4
-rw-r--r--lib/Dancer2/Logger/Note.pm4
-rw-r--r--lib/Dancer2/Logger/Null.pm4
-rw-r--r--lib/Dancer2/Manual.pod8
-rw-r--r--lib/Dancer2/Manual/Deployment.pod2
-rw-r--r--lib/Dancer2/Manual/Keywords.pod159
-rw-r--r--lib/Dancer2/Manual/Migration.pod2
-rw-r--r--lib/Dancer2/Manual/Testing.pod2
-rw-r--r--lib/Dancer2/Plugin.pm4
-rw-r--r--lib/Dancer2/Plugins.pod2
-rw-r--r--lib/Dancer2/Policy.pod2
-rw-r--r--lib/Dancer2/Serializer/Dumper.pm4
-rw-r--r--lib/Dancer2/Serializer/JSON.pm4
-rw-r--r--lib/Dancer2/Serializer/Mutable.pm4
-rw-r--r--lib/Dancer2/Serializer/YAML.pm4
-rw-r--r--lib/Dancer2/Session/Simple.pm4
-rw-r--r--lib/Dancer2/Session/YAML.pm4
-rw-r--r--lib/Dancer2/Template/Implementation/ForkedTiny.pm4
-rw-r--r--lib/Dancer2/Template/Simple.pm4
-rw-r--r--lib/Dancer2/Template/TemplateToolkit.pm4
-rw-r--r--lib/Dancer2/Template/Tiny.pm4
-rw-r--r--lib/Dancer2/Test.pm4
-rw-r--r--lib/Dancer2/Tutorial.pod2
-rwxr-xr-xscript/dancer22
-rw-r--r--t/author-no-tabs.t4
-rw-r--r--t/dsl/uri_for.t48
-rw-r--r--t/dsl/uri_for_route.t246
-rw-r--r--t/named_routes.t90
-rw-r--r--t/uri_for.t30
79 files changed, 943 insertions, 292 deletions
diff --git a/Changes b/Changes
index 41d1b54d..bdd1c4f8 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,20 @@
+1.1.0 2023-12-11 20:28:26-05:00 America/New_York
+
+ [ BUG FIXES ]
+ * None
+
+ [ ENHANCEMENTS ]
+ * GH #33: Named routes; add uri_for_route keyword (Sawyer X)
+
+ [ DOCUMENTATION ]
+ * None
+
+ [ DEPRECATED ]
+ * None
+
+ [ MISC ]
+ * None
+
1.0.0 2023-10-09 10:10:10-04:00 America/New_York
[ BUG FIXES ]
diff --git a/MANIFEST b/MANIFEST
index 2cbbf80f..b0360d8b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,4 +1,4 @@
-# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.030.
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.031.
AUTHORS
Changes
Contributing.md
@@ -201,6 +201,8 @@ t/dsl/send_as.t
t/dsl/send_file.t
t/dsl/splat.t
t/dsl/to_app.t
+t/dsl/uri_for.t
+t/dsl/uri_for_route.t
t/dsl/yaml.t
t/engine.t
t/error.t
@@ -301,6 +303,7 @@ t/multi_apps_forward.t
t/multiapp_template_hooks.t
t/multipart_content.t
t/named_apps.t
+t/named_routes.t
t/no_default_middleware.t
t/plugin2/app_dsl_cb/app_dsl_cb.t
t/plugin2/app_dsl_cb/lib/App.pm
@@ -395,7 +398,6 @@ t/template_tiny/samples/09_trim.txt
t/template_tiny/samples/09_trim.var
t/time.t
t/types.t
-t/uri_for.t
t/vars.t
t/views/auto_page.tt
t/views/beforetemplate.tt
diff --git a/META.json b/META.json
index d4001620..e7584bf6 100644
--- a/META.json
+++ b/META.json
@@ -4,7 +4,7 @@
"Dancer Core Developers"
],
"dynamic_config" : 1,
- "generated_by" : "Dist::Zilla version 6.030, CPAN::Meta::Converter version 2.150010",
+ "generated_by" : "Dist::Zilla version 6.031, CPAN::Meta::Converter version 2.150010",
"license" : [
"perl_5"
],
@@ -140,231 +140,231 @@
"provides" : {
"Dancer2" : {
"file" : "lib/Dancer2.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::CLI" : {
"file" : "lib/Dancer2/CLI.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::CLI::Gen" : {
"file" : "lib/Dancer2/CLI/Gen.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::CLI::Version" : {
"file" : "lib/Dancer2/CLI/Version.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core" : {
"file" : "lib/Dancer2/Core.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::App" : {
"file" : "lib/Dancer2/Core/App.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Cookie" : {
"file" : "lib/Dancer2/Core/Cookie.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::DSL" : {
"file" : "lib/Dancer2/Core/DSL.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Dispatcher" : {
"file" : "lib/Dancer2/Core/Dispatcher.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Error" : {
"file" : "lib/Dancer2/Core/Error.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Factory" : {
"file" : "lib/Dancer2/Core/Factory.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::HTTP" : {
"file" : "lib/Dancer2/Core/HTTP.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Hook" : {
"file" : "lib/Dancer2/Core/Hook.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::MIME" : {
"file" : "lib/Dancer2/Core/MIME.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Request" : {
"file" : "lib/Dancer2/Core/Request.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Request::Upload" : {
"file" : "lib/Dancer2/Core/Request/Upload.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Response" : {
"file" : "lib/Dancer2/Core/Response.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Response::Delayed" : {
"file" : "lib/Dancer2/Core/Response/Delayed.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::ConfigReader" : {
"file" : "lib/Dancer2/Core/Role/ConfigReader.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::DSL" : {
"file" : "lib/Dancer2/Core/Role/DSL.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::Engine" : {
"file" : "lib/Dancer2/Core/Role/Engine.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::Handler" : {
"file" : "lib/Dancer2/Core/Role/Handler.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::HasLocation" : {
"file" : "lib/Dancer2/Core/Role/HasLocation.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::Hookable" : {
"file" : "lib/Dancer2/Core/Role/Hookable.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::Logger" : {
"file" : "lib/Dancer2/Core/Role/Logger.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::Serializer" : {
"file" : "lib/Dancer2/Core/Role/Serializer.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::SessionFactory" : {
"file" : "lib/Dancer2/Core/Role/SessionFactory.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::SessionFactory::File" : {
"file" : "lib/Dancer2/Core/Role/SessionFactory/File.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::StandardResponses" : {
"file" : "lib/Dancer2/Core/Role/StandardResponses.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Role::Template" : {
"file" : "lib/Dancer2/Core/Role/Template.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Route" : {
"file" : "lib/Dancer2/Core/Route.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Runner" : {
"file" : "lib/Dancer2/Core/Runner.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Session" : {
"file" : "lib/Dancer2/Core/Session.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Time" : {
"file" : "lib/Dancer2/Core/Time.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Core::Types" : {
"file" : "lib/Dancer2/Core/Types.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::FileUtils" : {
"file" : "lib/Dancer2/FileUtils.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Handler::AutoPage" : {
"file" : "lib/Dancer2/Handler/AutoPage.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Handler::File" : {
"file" : "lib/Dancer2/Handler/File.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::Capture" : {
"file" : "lib/Dancer2/Logger/Capture.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::Capture::Trap" : {
"file" : "lib/Dancer2/Logger/Capture/Trap.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::Console" : {
"file" : "lib/Dancer2/Logger/Console.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::Diag" : {
"file" : "lib/Dancer2/Logger/Diag.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::File" : {
"file" : "lib/Dancer2/Logger/File.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::Note" : {
"file" : "lib/Dancer2/Logger/Note.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Logger::Null" : {
"file" : "lib/Dancer2/Logger/Null.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Plugin" : {
"file" : "lib/Dancer2/Plugin.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Serializer::Dumper" : {
"file" : "lib/Dancer2/Serializer/Dumper.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Serializer::JSON" : {
"file" : "lib/Dancer2/Serializer/JSON.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Serializer::Mutable" : {
"file" : "lib/Dancer2/Serializer/Mutable.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Serializer::YAML" : {
"file" : "lib/Dancer2/Serializer/YAML.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Session::Simple" : {
"file" : "lib/Dancer2/Session/Simple.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Session::YAML" : {
"file" : "lib/Dancer2/Session/YAML.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Template::Implementation::ForkedTiny" : {
"file" : "lib/Dancer2/Template/Implementation/ForkedTiny.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Template::Simple" : {
"file" : "lib/Dancer2/Template/Simple.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Template::TemplateToolkit" : {
"file" : "lib/Dancer2/Template/TemplateToolkit.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Template::Tiny" : {
"file" : "lib/Dancer2/Template/Tiny.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
},
"Dancer2::Test" : {
"file" : "lib/Dancer2/Test.pm",
- "version" : "v1.0.0"
+ "version" : "v1.1.0"
}
},
"release_status" : "stable",
@@ -381,9 +381,9 @@
"x_IRC" : "irc://irc.perl.org/#dancer",
"x_WebIRC" : "https://chat.mibbit.com/#dancer@irc.perl.org"
},
- "version" : "1.0.0",
- "x_generated_by_perl" : "v5.36.1",
- "x_serialization_backend" : "Cpanel::JSON::XS version 4.36",
+ "version" : "1.1.0",
+ "x_generated_by_perl" : "v5.38.1",
+ "x_serialization_backend" : "Cpanel::JSON::XS version 4.37",
"x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later"
}
diff --git a/META.yml b/META.yml
index 2191ab8b..b531ab4d 100644
--- a/META.yml
+++ b/META.yml
@@ -25,7 +25,7 @@ conflicts:
Role::Tiny: '== 2.000007'
YAML: '== 1.16'
dynamic_config: 1
-generated_by: 'Dist::Zilla version 6.030, CPAN::Meta::Converter version 2.150010'
+generated_by: 'Dist::Zilla version 6.031, CPAN::Meta::Converter version 2.150010'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -34,175 +34,175 @@ name: Dancer2
provides:
Dancer2:
file: lib/Dancer2.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::CLI:
file: lib/Dancer2/CLI.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::CLI::Gen:
file: lib/Dancer2/CLI/Gen.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::CLI::Version:
file: lib/Dancer2/CLI/Version.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core:
file: lib/Dancer2/Core.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::App:
file: lib/Dancer2/Core/App.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Cookie:
file: lib/Dancer2/Core/Cookie.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::DSL:
file: lib/Dancer2/Core/DSL.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Dispatcher:
file: lib/Dancer2/Core/Dispatcher.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Error:
file: lib/Dancer2/Core/Error.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Factory:
file: lib/Dancer2/Core/Factory.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::HTTP:
file: lib/Dancer2/Core/HTTP.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Hook:
file: lib/Dancer2/Core/Hook.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::MIME:
file: lib/Dancer2/Core/MIME.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Request:
file: lib/Dancer2/Core/Request.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Request::Upload:
file: lib/Dancer2/Core/Request/Upload.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Response:
file: lib/Dancer2/Core/Response.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Response::Delayed:
file: lib/Dancer2/Core/Response/Delayed.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::ConfigReader:
file: lib/Dancer2/Core/Role/ConfigReader.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::DSL:
file: lib/Dancer2/Core/Role/DSL.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::Engine:
file: lib/Dancer2/Core/Role/Engine.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::Handler:
file: lib/Dancer2/Core/Role/Handler.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::HasLocation:
file: lib/Dancer2/Core/Role/HasLocation.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::Hookable:
file: lib/Dancer2/Core/Role/Hookable.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::Logger:
file: lib/Dancer2/Core/Role/Logger.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::Serializer:
file: lib/Dancer2/Core/Role/Serializer.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::SessionFactory:
file: lib/Dancer2/Core/Role/SessionFactory.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::SessionFactory::File:
file: lib/Dancer2/Core/Role/SessionFactory/File.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::StandardResponses:
file: lib/Dancer2/Core/Role/StandardResponses.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Role::Template:
file: lib/Dancer2/Core/Role/Template.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Route:
file: lib/Dancer2/Core/Route.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Runner:
file: lib/Dancer2/Core/Runner.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Session:
file: lib/Dancer2/Core/Session.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Time:
file: lib/Dancer2/Core/Time.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Core::Types:
file: lib/Dancer2/Core/Types.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::FileUtils:
file: lib/Dancer2/FileUtils.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Handler::AutoPage:
file: lib/Dancer2/Handler/AutoPage.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Handler::File:
file: lib/Dancer2/Handler/File.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::Capture:
file: lib/Dancer2/Logger/Capture.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::Capture::Trap:
file: lib/Dancer2/Logger/Capture/Trap.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::Console:
file: lib/Dancer2/Logger/Console.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::Diag:
file: lib/Dancer2/Logger/Diag.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::File:
file: lib/Dancer2/Logger/File.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::Note:
file: lib/Dancer2/Logger/Note.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Logger::Null:
file: lib/Dancer2/Logger/Null.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Plugin:
file: lib/Dancer2/Plugin.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Serializer::Dumper:
file: lib/Dancer2/Serializer/Dumper.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Serializer::JSON:
file: lib/Dancer2/Serializer/JSON.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Serializer::Mutable:
file: lib/Dancer2/Serializer/Mutable.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Serializer::YAML:
file: lib/Dancer2/Serializer/YAML.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Session::Simple:
file: lib/Dancer2/Session/Simple.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Session::YAML:
file: lib/Dancer2/Session/YAML.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Template::Implementation::ForkedTiny:
file: lib/Dancer2/Template/Implementation/ForkedTiny.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Template::Simple:
file: lib/Dancer2/Template/Simple.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Template::TemplateToolkit:
file: lib/Dancer2/Template/TemplateToolkit.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Template::Tiny:
file: lib/Dancer2/Template/Tiny.pm
- version: v1.0.0
+ version: v1.1.0
Dancer2::Test:
file: lib/Dancer2/Test.pm
- version: v1.0.0
+ version: v1.1.0
recommends:
CGI::Deurl::XS: '0'
Class::XSAccessor: '0'
@@ -273,7 +273,7 @@ resources:
bugtracker: https://github.com/PerlDancer/Dancer2/issues
homepage: http://perldancer.org/
repository: git://github.com/PerlDancer/Dancer2.git
-version: 1.0.0
-x_generated_by_perl: v5.36.1
+version: 1.1.0
+x_generated_by_perl: v5.38.1
x_serialization_backend: 'YAML::Tiny version 1.74'
x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later'
diff --git a/Makefile.PL b/Makefile.PL
index 658a2ba6..f4e96a3f 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -1,4 +1,4 @@
-# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.030.
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.031.
use strict;
use warnings;
@@ -91,7 +91,7 @@ my %WriteMakefileArgs = (
"Test::Fatal" => 0,
"Test::More" => "0.92"
},
- "VERSION" => "1.0.0",
+ "VERSION" => "1.1.0",
"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-Delayed/*.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-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/examples/*.t t/issues/*.t t/issues/gh-1013/*.t t/issues/gh-1046/*.t t/issues/gh-1216/*.t t/issues/gh-1226/*.t t/issues/gh-1230/*.t t/issues/gh-1621/*.t t/issues/gh-639/fails/*.t t/issues/gh-639/succeeds/*.t t/issues/gh-650/*.t t/issues/gh-975/*.t t/issues/memleak/*.t t/plugin2/*.t t/plugin2/app_dsl_cb/*.t t/roles/*.t t/route-pod-coverage/*.t t/scope_problems/*.t t/template_tiny/*.t"
}
diff --git a/lib/Dancer2.pm b/lib/Dancer2.pm
index e456ec98..bc6bd28c 100644
--- a/lib/Dancer2.pm
+++ b/lib/Dancer2.pm
@@ -1,5 +1,5 @@
package Dancer2;
-$Dancer2::VERSION = '1.0.0';
+$Dancer2::VERSION = '1.1.0';
# ABSTRACT: Lightweight yet powerful web application framework
use 5.12.0;
@@ -129,7 +129,7 @@ Dancer2 - Lightweight yet powerful web application framework
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/CLI.pm b/lib/Dancer2/CLI.pm
index 2d027425..68282808 100644
--- a/lib/Dancer2/CLI.pm
+++ b/lib/Dancer2/CLI.pm
@@ -1,6 +1,6 @@
package Dancer2::CLI;
# ABSTRACT: Dancer2 CLI application
-$Dancer2::CLI::VERSION = '1.0.0';
+$Dancer2::CLI::VERSION = '1.1.0';
use Moo;
use CLI::Osprey;
use File::Share 'dist_dir';
@@ -42,7 +42,7 @@ Dancer2::CLI - Dancer2 CLI application
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/CLI/Gen.pm b/lib/Dancer2/CLI/Gen.pm
index b92f7fa4..f127312d 100644
--- a/lib/Dancer2/CLI/Gen.pm
+++ b/lib/Dancer2/CLI/Gen.pm
@@ -1,6 +1,6 @@
package Dancer2::CLI::Gen;
# ABSTRACT: Create new Dancer2 application
-$Dancer2::CLI::Gen::VERSION = '1.0.0';
+$Dancer2::CLI::Gen::VERSION = '1.1.0';
use Moo;
use URI;
use HTTP::Tiny;
@@ -461,7 +461,7 @@ Dancer2::CLI::Gen - Create new Dancer2 application
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/CLI/Version.pm b/lib/Dancer2/CLI/Version.pm
index 589cc88c..2773adc4 100644
--- a/lib/Dancer2/CLI/Version.pm
+++ b/lib/Dancer2/CLI/Version.pm
@@ -1,6 +1,6 @@
package Dancer2::CLI::Version;
# ABSTRACT: Display Dancer2 version
-$Dancer2::CLI::Version::VERSION = '1.0.0';
+$Dancer2::CLI::Version::VERSION = '1.1.0';
use Moo;
use CLI::Osprey
desc => 'Display version of Dancer2';
@@ -24,7 +24,7 @@ Dancer2::CLI::Version - Display Dancer2 version
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Config.pod b/lib/Dancer2/Config.pod
index 4d5b45a3..f82fa6d9 100644
--- a/lib/Dancer2/Config.pod
+++ b/lib/Dancer2/Config.pod
@@ -13,7 +13,7 @@ Dancer2::Config - Configure Dancer2 to suit your needs
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Cookbook.pod b/lib/Dancer2/Cookbook.pod
index fcf3fe2b..26a018e3 100644
--- a/lib/Dancer2/Cookbook.pod
+++ b/lib/Dancer2/Cookbook.pod
@@ -13,7 +13,7 @@ Dancer2::Cookbook - Example-driven quick-start to the Dancer2 web framework
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core.pm b/lib/Dancer2/Core.pm
index 1f703590..463b0cae 100644
--- a/lib/Dancer2/Core.pm
+++ b/lib/Dancer2/Core.pm
@@ -1,6 +1,6 @@
package Dancer2::Core;
# ABSTRACT: Core libraries for Dancer2 2.0
-$Dancer2::Core::VERSION = '1.0.0';
+$Dancer2::Core::VERSION = '1.1.0';
use strict;
use warnings;
@@ -29,7 +29,7 @@ Dancer2::Core - Core libraries for Dancer2 2.0
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 FUNCTIONS
diff --git a/lib/Dancer2/Core/App.pm b/lib/Dancer2/Core/App.pm
index c7c50008..68c8b754 100644
--- a/lib/Dancer2/Core/App.pm
+++ b/lib/Dancer2/Core/App.pm
@@ -1,16 +1,16 @@
# ABSTRACT: encapsulation of Dancer2 packages
package Dancer2::Core::App;
-$Dancer2::Core::App::VERSION = '1.0.0';
+$Dancer2::Core::App::VERSION = '1.1.0';
use Moo;
use Carp qw<croak carp>;
use Scalar::Util 'blessed';
+use List::Util ();
use Module::Runtime 'is_module_name';
use Safe::Isa;
use Sub::Quote;
use File::Spec;
use Module::Runtime qw< require_module use_module >;
-use List::Util ();
-use Ref::Util qw< is_ref is_globref is_scalarref >;
+use Ref::Util qw< is_ref is_arrayref is_globref is_scalarref is_regexpref >;
use Plack::App::File;
use Plack::Middleware::FixMissingBodyInRedirect;
@@ -608,6 +608,12 @@ has routes => (
},
);
+has 'route_names' => (
+ 'is' => 'rw',
+ 'isa' => HashRef,
+ 'default' => sub { {} },
+);
+
# add_hook will add the hook to the first "hook candidate" it finds that support
# it. If none, then it will try to add the hook to the current application.
around add_hook => sub {
@@ -1244,9 +1250,16 @@ sub add_route {
);
my $method = $route->method;
-
push @{ $self->routes->{$method} }, $route;
+ if ( $method ne 'head' && $route->has_name() ) {
+ my $name = $route->name;
+ $self->route_names->{$name}
+ and die "Route with this name ($name) already exists";
+
+ $self->route_names->{$name} = $route;
+ }
+
return $route;
}
@@ -1597,11 +1610,13 @@ DISPATCH:
sub build_request {
my ( $self, $env ) = @_;
+ Scalar::Util::weaken( my $weak_self = $self );
# If we have an app, send the serialization engine
my $request = Dancer2::Core::Request->new(
env => $env,
is_behind_proxy => $self->settings->{'behind_proxy'} || 0,
+ uri_for_route => sub { shift; $weak_self->uri_for_route(@_) },
$self->has_serializer_engine
? ( serializer => $self->serializer_engine )
@@ -1694,6 +1709,63 @@ sub response_not_found {
return $response;
}
+sub uri_for_route {
+ my ( $self, $route_name, $route_params, $query_params, $dont_escape ) = @_;
+ my $route = $self->route_names->{$route_name}
+ or die "Cannot find route named '$route_name'";
+
+ my $string = $route->spec_route;
+ is_regexpref($string)
+ and die "uri_for_route() does not support regexp route paths";
+
+ # Convert splat only to the general purpose structure
+ if ( is_arrayref($route_params) ) {
+ $route_params = { 'splat' => $route_params };
+ }
+
+ # The regexes are taken and altered from:
+ # Dancer2::Core::Route::_build_regexp_from_string.
+
+ # Replace :foo with arg (route parameters)
+ # Not a fan of all this regex play to handle typed parameter -- SX
+ my @params = $string =~ m{:([^/.\?]+)}xmsg;
+
+ foreach my $param (@params) {
+ $param =~ s{^([^\[]+).*}{$1}xms;
+ my $value = $route_params->{$param}
+ or die "Route $route_name uses the parameter '${param}', which was not provided";
+
+ $string =~ s!\Q:$param\E(\[[^\]]+\])?!$value!xmsg;
+ }
+
+ # TODO: Can we cut this down by replacing on the spot?
+ # I think that will be tricky because we first need all **, then *
+
+ $string =~ s!\Q**\E!(?#megasplat)!g;
+ $string =~ s!\*!(?#splat)!g;
+
+ # TODO: Can we cut this down?
+ my @token_or_splat =
+ $string =~ /\(\?#((?:mega)?splat)\)/g;
+
+ my $splat_params = $route_params->{'splat'};
+ if ($splat_params && @token_or_splat) {
+ $#{$splat_params} == $#token_or_splat
+ or die 'Mismatch in amount of splat args and splat elements';
+
+ for ( my $i = 0; $i < @{$splat_params}; $i++ ) {
+ if ( is_arrayref($splat_params->[$i]) ){
+ my $megasplat = join '/', @{ $splat_params->[$i] };
+ $string =~ s{\Q(?#megasplat)\E}{$megasplat};
+ } else {
+ $string =~ s{\Q(?#splat)\E}{$splat_params->[$i]};
+ }
+ }
+ }
+
+ return $self->request->uri_for( $string, $query_params, $dont_escape );
+}
+
1;
__END__
@@ -1708,7 +1780,7 @@ Dancer2::Core::App - encapsulation of Dancer2 packages
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Cookie.pm b/lib/Dancer2/Core/Cookie.pm
index e8597c92..6dee9e97 100644
--- a/lib/Dancer2/Core/Cookie.pm
+++ b/lib/Dancer2/Core/Cookie.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Cookie;
# ABSTRACT: A cookie representing class
-$Dancer2::Core::Cookie::VERSION = '1.0.0';
+$Dancer2::Core::Cookie::VERSION = '1.1.0';
use Moo;
use URI::Escape;
use Dancer2::Core::Types;
@@ -152,7 +152,7 @@ Dancer2::Core::Cookie - A cookie representing class
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/DSL.pm b/lib/Dancer2/Core/DSL.pm
index 53dab17a..6b5dad6f 100644
--- a/lib/Dancer2/Core/DSL.pm
+++ b/lib/Dancer2/Core/DSL.pm
@@ -1,11 +1,11 @@
# ABSTRACT: Dancer2's Domain Specific Language (DSL)
package Dancer2::Core::DSL;
-$Dancer2::Core::DSL::VERSION = '1.0.0';
+$Dancer2::Core::DSL::VERSION = '1.1.0';
use Moo;
use Carp;
use Module::Runtime 'require_module';
-use Ref::Util qw< is_arrayref >;
+use Ref::Util qw< is_arrayref is_hashref >;
use Dancer2::Core::Hook;
use Dancer2::FileUtils;
use Dancer2::Core::Response::Delayed;
@@ -122,6 +122,7 @@ sub dsl_keywords {
true => { is_global => 1 },
upload => { is_global => 0 },
uri_for => { is_global => 0 },
+ uri_for_route => { is_global => 0 },
var => { is_global => 0 },
vars => { is_global => 0 },
warning => { is_global => 1 },
@@ -241,11 +242,26 @@ sub _normalize_route {
my $methods = shift;
my %args;
- # Options are optional, deduce their presence from arg length.
- # @_ = ( REGEXP, OPTIONS, CODE )
- # or
- # @_ = ( REGEXP, CODE )
- @args{qw/regexp options code/} = @_ == 3 ? @_ : ( $_[0], {}, $_[1] );
+ # Options are optional, try to deduce their presence from arg length.
+ if ( @_ == 4 ) {
+ # @_ = ( NAME, REGEXP, OPTIONS, CODE )
+ # get 'foo', '/foo', { 'user_agent' => '...' }, sub {...}
+ @args{qw<name regexp options code>} = @_;
+ } elsif ( @_ == 2 ) {
+ # @_ = ( REGEXP, CODE )
+ # get '/foo', sub {...}
+ @args{qw<regexp code>} = @_;
+ } elsif ( @_ == 3 ) {
+ # @_ = ( REGEXP, OPTIONS, CODE )
+ # get '/foo', { 'user_agent' => '...' }, sub {...}
+ # @_ = ( NAME, REGEXP, CODE )
+ # get 'foo', '/foo',sub {...}
+ if ( is_hashref( $_[1] ) ) {
+ @args{qw<regexp options code>} = @_;
+ } else {
+ @args{qw<name regexp code>} = @_;
+ }
+ }
return map $app->add_route( %args, method => $_ ), @{$methods};
}
@@ -414,6 +430,8 @@ sub captures { $Dancer2::Core::Route::REQUEST->captures }
sub uri_for { shift; $Dancer2::Core::Route::REQUEST->uri_for(@_); }
+sub uri_for_route { shift->app->uri_for_route(@_); }
+
sub splat { $Dancer2::Core::Route::REQUEST->splat }
sub params { shift; $Dancer2::Core::Route::REQUEST->params(@_); }
@@ -515,7 +533,7 @@ Dancer2::Core::DSL - Dancer2's Domain Specific Language (DSL)
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 FUNCTIONS
diff --git a/lib/Dancer2/Core/Dispatcher.pm b/lib/Dancer2/Core/Dispatcher.pm
index 1a33e440..dc477b9c 100644
--- a/lib/Dancer2/Core/Dispatcher.pm
+++ b/lib/Dancer2/Core/Dispatcher.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Dispatcher;
# ABSTRACT: Class for dispatching request to the appropriate route handler
-$Dancer2::Core::Dispatcher::VERSION = '1.0.0';
+$Dancer2::Core::Dispatcher::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types;
@@ -73,7 +73,7 @@ Dancer2::Core::Dispatcher - Class for dispatching request to the appropriate rou
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/Error.pm b/lib/Dancer2/Core/Error.pm
index 9fd8f07f..551010fd 100644
--- a/lib/Dancer2/Core/Error.pm
+++ b/lib/Dancer2/Core/Error.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Error;
# ABSTRACT: Class representing fatal errors
-$Dancer2::Core::Error::VERSION = '1.0.0';
+$Dancer2::Core::Error::VERSION = '1.1.0';
use Moo;
use Carp;
use Dancer2::Core::Types;
@@ -483,7 +483,7 @@ Dancer2::Core::Error - Class representing fatal errors
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/Factory.pm b/lib/Dancer2/Core/Factory.pm
index 54db3881..07c58f01 100644
--- a/lib/Dancer2/Core/Factory.pm
+++ b/lib/Dancer2/Core/Factory.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Factory;
# ABSTRACT: Instantiate components by type and name
-$Dancer2::Core::Factory::VERSION = '1.0.0';
+$Dancer2::Core::Factory::VERSION = '1.1.0';
use Moo;
use Dancer2::Core;
use Module::Runtime 'use_module';
@@ -33,7 +33,7 @@ Dancer2::Core::Factory - Instantiate components by type and name
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Core/HTTP.pm b/lib/Dancer2/Core/HTTP.pm
index 7cb23013..6c79a31c 100644
--- a/lib/Dancer2/Core/HTTP.pm
+++ b/lib/Dancer2/Core/HTTP.pm
@@ -1,7 +1,7 @@
# ABSTRACT: helper for rendering HTTP status codes for Dancer2
package Dancer2::Core::HTTP;
-$Dancer2::Core::HTTP::VERSION = '1.0.0';
+$Dancer2::Core::HTTP::VERSION = '1.1.0';
use strict;
use warnings;
@@ -144,7 +144,7 @@ Dancer2::Core::HTTP - helper for rendering HTTP status codes for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 FUNCTIONS
diff --git a/lib/Dancer2/Core/Hook.pm b/lib/Dancer2/Core/Hook.pm
index ad312afb..65fa5575 100644
--- a/lib/Dancer2/Core/Hook.pm
+++ b/lib/Dancer2/Core/Hook.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Hook;
# ABSTRACT: Manipulate hooks with Dancer2
-$Dancer2::Core::Hook::VERSION = '1.0.0';
+$Dancer2::Core::Hook::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types;
use Carp;
@@ -51,7 +51,7 @@ Dancer2::Core::Hook - Manipulate hooks with Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/MIME.pm b/lib/Dancer2/Core/MIME.pm
index cf0f7f98..836fddd4 100644
--- a/lib/Dancer2/Core/MIME.pm
+++ b/lib/Dancer2/Core/MIME.pm
@@ -1,7 +1,7 @@
# ABSTRACT: Class to ease manipulation of MIME types
package Dancer2::Core::MIME;
-$Dancer2::Core::MIME::VERSION = '1.0.0';
+$Dancer2::Core::MIME::VERSION = '1.1.0';
use Moo;
use Plack::MIME;
@@ -91,7 +91,7 @@ Dancer2::Core::MIME - Class to ease manipulation of MIME types
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/Request.pm b/lib/Dancer2/Core/Request.pm
index ef2bf5c9..040d6822 100644
--- a/lib/Dancer2/Core/Request.pm
+++ b/lib/Dancer2/Core/Request.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Request;
# ABSTRACT: Interface for accessing incoming requests
-$Dancer2::Core::Request::VERSION = '1.0.0';
+$Dancer2::Core::Request::VERSION = '1.1.0';
use strict;
use warnings;
use parent 'Plack::Request';
@@ -11,7 +11,7 @@ use URI;
use URI::Escape;
use Safe::Isa;
use Hash::MultiValue;
-use Ref::Util qw< is_ref is_arrayref is_hashref >;
+use Ref::Util qw< is_ref is_arrayref is_hashref is_coderef >;
use Dancer2::Core::Types;
use Dancer2::Core::Request::Upload;
@@ -77,6 +77,7 @@ sub new {
$self->{'id'} = ++$_id;
$self->{'vars'} = {};
$self->{'is_behind_proxy'} = !!$opts{'is_behind_proxy'};
+ $self->{'uri_for_route'} = $opts{'uri_for_route'};
$opts{'body_params'}
and $self->{'_body_params'} = $opts{'body_params'};
@@ -316,6 +317,15 @@ sub uri_for {
: ${ $uri->canonical };
}
+sub uri_for_route {
+ my ( $self, @args ) = @_;
+
+ is_coderef( $self->{'uri_for_route'} )
+ or die 'uri_for_route called on a request instance without it';
+
+ return $self->{'uri_for_route'}->(@_);
+}
+
sub params {
my ( $self, $source ) = @_;
@@ -648,7 +658,7 @@ Dancer2::Core::Request - Interface for accessing incoming requests
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
@@ -1021,6 +1031,13 @@ You get the following behavior:
C<uri_for> returns a L<URI> object (which can stringify to the value).
+=head2 uri_for_route(route_name, route_params, query_params, escape)
+
+Constructs a URI from the base and the path of the specified route name.
+
+Read more about it in the C<Dancer2::Manual::Keywords> document under
+C<uri_for_route>.
+
=head2 user
Return remote user if defined.
diff --git a/lib/Dancer2/Core/Request/Upload.pm b/lib/Dancer2/Core/Request/Upload.pm
index d57b935a..dce88e7d 100644
--- a/lib/Dancer2/Core/Request/Upload.pm
+++ b/lib/Dancer2/Core/Request/Upload.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Request::Upload;
# ABSTRACT: Class representing file upload requests
-$Dancer2::Core::Request::Upload::VERSION = '1.0.0';
+$Dancer2::Core::Request::Upload::VERSION = '1.1.0';
use Moo;
use Carp;
@@ -92,7 +92,7 @@ Dancer2::Core::Request::Upload - Class representing file upload requests
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Response.pm b/lib/Dancer2/Core/Response.pm
index debe5ea7..62d82b43 100644
--- a/lib/Dancer2/Core/Response.pm
+++ b/lib/Dancer2/Core/Response.pm
@@ -1,7 +1,7 @@
# ABSTRACT: Response object for Dancer2
package Dancer2::Core::Response;
-$Dancer2::Core::Response::VERSION = '1.0.0';
+$Dancer2::Core::Response::VERSION = '1.1.0';
use Moo;
use Encode;
@@ -276,7 +276,7 @@ Dancer2::Core::Response - Response object for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 ATTRIBUTES
diff --git a/lib/Dancer2/Core/Response/Delayed.pm b/lib/Dancer2/Core/Response/Delayed.pm
index a38466b3..88cfb8ea 100644
--- a/lib/Dancer2/Core/Response/Delayed.pm
+++ b/lib/Dancer2/Core/Response/Delayed.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Response::Delayed;
# ABSTRACT: Delayed responses
-$Dancer2::Core::Response::Delayed::VERSION = '1.0.0';
+$Dancer2::Core::Response::Delayed::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types qw<CodeRef InstanceOf>;
@@ -64,7 +64,7 @@ Dancer2::Core::Response::Delayed - Delayed responses
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/Role/ConfigReader.pm b/lib/Dancer2/Core/Role/ConfigReader.pm
index 6d509aa4..9ef49a78 100644
--- a/lib/Dancer2/Core/Role/ConfigReader.pm
+++ b/lib/Dancer2/Core/Role/ConfigReader.pm
@@ -1,6 +1,6 @@
# ABSTRACT: Config role for Dancer2 core objects
package Dancer2::Core::Role::ConfigReader;
-$Dancer2::Core::Role::ConfigReader::VERSION = '1.0.0';
+$Dancer2::Core::Role::ConfigReader::VERSION = '1.1.0';
use Moo::Role;
use File::Spec;
@@ -289,7 +289,7 @@ Dancer2::Core::Role::ConfigReader - Config role for Dancer2 core objects
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Role/DSL.pm b/lib/Dancer2/Core/Role/DSL.pm
index a8cb0879..dd88e035 100644
--- a/lib/Dancer2/Core/Role/DSL.pm
+++ b/lib/Dancer2/Core/Role/DSL.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::DSL;
# ABSTRACT: Role for DSL
-$Dancer2::Core::Role::DSL::VERSION = '1.0.0';
+$Dancer2::Core::Role::DSL::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core::Types;
use Carp 'croak';
@@ -114,7 +114,7 @@ Dancer2::Core::Role::DSL - Role for DSL
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Core/Role/Engine.pm b/lib/Dancer2/Core/Role/Engine.pm
index 2bc71fc3..ff4e2154 100644
--- a/lib/Dancer2/Core/Role/Engine.pm
+++ b/lib/Dancer2/Core/Role/Engine.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::Engine;
# ABSTRACT: Role for engines
-$Dancer2::Core::Role::Engine::VERSION = '1.0.0';
+$Dancer2::Core::Role::Engine::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core::Types;
@@ -42,7 +42,7 @@ Dancer2::Core::Role::Engine - Role for engines
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Role/Handler.pm b/lib/Dancer2/Core/Role/Handler.pm
index 1290c02c..9fd1fb23 100644
--- a/lib/Dancer2/Core/Role/Handler.pm
+++ b/lib/Dancer2/Core/Role/Handler.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::Handler;
# ABSTRACT: Role for Handlers
-$Dancer2::Core::Role::Handler::VERSION = '1.0.0';
+$Dancer2::Core::Role::Handler::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core::Types;
@@ -26,7 +26,7 @@ Dancer2::Core::Role::Handler - Role for Handlers
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 ATTRIBUTES
diff --git a/lib/Dancer2/Core/Role/HasLocation.pm b/lib/Dancer2/Core/Role/HasLocation.pm
index c35521d5..9f25ba84 100644
--- a/lib/Dancer2/Core/Role/HasLocation.pm
+++ b/lib/Dancer2/Core/Role/HasLocation.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::HasLocation;
# ABSTRACT: Role for application location "guessing"
-$Dancer2::Core::Role::HasLocation::VERSION = '1.0.0';
+$Dancer2::Core::Role::HasLocation::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core::Types;
use Dancer2::FileUtils;
@@ -88,7 +88,7 @@ Dancer2::Core::Role::HasLocation - Role for application location "guessing"
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Core/Role/Hookable.pm b/lib/Dancer2/Core/Role/Hookable.pm
index b2d58ab1..592730e3 100644
--- a/lib/Dancer2/Core/Role/Hookable.pm
+++ b/lib/Dancer2/Core/Role/Hookable.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::Hookable;
# ABSTRACT: Role for hookable objects
-$Dancer2::Core::Role::Hookable::VERSION = '1.0.0';
+$Dancer2::Core::Role::Hookable::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core;
use Dancer2::Core::Types;
@@ -130,7 +130,7 @@ Dancer2::Core::Role::Hookable - Role for hookable objects
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Core/Role/Logger.pm b/lib/Dancer2/Core/Role/Logger.pm
index 5bb22813..a1d56706 100644
--- a/lib/Dancer2/Core/Role/Logger.pm
+++ b/lib/Dancer2/Core/Role/Logger.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::Logger;
# ABSTRACT: Role for logger engines
-$Dancer2::Core::Role::Logger::VERSION = '1.0.0';
+$Dancer2::Core::Role::Logger::VERSION = '1.1.0';
use Dancer2::Core::Types;
use Moo::Role;
@@ -191,7 +191,7 @@ Dancer2::Core::Role::Logger - Role for logger engines
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Role/Serializer.pm b/lib/Dancer2/Core/Role/Serializer.pm
index c009b30b..6ac66575 100644
--- a/lib/Dancer2/Core/Role/Serializer.pm
+++ b/lib/Dancer2/Core/Role/Serializer.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::Serializer;
# ABSTRACT: Role for Serializer engines
-$Dancer2::Core::Role::Serializer::VERSION = '1.0.0';
+$Dancer2::Core::Role::Serializer::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core::Types;
use Scalar::Util 'blessed';
@@ -88,7 +88,7 @@ Dancer2::Core::Role::Serializer - Role for Serializer engines
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Role/SessionFactory.pm b/lib/Dancer2/Core/Role/SessionFactory.pm
index 8d171a81..2e450bfe 100644
--- a/lib/Dancer2/Core/Role/SessionFactory.pm
+++ b/lib/Dancer2/Core/Role/SessionFactory.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::SessionFactory;
# ABSTRACT: Role for session factories
-$Dancer2::Core::Role::SessionFactory::VERSION = '1.0.0';
+$Dancer2::Core::Role::SessionFactory::VERSION = '1.1.0';
use Moo::Role;
with 'Dancer2::Core::Role::Engine';
@@ -301,7 +301,7 @@ Dancer2::Core::Role::SessionFactory - Role for session factories
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Role/SessionFactory/File.pm b/lib/Dancer2/Core/Role/SessionFactory/File.pm
index a24d6f3c..65d46b76 100644
--- a/lib/Dancer2/Core/Role/SessionFactory/File.pm
+++ b/lib/Dancer2/Core/Role/SessionFactory/File.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::SessionFactory::File;
# ABSTRACT: Role for file-based session factories
-$Dancer2::Core::Role::SessionFactory::File::VERSION = '1.0.0';
+$Dancer2::Core::Role::SessionFactory::File::VERSION = '1.1.0';
use Moo::Role;
with 'Dancer2::Core::Role::SessionFactory';
@@ -125,7 +125,7 @@ Dancer2::Core::Role::SessionFactory::File - Role for file-based session factorie
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Role/StandardResponses.pm b/lib/Dancer2/Core/Role/StandardResponses.pm
index 151d155c..dd11edb5 100644
--- a/lib/Dancer2/Core/Role/StandardResponses.pm
+++ b/lib/Dancer2/Core/Role/StandardResponses.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Role::StandardResponses;
# ABSTRACT: Role to provide commonly used responses
-$Dancer2::Core::Role::StandardResponses::VERSION = '1.0.0';
+$Dancer2::Core::Role::StandardResponses::VERSION = '1.1.0';
use Moo::Role;
use Dancer2::Core::HTTP;
@@ -35,7 +35,7 @@ Dancer2::Core::Role::StandardResponses - Role to provide commonly used responses
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 METHODS
diff --git a/lib/Dancer2/Core/Role/Template.pm b/lib/Dancer2/Core/Role/Template.pm
index 3580d17c..f5674681 100644
--- a/lib/Dancer2/Core/Role/Template.pm
+++ b/lib/Dancer2/Core/Role/Template.pm
@@ -1,7 +1,7 @@
# ABSTRACT: Role for template engines
package Dancer2::Core::Role::Template;
-$Dancer2::Core::Role::Template::VERSION = '1.0.0';
+$Dancer2::Core::Role::Template::VERSION = '1.1.0';
use Dancer2::Core::Types;
use Dancer2::FileUtils 'path';
use Carp 'croak';
@@ -237,7 +237,7 @@ Dancer2::Core::Role::Template - Role for template engines
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Route.pm b/lib/Dancer2/Core/Route.pm
index 67970de9..bea52b14 100644
--- a/lib/Dancer2/Core/Route.pm
+++ b/lib/Dancer2/Core/Route.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Route;
# ABSTRACT: Dancer2's route handler
-$Dancer2::Core::Route::VERSION = '1.0.0';
+$Dancer2::Core::Route::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types;
use Module::Runtime 'use_module';
@@ -12,6 +12,12 @@ use Type::Registry;
our ( $REQUEST, $RESPONSE, $RESPONDER, $WRITER, $ERROR_HANDLER );
+has name => (
+ is => 'ro',
+ isa => Str,
+ predicate => 'has_name',
+);
+
has method => (
is => 'ro',
isa => Dancer2Method,
@@ -318,7 +324,7 @@ Dancer2::Core::Route - Dancer2's route handler
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 ATTRIBUTES
diff --git a/lib/Dancer2/Core/Runner.pm b/lib/Dancer2/Core/Runner.pm
index e587b088..5f8cc9ec 100644
--- a/lib/Dancer2/Core/Runner.pm
+++ b/lib/Dancer2/Core/Runner.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Runner;
# ABSTRACT: Top-layer class to start a dancer app
-$Dancer2::Core::Runner::VERSION = '1.0.0';
+$Dancer2::Core::Runner::VERSION = '1.1.0';
use Moo;
use Carp 'croak';
use Module::Runtime 'require_module';
@@ -261,7 +261,7 @@ Dancer2::Core::Runner - Top-layer class to start a dancer app
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Core/Session.pm b/lib/Dancer2/Core/Session.pm
index 05bab5a5..d58e1182 100644
--- a/lib/Dancer2/Core/Session.pm
+++ b/lib/Dancer2/Core/Session.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Session;
# ABSTRACT: class to represent any session object
-$Dancer2::Core::Session::VERSION = '1.0.0';
+$Dancer2::Core::Session::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types;
use Dancer2::Core::Time;
@@ -68,7 +68,7 @@ Dancer2::Core::Session - class to represent any session object
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Core/Time.pm b/lib/Dancer2/Core/Time.pm
index d4257623..eda6e380 100644
--- a/lib/Dancer2/Core/Time.pm
+++ b/lib/Dancer2/Core/Time.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Time;
# ABSTRACT: class to handle common helpers for time manipulations
-$Dancer2::Core::Time::VERSION = '1.0.0';
+$Dancer2::Core::Time::VERSION = '1.1.0';
use Moo;
has seconds => (
@@ -134,7 +134,7 @@ Dancer2::Core::Time - class to handle common helpers for time manipulations
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Core/Types.pm b/lib/Dancer2/Core/Types.pm
index 776019d4..846ab211 100644
--- a/lib/Dancer2/Core/Types.pm
+++ b/lib/Dancer2/Core/Types.pm
@@ -1,6 +1,6 @@
package Dancer2::Core::Types;
# ABSTRACT: Type::Tiny types for Dancer2 core.
-$Dancer2::Core::Types::VERSION = '1.0.0';
+$Dancer2::Core::Types::VERSION = '1.1.0';
use strict;
use warnings;
use Type::Library -base;
@@ -90,7 +90,7 @@ Dancer2::Core::Types - Type::Tiny types for Dancer2 core.
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/DeprecationPolicy.pod b/lib/Dancer2/DeprecationPolicy.pod
index f9275dbe..2954cabf 100644
--- a/lib/Dancer2/DeprecationPolicy.pod
+++ b/lib/Dancer2/DeprecationPolicy.pod
@@ -14,7 +14,7 @@ Dancer2::DeprecationPolicy - Define the process by which outdated, broken, or un
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/FileUtils.pm b/lib/Dancer2/FileUtils.pm
index 14967399..29444d81 100644
--- a/lib/Dancer2/FileUtils.pm
+++ b/lib/Dancer2/FileUtils.pm
@@ -1,6 +1,6 @@
package Dancer2::FileUtils;
# ABSTRACT: File utility helpers
-$Dancer2::FileUtils::VERSION = '1.0.0';
+$Dancer2::FileUtils::VERSION = '1.1.0';
use strict;
use warnings;
@@ -109,7 +109,7 @@ Dancer2::FileUtils - File utility helpers
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Handler/AutoPage.pm b/lib/Dancer2/Handler/AutoPage.pm
index a32c6909..e4f17936 100644
--- a/lib/Dancer2/Handler/AutoPage.pm
+++ b/lib/Dancer2/Handler/AutoPage.pm
@@ -1,6 +1,6 @@
package Dancer2::Handler::AutoPage;
# ABSTRACT: Class for handling the AutoPage feature
-$Dancer2::Handler::AutoPage::VERSION = '1.0.0';
+$Dancer2::Handler::AutoPage::VERSION = '1.1.0';
use Moo;
use Carp 'croak';
use Dancer2::Core::Types;
@@ -72,7 +72,7 @@ Dancer2::Handler::AutoPage - Class for handling the AutoPage feature
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Handler/File.pm b/lib/Dancer2/Handler/File.pm
index 9cdb397d..65d12c2d 100644
--- a/lib/Dancer2/Handler/File.pm
+++ b/lib/Dancer2/Handler/File.pm
@@ -1,6 +1,6 @@
package Dancer2::Handler::File;
# ABSTRACT: class for handling file content rendering
-$Dancer2::Handler::File::VERSION = '1.0.0';
+$Dancer2::Handler::File::VERSION = '1.1.0';
use Carp 'croak';
use Moo;
use HTTP::Date;
@@ -163,7 +163,7 @@ Dancer2::Handler::File - class for handling file content rendering
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 AUTHOR
diff --git a/lib/Dancer2/Logger/Capture.pm b/lib/Dancer2/Logger/Capture.pm
index 22793eb0..19205482 100644
--- a/lib/Dancer2/Logger/Capture.pm
+++ b/lib/Dancer2/Logger/Capture.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::Capture;
# ABSTRACT: Capture dancer logs
-$Dancer2::Logger::Capture::VERSION = '1.0.0';
+$Dancer2::Logger::Capture::VERSION = '1.1.0';
use Moo;
use Dancer2::Logger::Capture::Trap;
@@ -38,7 +38,7 @@ Dancer2::Logger::Capture - Capture dancer logs
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Logger/Capture/Trap.pm b/lib/Dancer2/Logger/Capture/Trap.pm
index 6bec97a3..a575b35f 100644
--- a/lib/Dancer2/Logger/Capture/Trap.pm
+++ b/lib/Dancer2/Logger/Capture/Trap.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::Capture::Trap;
# ABSTRACT: a place to store captured Dancer2 logs
-$Dancer2::Logger::Capture::Trap::VERSION = '1.0.0';
+$Dancer2::Logger::Capture::Trap::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types;
@@ -41,7 +41,7 @@ Dancer2::Logger::Capture::Trap - a place to store captured Dancer2 logs
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Logger/Console.pm b/lib/Dancer2/Logger/Console.pm
index c6695949..5507029f 100644
--- a/lib/Dancer2/Logger/Console.pm
+++ b/lib/Dancer2/Logger/Console.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::Console;
# ABSTRACT: Console logger
-$Dancer2::Logger::Console::VERSION = '1.0.0';
+$Dancer2::Logger::Console::VERSION = '1.1.0';
use Moo;
with 'Dancer2::Core::Role::Logger';
@@ -24,7 +24,7 @@ Dancer2::Logger::Console - Console logger
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Logger/Diag.pm b/lib/Dancer2/Logger/Diag.pm
index 5f79eb53..ff705caa 100644
--- a/lib/Dancer2/Logger/Diag.pm
+++ b/lib/Dancer2/Logger/Diag.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::Diag;
# ABSTRACT: Test::More diag() logging engine for Dancer2
-$Dancer2::Logger::Diag::VERSION = '1.0.0';
+$Dancer2::Logger::Diag::VERSION = '1.1.0';
use Moo;
use Test::More;
@@ -26,7 +26,7 @@ Dancer2::Logger::Diag - Test::More diag() logging engine for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Logger/File.pm b/lib/Dancer2/Logger/File.pm
index df05b4d3..d61ddcfc 100644
--- a/lib/Dancer2/Logger/File.pm
+++ b/lib/Dancer2/Logger/File.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::File;
# ABSTRACT: file-based logging engine for Dancer2
-$Dancer2::Logger::File::VERSION = '1.0.0';
+$Dancer2::Logger::File::VERSION = '1.1.0';
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 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Logger/Note.pm b/lib/Dancer2/Logger/Note.pm
index 7d3df1fe..62a248e7 100644
--- a/lib/Dancer2/Logger/Note.pm
+++ b/lib/Dancer2/Logger/Note.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::Note;
# ABSTRACT: Test::More note() logging engine for Dancer2
-$Dancer2::Logger::Note::VERSION = '1.0.0';
+$Dancer2::Logger::Note::VERSION = '1.1.0';
use Moo;
use Test::More;
@@ -26,7 +26,7 @@ Dancer2::Logger::Note - Test::More note() logging engine for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Logger/Null.pm b/lib/Dancer2/Logger/Null.pm
index f939dd8c..bff0cdb8 100644
--- a/lib/Dancer2/Logger/Null.pm
+++ b/lib/Dancer2/Logger/Null.pm
@@ -1,6 +1,6 @@
package Dancer2::Logger::Null;
# ABSTRACT: Blackhole-like silent logging engine for Dancer2
-$Dancer2::Logger::Null::VERSION = '1.0.0';
+$Dancer2::Logger::Null::VERSION = '1.1.0';
use Moo;
with 'Dancer2::Core::Role::Logger';
@@ -20,7 +20,7 @@ Dancer2::Logger::Null - Blackhole-like silent logging engine for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Manual.pod b/lib/Dancer2/Manual.pod
index 858393e5..7e2c9e4a 100644
--- a/lib/Dancer2/Manual.pod
+++ b/lib/Dancer2/Manual.pod
@@ -13,7 +13,7 @@ Dancer2::Manual - A gentle introduction to Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
@@ -223,6 +223,12 @@ coderef to execute, which returns the response.
The above route specifies that, for GET requests to C</hello/...>, the code
block provided should be executed.
+You can also provide routes with a name:
+
+ get 'hi_to' => '/hello/:name' => sub {...};
+
+See L<Dancer2::Manual::Keywords/uri_for_route> on how this can be used.
+
=head3 Retrieving request parameters
The L<query_parameters|Dancer2::Manual/query_parameters>,
diff --git a/lib/Dancer2/Manual/Deployment.pod b/lib/Dancer2/Manual/Deployment.pod
index 6ae47dc3..9c08568a 100644
--- a/lib/Dancer2/Manual/Deployment.pod
+++ b/lib/Dancer2/Manual/Deployment.pod
@@ -13,7 +13,7 @@ Dancer2::Manual::Deployment - common ways to put your Dancer app into use
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Manual/Keywords.pod b/lib/Dancer2/Manual/Keywords.pod
index 1b8cf2b5..a37d2e6e 100644
--- a/lib/Dancer2/Manual/Keywords.pod
+++ b/lib/Dancer2/Manual/Keywords.pod
@@ -13,7 +13,7 @@ Dancer2::Manual::Keywords - Dancer2 DSL Keywords
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DSL KEYWORDS
@@ -210,6 +210,12 @@ Defines a route for HTTP B<DELETE> requests to the given URL:
del '/resource' => sub { ... };
+You can also provide the route with a name:
+
+ del 'rec' => '/resource' => sub { ... };
+
+See C<uri_for_route> on how this can be used.
+
=head2 delayed
Stream a response asynchronously. For more information, please see
@@ -359,6 +365,14 @@ Defines a route for HTTP B<GET> requests to the given path:
Note that a route to match B<HEAD> requests is automatically created as well.
+You can also provide the route with a name:
+
+ get 'index' => '/' => sub {
+ return "Hello world";
+ }
+
+See C<uri_for_route> on how this can be used.
+
=head2 halt
Sets a response object with the content given.
@@ -526,6 +540,12 @@ Defines a route for HTTP B<PATCH> requests to the given URL:
intended to work as a "partial-PUT", transferring just the changes; please
see L<RFC5789|http://tools.ietf.org/html/rfc5789> for further details.)
+You can also provide the route with a name:
+
+ patch 'rec' => '/resource' => sub { ... };
+
+See C<uri_for_route> on how this can be used.
+
=head2 path
Concatenates multiple paths together, without worrying about the underlying
@@ -544,6 +564,14 @@ Defines a route for HTTP B<POST> requests to the given URL:
return "Hello world";
}
+You can also provide the route with a name:
+
+ post 'index' => '/' => sub {
+ return "Hello world";
+ }
+
+See C<uri_for_route> on how this can be used.
+
=head2 prefix
Defines a prefix for each route handler, like this:
@@ -635,6 +663,12 @@ Defines a route for HTTP B<PUT> requests to the given URL:
put '/resource' => sub { ... };
+You can also provide the route with a name:
+
+ put 'rec' => '/resource' => sub { ... };
+
+See C<uri_for_route> on how this can be used.
+
=head2 query_parameters
Returns a L<Hash::MultiValue> object from the request parameters.
@@ -1154,6 +1188,129 @@ URL encoding via a third parameter:
uri_for('/path', { foo => 'qux%3Dquo' }, 1);
# would return http://localhost:5000/path?foo=qux%3Dquo
+=head2 uri_for_route
+
+An enhanced version of C<uri_for> that utilizes routes' names.
+
+ get 'view_entry' => '/entry/view/:id' => sub {...};
+
+Now that the route has a name we can use C<uri_for_route> to
+create a URI for it:
+
+ my $path = uri_for_route(
+ 'view_entry',
+ { 'id' => 3 },
+ { 'foo' => 'bar' },
+ );
+
+ # (assuming it's run on a local server in HTTP port 5000)
+ # $path = 'http://localhost:5000/entry/view/3?foo=bar'
+
+This works for every HTTP method, except C<HEAD> (which is
+effectively a C<GET>).
+
+It can also be used in templates:
+
+ <!-- some_template.tt -->
+ [% request.uri_for_route( 'my_route_name', { 'foo' => 'bar' }, { 'id' => 4 } ) %]
+
+There are multiple arguments options:
+
+=over 4
+
+=item * Route parameters
+
+The first argument controls the route parameters:
+
+ get 'test' => '/:foo/:bar' => sub {1};
+ # ...
+ $path = uri_for_route( 'test', { 'foo' => 'hello', 'bar' => 'world' } );
+ # $path = http://localhost:5000/hello/world
+
+=item * Splat route parameters
+
+If you provide an arrayref instead of hashref, it will assume on
+these being splat and megasplat args:
+
+ get 'test' => '/*/*/**' => sub {1};
+ # ...
+ $path = uri_for_route(
+ 'test',
+ [ 'hello', 'world', [ 'myhello', 'myworld' ],
+ );
+ # $path = http://localhost:5000/hello/world/myhello/myworld
+
+=item * Mixed route parameters
+
+If you have a route that includes both, the splat and megasplat
+arguments need to be under the C<splat> key:
+
+ patch 'test' => '/*/:id/*/:foo/*' => sub {1};
+ # ...
+ $path = uri_for_route(
+ 'test',
+ {
+ 'id' => 4,
+ 'foo ' => 'bar',
+ 'splat' => [ 'hello', 'world' ],
+ }
+ );
+ # $path = http://localhost:5000/hello/4/world/bar
+
+=item * Query parameters
+
+If you want to create a path the query parameters, use the
+second argument:
+
+ get 'index' => '/:foo' => sub {1};
+ get 'update_form' => '/update' => sub {1};
+
+ # ...
+
+ $path = uri_for_route(
+ 'index',
+ { 'foo' => 'bar' },
+ { 'id' => 1 },
+ );
+ # $path = http://localhost:5000/bar?id=1
+
+ $path = uri_for_route( 'update_form', {}, { 'id' => 2 } );
+ # $path = http://localhost:5000/update?id=2
+
+(Technically, only C<GET> requests should include query parameters, but
+C<uri_for_route> does not enforce this.)
+
+=item * Disable URI escaping
+
+The final parameter determines whether the URI will be URI-escaped or not:
+
+ get 'show_entry' => '/view/:str_id' => sub {1};
+ # ...
+ $path = uri_for_route(
+ 'show_entry',
+ { 'str_id' => '<javascript>...' },
+ {},
+ );
+ # $path = http://localhost/view/%3Cjavascript%3E...
+
+This is useful when your ID is not HTML-safe and might include HTML
+tags and Javascript code or include characters that interfere with the
+URI request string (like a forward slash).
+
+This is on by default, but you can disable it by setting this flag:
+
+ get 'show_entry' => '/view/:str_id' => sub {1};
+ # ...
+ $path = uri_for_route(
+ 'show_entry',
+ { 'str_id' => '<javascript>...' },
+ {},
+ 1,
+ );
+ # $path = http://localhost/view/<javascript>...
+
+=back
+
=head2 var
Provides an accessor for variables shared between hooks and route
diff --git a/lib/Dancer2/Manual/Migration.pod b/lib/Dancer2/Manual/Migration.pod
index 9663a438..3e5258a6 100644
--- a/lib/Dancer2/Manual/Migration.pod
+++ b/lib/Dancer2/Manual/Migration.pod
@@ -18,7 +18,7 @@ Dancer2::Manual::Migration - Migrating from Dancer to Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 Migration from Dancer 1 to Dancer2
diff --git a/lib/Dancer2/Manual/Testing.pod b/lib/Dancer2/Manual/Testing.pod
index 5d0f8d48..d9637501 100644
--- a/lib/Dancer2/Manual/Testing.pod
+++ b/lib/Dancer2/Manual/Testing.pod
@@ -18,7 +18,7 @@ Dancer2::Manual::Testing - Writing tests for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 Basic application testing
diff --git a/lib/Dancer2/Plugin.pm b/lib/Dancer2/Plugin.pm
index bd626a10..29e01d2a 100644
--- a/lib/Dancer2/Plugin.pm
+++ b/lib/Dancer2/Plugin.pm
@@ -1,6 +1,6 @@
package Dancer2::Plugin;
# ABSTRACT: base class for Dancer2 plugins
-$Dancer2::Plugin::VERSION = '1.0.0';
+$Dancer2::Plugin::VERSION = '1.1.0';
use strict;
use warnings;
@@ -632,7 +632,7 @@ Dancer2::Plugin - base class for Dancer2 plugins
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Plugins.pod b/lib/Dancer2/Plugins.pod
index afb67e5b..30489da2 100644
--- a/lib/Dancer2/Plugins.pod
+++ b/lib/Dancer2/Plugins.pod
@@ -13,7 +13,7 @@ Dancer2::Plugins - Recommended Dancer2 plugins
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Policy.pod b/lib/Dancer2/Policy.pod
index 669caefa..692bb355 100644
--- a/lib/Dancer2/Policy.pod
+++ b/lib/Dancer2/Policy.pod
@@ -18,7 +18,7 @@ Dancer2::Policy - Dancer core and community policy and standards of conduct
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Serializer/Dumper.pm b/lib/Dancer2/Serializer/Dumper.pm
index 36c4869a..2ea87024 100644
--- a/lib/Dancer2/Serializer/Dumper.pm
+++ b/lib/Dancer2/Serializer/Dumper.pm
@@ -1,7 +1,7 @@
# ABSTRACT: Serializer for handling Dumper data
package Dancer2::Serializer::Dumper;
-$Dancer2::Serializer::Dumper::VERSION = '1.0.0';
+$Dancer2::Serializer::Dumper::VERSION = '1.1.0';
use Moo;
use Carp 'croak';
use Data::Dumper;
@@ -50,7 +50,7 @@ Dancer2::Serializer::Dumper - Serializer for handling Dumper data
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Serializer/JSON.pm b/lib/Dancer2/Serializer/JSON.pm
index 63df5304..0ee6b786 100644
--- a/lib/Dancer2/Serializer/JSON.pm
+++ b/lib/Dancer2/Serializer/JSON.pm
@@ -1,6 +1,6 @@
package Dancer2::Serializer::JSON;
# ABSTRACT: Serializer for handling JSON data
-$Dancer2::Serializer::JSON::VERSION = '1.0.0';
+$Dancer2::Serializer::JSON::VERSION = '1.1.0';
use Moo;
use JSON::MaybeXS ();
use Scalar::Util 'blessed';
@@ -61,7 +61,7 @@ Dancer2::Serializer::JSON - Serializer for handling JSON data
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Serializer/Mutable.pm b/lib/Dancer2/Serializer/Mutable.pm
index 6e8e34fe..1aba36d1 100644
--- a/lib/Dancer2/Serializer/Mutable.pm
+++ b/lib/Dancer2/Serializer/Mutable.pm
@@ -1,6 +1,6 @@
package Dancer2::Serializer::Mutable;
# ABSTRACT: Serialize and deserialize content based on HTTP header
-$Dancer2::Serializer::Mutable::VERSION = '1.0.0';
+$Dancer2::Serializer::Mutable::VERSION = '1.1.0';
use Moo;
use Carp 'croak';
use Encode;
@@ -121,7 +121,7 @@ Dancer2::Serializer::Mutable - Serialize and deserialize content based on HTTP h
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Serializer/YAML.pm b/lib/Dancer2/Serializer/YAML.pm
index 9638eb58..668a5773 100644
--- a/lib/Dancer2/Serializer/YAML.pm
+++ b/lib/Dancer2/Serializer/YAML.pm
@@ -1,6 +1,6 @@
package Dancer2::Serializer::YAML;
# ABSTRACT: Serializer for handling YAML data
-$Dancer2::Serializer::YAML::VERSION = '1.0.0';
+$Dancer2::Serializer::YAML::VERSION = '1.1.0';
use Moo;
use Carp 'croak';
use Encode;
@@ -51,7 +51,7 @@ Dancer2::Serializer::YAML - Serializer for handling YAML data
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Session/Simple.pm b/lib/Dancer2/Session/Simple.pm
index 3fa1b098..dfa86fdb 100644
--- a/lib/Dancer2/Session/Simple.pm
+++ b/lib/Dancer2/Session/Simple.pm
@@ -1,6 +1,6 @@
package Dancer2::Session::Simple;
# ABSTRACT: in-memory session backend for Dancer2
-$Dancer2::Session::Simple::VERSION = '1.0.0';
+$Dancer2::Session::Simple::VERSION = '1.1.0';
use Moo;
use Dancer2::Core::Types;
use Carp;
@@ -56,7 +56,7 @@ Dancer2::Session::Simple - in-memory session backend for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Session/YAML.pm b/lib/Dancer2/Session/YAML.pm
index 3d189f18..c6342508 100644
--- a/lib/Dancer2/Session/YAML.pm
+++ b/lib/Dancer2/Session/YAML.pm
@@ -1,5 +1,5 @@
package Dancer2::Session::YAML;
-$Dancer2::Session::YAML::VERSION = '1.0.0';
+$Dancer2::Session::YAML::VERSION = '1.1.0';
# ABSTRACT: YAML-file-based session backend for Dancer2
use Moo;
@@ -40,7 +40,7 @@ Dancer2::Session::YAML - YAML-file-based session backend for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 DESCRIPTION
diff --git a/lib/Dancer2/Template/Implementation/ForkedTiny.pm b/lib/Dancer2/Template/Implementation/ForkedTiny.pm
index fa0a52a9..667293b6 100644
--- a/lib/Dancer2/Template/Implementation/ForkedTiny.pm
+++ b/lib/Dancer2/Template/Implementation/ForkedTiny.pm
@@ -1,5 +1,5 @@
package Dancer2::Template::Implementation::ForkedTiny;
-$Dancer2::Template::Implementation::ForkedTiny::VERSION = '1.0.0';
+$Dancer2::Template::Implementation::ForkedTiny::VERSION = '1.1.0';
# ABSTRACT: Dancer2 own implementation of Template::Tiny
use 5.00503;
@@ -225,7 +225,7 @@ Dancer2::Template::Implementation::ForkedTiny - Dancer2 own implementation of Te
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Template/Simple.pm b/lib/Dancer2/Template/Simple.pm
index e3ff4e9f..1721c62f 100644
--- a/lib/Dancer2/Template/Simple.pm
+++ b/lib/Dancer2/Template/Simple.pm
@@ -1,6 +1,6 @@
package Dancer2::Template::Simple;
# ABSTRACT: Pure Perl 5 template engine for Dancer2
-$Dancer2::Template::Simple::VERSION = '1.0.0';
+$Dancer2::Template::Simple::VERSION = '1.1.0';
use Moo;
use Dancer2::FileUtils 'read_file_content';
use Ref::Util qw<is_arrayref is_coderef is_plain_hashref>;
@@ -155,7 +155,7 @@ Dancer2::Template::Simple - Pure Perl 5 template engine for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Template/TemplateToolkit.pm b/lib/Dancer2/Template/TemplateToolkit.pm
index d67f2d59..dca37908 100644
--- a/lib/Dancer2/Template/TemplateToolkit.pm
+++ b/lib/Dancer2/Template/TemplateToolkit.pm
@@ -1,7 +1,7 @@
# ABSTRACT: Template toolkit engine for Dancer2
package Dancer2::Template::TemplateToolkit;
-$Dancer2::Template::TemplateToolkit::VERSION = '1.0.0';
+$Dancer2::Template::TemplateToolkit::VERSION = '1.1.0';
use Moo;
use Carp qw<croak>;
use Dancer2::Core::Types;
@@ -101,7 +101,7 @@ Dancer2::Template::TemplateToolkit - Template toolkit engine for Dancer2
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Template/Tiny.pm b/lib/Dancer2/Template/Tiny.pm
index a975905b..1075982f 100644
--- a/lib/Dancer2/Template/Tiny.pm
+++ b/lib/Dancer2/Template/Tiny.pm
@@ -1,6 +1,6 @@
package Dancer2::Template::Tiny;
# ABSTRACT: Template::Tiny engine for Dancer2
-$Dancer2::Template::Tiny::VERSION = '1.0.0';
+$Dancer2::Template::Tiny::VERSION = '1.1.0';
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 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Test.pm b/lib/Dancer2/Test.pm
index 530d9680..f2b9aa1a 100644
--- a/lib/Dancer2/Test.pm
+++ b/lib/Dancer2/Test.pm
@@ -1,6 +1,6 @@
package Dancer2::Test;
# ABSTRACT: Useful routines for testing Dancer2 apps
-$Dancer2::Test::VERSION = '1.0.0';
+$Dancer2::Test::VERSION = '1.1.0';
use strict;
use warnings;
@@ -629,7 +629,7 @@ Dancer2::Test - Useful routines for testing Dancer2 apps
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/lib/Dancer2/Tutorial.pod b/lib/Dancer2/Tutorial.pod
index 0d4141dc..a4b7e8a2 100644
--- a/lib/Dancer2/Tutorial.pod
+++ b/lib/Dancer2/Tutorial.pod
@@ -13,7 +13,7 @@ Dancer2::Tutorial - An example to get you dancing
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 Tutorial Overview
diff --git a/script/dancer2 b/script/dancer2
index 581fa6ed..884823b3 100755
--- a/script/dancer2
+++ b/script/dancer2
@@ -20,7 +20,7 @@ dancer2 - Dancer2 command line interface
=head1 VERSION
-version 1.0.0
+version 1.1.0
=head1 SYNOPSIS
diff --git a/t/author-no-tabs.t b/t/author-no-tabs.t
index aace1db2..1123e22a 100644
--- a/t/author-no-tabs.t
+++ b/t/author-no-tabs.t
@@ -176,6 +176,8 @@ my @files = (
't/dsl/send_file.t',
't/dsl/splat.t',
't/dsl/to_app.t',
+ 't/dsl/uri_for.t',
+ 't/dsl/uri_for_route.t',
't/dsl/yaml.t',
't/engine.t',
't/error.t',
@@ -276,6 +278,7 @@ my @files = (
't/multiapp_template_hooks.t',
't/multipart_content.t',
't/named_apps.t',
+ 't/named_routes.t',
't/no_default_middleware.t',
't/plugin2/app_dsl_cb/app_dsl_cb.t',
't/plugin2/app_dsl_cb/lib/App.pm',
@@ -370,7 +373,6 @@ my @files = (
't/template_tiny/samples/09_trim.var',
't/time.t',
't/types.t',
- 't/uri_for.t',
't/vars.t',
't/views/auto_page.tt',
't/views/beforetemplate.tt',
diff --git a/t/dsl/uri_for.t b/t/dsl/uri_for.t
new file mode 100644
index 00000000..7712ce5c
--- /dev/null
+++ b/t/dsl/uri_for.t
@@ -0,0 +1,48 @@
+use strict;
+use warnings;
+use Test::More 'tests' => 2;
+use Plack::Test;
+use Plack::Builder;
+use HTTP::Request::Common;
+
+{
+ package App;
+ use Dancer2;
+ get '/' => sub { return uri_for('/foo'); };
+}
+
+{
+ package MountedApp;
+ use Dancer2;
+ get '/' => sub { return uri_for('/bar'); };
+}
+
+my $prefix = 'http://localhost';
+
+subtest 'Non-mounted app' => sub {
+ my $app = Plack::Test->create( App->to_app );
+ my $res;
+
+ $res = $app->request( GET "$prefix/" );
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, "$prefix/foo", 'Correct regular path' );
+};
+
+subtest 'Mounted app' => sub {
+ my $app = Plack::Test->create(
+ builder {
+ mount '/mount' => MountedApp->to_app;
+ mount '/' => App->to_app;
+ }
+ );
+
+ my $res;
+
+ $res = $app->request( GET "$prefix/" );
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, "$prefix/foo", 'Correct mounted regular path' );
+
+ $res = $app->request( GET "$prefix/mount" );
+ ok( $res->is_success, 'Successful request' );
+ is($res->content, "$prefix/mount/bar", 'Correct mounted regular path');
+};
diff --git a/t/dsl/uri_for_route.t b/t/dsl/uri_for_route.t
new file mode 100644
index 00000000..c327b884
--- /dev/null
+++ b/t/dsl/uri_for_route.t
@@ -0,0 +1,246 @@
+use strict;
+use warnings;
+use Test::More 'tests' => 3;
+use Plack::Test;
+use Plack::Builder;
+use HTTP::Request::Common;
+use JSON::MaybeXS;
+
+{
+ package App;
+ use Dancer2;
+ our $tested;
+
+ # Static with route params
+ # Static with code
+ # Static with options and code
+ get 'view_entry_static1' => '/view1/:id' => sub {1};
+ get 'view_entry_static2' => '/view2/:id' => { 'user_agent' => 'UA/1.0' }, sub {1};
+
+ # static with typed route param
+ get 'view_user' => '/:prefix/user/:username[Str]' => sub {1};
+
+ # splat / megasplat
+ get 'view_entry_splat' => '/viewsplat/*/*/**' => sub {1};
+
+ # Mixed with splat/megasplat
+ # Different method
+ patch 'view_entry_mixed' => '/view_mixed/*/**/:id' => sub {1};
+
+ # Regexp - fails
+ get 'view_entry_regexp1' => qr{/rview1/[0-9]+} => sub {1};
+
+ post '/uri_for_route' => sub {
+ my $params = JSON::MaybeXS::decode_json( request->content );
+ return uri_for_route(
+ $params->{'route_name'},
+ $params->{'route_params'},
+ $params->{'query_params'} // {},
+ !!$params->{'dont_escape'},
+ );
+ };
+
+ get '/fail_uri_for_route' => sub {
+ my $failed = 0;
+ eval {
+ uri_for_route('vvv');
+ 1;
+ } or do {
+ ::like(
+ $@,
+ qr/\QCannot find route named 'vvv'\E/xms,
+ 'Cannot retrieve nonexistent route',
+ );
+
+ $failed++;
+ };
+
+ return $failed;
+ };
+
+ get '/fail_uri_for_route_splat_args' => sub {
+ my $failed = 0;
+ eval {
+ uri_for_route(
+ 'view_entry_splat',
+ ['foo'],
+ );
+
+ 1;
+ } or do {
+ ::like(
+ $@,
+ qr/\QMismatch in amount of splat args and splat elements\E/xms,
+ 'Cannot handle mismatched splat args and elements',
+ );
+
+ $failed++;
+ };
+
+ return $failed;
+ };
+
+ get '/fail_uri_for_route_leftovers' => sub {
+ my $failed = 0;
+ eval {
+ uri_for_route('view_entry_static1');
+ 1;
+ } or do {
+ my $msg = 'Route view_entry_static1 uses the parameter \'id\', '
+ . 'which was not provided';
+
+ ::like(
+ $@,
+ qr/\Q$msg\E/xms,
+ 'Cannot handle leftover route parameters',
+ );
+
+ $failed++;
+ };
+
+ return $failed;
+ };
+
+ # Error defining two routes with the same name, regardless of method
+ eval {
+ get 'view_entry_splat' => '/' => sub {1};
+ 1;
+ } or do {
+ ::like(
+ $@,
+ qr/\QRoute with this name (view_entry_splat) already exists\E/xms,
+ 'Cannot register two routes with same name',
+ );
+
+ $tested = 1;
+ };
+}
+
+sub test_app {
+ my ( $app, $mount_path ) = @_;
+
+ my $prefix = 'http://localhost';
+ $mount_path
+ and $prefix .= $mount_path;
+
+ my ( $path, $res );
+
+ # Test static paths
+ foreach my $idx ( 1 .. 2 ) {
+ $res = $app->request(
+ POST(
+ "$prefix/uri_for_route",
+ 'Content' => JSON::MaybeXS::encode_json({
+ 'route_name' => "view_entry_static$idx",
+ 'route_params' => { 'id' => $idx },
+ 'query_params' => { 'foo' => $idx },
+ }),
+ )
+ );
+
+ $path = "$prefix/view$idx/$idx?foo=$idx";
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, $path, "Correct path: $path" );
+ }
+
+ # Test splat + megasplat
+ $res = $app->request(
+ POST(
+ "$prefix/uri_for_route",
+ 'Content' => JSON::MaybeXS::encode_json({
+ 'route_name' => 'view_entry_splat',
+ 'route_params' => [ 'foo', 'bar', [ 'baz', 'quux' ] ],
+ 'query_params' => { 'id' => 'di' },
+ }),
+ )
+ );
+
+ $path = "$prefix/viewsplat/foo/bar/baz/quux?id=di";
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, $path, "Correct path: $path" );
+
+ # Test mixed
+ $res = $app->request(
+ POST(
+ "$prefix/uri_for_route",
+ 'Content' => JSON::MaybeXS::encode_json(
+ { 'route_name' => 'view_entry_mixed',
+ 'route_params' => {
+ 'id' => 'di',
+ 'splat' => ['foo', ['bar', 'baz']]
+ },
+ 'query_params' => {'foo' => 'bar'},
+ }
+ ),
+ )
+ );
+
+ $path = "$prefix/view_mixed/foo/bar/baz/di?foo=bar";
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, $path, "Correct path: $path" );
+
+ # Test escaping
+ $res = $app->request(
+ POST(
+ "$prefix/uri_for_route",
+ 'Content' => JSON::MaybeXS::encode_json({
+ 'route_name' => 'view_entry_static1',
+ 'route_params' => { 'id' => '!@£$%' },
+ }),
+ )
+ );
+
+ $path = "$prefix/view1/!@%C3%82%C2%A3\$%";
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, $path, "Correct path: $path" );
+
+ # Test nonexistent route name
+ $res = $app->request( GET "$prefix/fail_uri_for_route" );
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, '1', 'Successfully tested nonexistent failure mode' );
+
+ # Test splat + megasplat (incorrect amount)
+ $res = $app->request( GET "$prefix/fail_uri_for_route_splat_args" );
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, '1', 'Successfully tested mismatch splat args/elements failure mode' );
+
+ # Test mixed with not all filled (named args left)
+ $res = $app->request( GET "$prefix/fail_uri_for_route_leftovers" );
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, '1', 'Successfully tested leftover args failure mode' );
+
+ # Static with typed route parameters
+ $res = $app->request(
+ POST(
+ "$prefix/uri_for_route",
+ 'Content' => JSON::MaybeXS::encode_json({
+ 'route_name' => 'view_user',
+ 'route_params' => { 'prefix' => 'foo', 'username' => 'sawyer' },
+ 'query_params' => { 'foo' => 1 },
+ }),
+ )
+ );
+
+ $path = "$prefix/foo/user/sawyer?foo=1";
+ ok( $res->is_success, 'Successful request' );
+ is( $res->content, $path, "Correct path for typed route param: $path" );
+}
+
+subtest 'Non-mounted app' => sub {
+ my $app = Plack::Test->create( App->to_app );
+ test_app($app);
+ ok( $App::tested, 'Check for duplicate route names done successfully' );
+};
+
+subtest 'Mounted app' => sub {
+ my $app = Plack::Test->create(
+ builder {
+ mount '/mount' => App->to_app;
+ mount '/' => sub {
+ return { Plack::Response->new(200, [], ['OK'] ) }
+ },
+ }
+ );
+
+ test_app( $app, '/mount' );
+};
diff --git a/t/named_routes.t b/t/named_routes.t
new file mode 100644
index 00000000..4e933ad1
--- /dev/null
+++ b/t/named_routes.t
@@ -0,0 +1,90 @@
+use strict;
+use warnings;
+use Test::More 'tests' => 5;
+use Plack::Test;
+use HTTP::Request::Common;
+
+{
+ package MyApp;
+
+ use Dancer2;
+
+ # Name, Regexp, Code
+ get 'view_static', '/view' => sub {
+ 'View Static';
+ };
+
+ get 'view_regex', qr{^/view_r$} => sub {
+ 'View Regex'
+ };
+
+ # Name, Regexp, Options, Code
+ get 'base_static', '/' => { 'user_agent' => 'XX' }, sub {
+ 'Base Static';
+ };
+
+ # Name, Regexp, Options, Code
+ get 'base_regex', qr{^/r$}, {}, sub {
+ 'Base Regex';
+ };
+
+ get '/ignore1' => sub {1};
+ get '/ignore2' => sub {1};
+ get '/ignore3' => sub {1};
+}
+
+my $test = Plack::Test->create( MyApp->to_app );
+
+subtest 'Named static route' => sub {
+ plan 'tests' => 2;
+
+ my $response = $test->request( GET '/view' );
+ ok( $response->is_success, 'Successfully reached /view' );
+ is( $response->content, 'View Static', 'Static route with name' );
+};
+
+subtest 'Named regex route' => sub {
+ plan 'tests' => 2;
+
+ my $response = $test->request( GET '/view_r' );
+ ok( $response->is_success, 'Successfully reached /view_r' );
+ is( $response->content, 'View Regex', 'Regex route with name' );
+};
+
+subtest 'Named static route with options' => sub {
+ plan 'tests' => 2;
+
+ my $response = $test->request( GET '/', 'User-Agent' => 'XX' );
+ ok( $response->is_success, 'Successfully reached /' );
+ is($response->content, 'Base Static',
+ 'Static route with name and options');
+};
+
+subtest 'Named regex route with options' => sub {
+ plan 'tests' => 2;
+
+ my $response = $test->request( GET '/r', 'User-Agent' => 'XX' );
+ ok( $response->is_success, 'Successfully reached /r' );
+ is($response->content, 'Base Regex', 'Regex route with name and options');
+};
+
+subtest 'Route objects' => sub {
+ plan 'tests' => 3;
+
+ my @apps = @{ Dancer2::runner->apps };
+ is( scalar @apps, 1, 'Only one app exists' );
+
+ my %routes = %{ $apps[0]->route_names() };
+ is( scalar keys %routes, 4, 'Four named routes registered' );
+
+ is_deeply(
+ [ sort keys %routes ],
+ [
+ 'base_regex',
+ 'base_static',
+ 'view_regex',
+ 'view_static',
+ ],
+ 'All the right route names',
+ );
+};
diff --git a/t/uri_for.t b/t/uri_for.t
deleted file mode 100644
index 7eff3478..00000000
--- a/t/uri_for.t
+++ /dev/null
@@ -1,30 +0,0 @@
-use strict;
-use warnings;
-use Test::More import => ['!pass'];
-use Plack::Test;
-use HTTP::Request::Common;
-use Ref::Util qw<is_coderef>;
-
-{
- package App;
- use Dancer2;
- get '/foo' => sub {
- return uri_for('/foo');
- };
-}
-
-my $app = App->to_app;
-ok( is_coderef($app), 'Got app' );
-
-test_psgi $app, sub {
- my $cb = shift;
-
- is( $cb->( GET '/foo' )->code, 200, '/foo code okay' );
- is(
- $cb->( GET '/foo' )->content,
- 'http://localhost/foo',
- 'uri_for works as expected',
- );
-};
-
-done_testing;