1Dancer2::Manual(3)    User Contributed Perl Documentation   Dancer2::Manual(3)
2
3
4

NAME

6       Dancer2::Manual - A gentle introduction to Dancer2
7

VERSION

9       version 0.400001
10

DESCRIPTION

12       Dancer2 is a free and open source web application framework written in
13       Perl.
14
15       It's a complete rewrite of Dancer, based on Moo and using a more robust
16       and extensible fully-OO design.
17
18       It's designed to be powerful and flexible, but also easy to use -
19       getting up and running with your web app is trivial, and an ecosystem
20       of adaptors for common template engines, session storage, logging
21       methods, serializers, and plugins to make common tasks easy means you
22       can do what you want to do, your way, easily.
23

INSTALL

25       Installation of Dancer2 is simple, using your favourite method to
26       install from CPAN, e.g.:
27
28           perl -MCPAN -e 'install Dancer2'
29
30       Thanks to the magic of cpanminus, if you do not have CPAN.pm
31       configured, or just want a quickfire way to get running, the following
32       should work, at least on Unix-like systems:
33
34           wget -O - http://cpanmin.us | sudo perl - Dancer2
35
36       (If you don't have root access, omit the 'sudo', and cpanminus will
37       install Dancer2 and prereqs into "~/perl5".)
38
39       Dancer2 is also available as a package from the package repository of
40       several distributions, for example on Debian/Ubuntu you should be able
41       to just:
42
43           apt-get install libdancer2-perl
44
45       Do be aware, though, that distribution-packaged versions sometimes lag
46       behind the most recent version on CPAN.
47

BOOTSTRAPPING A NEW APP

49       Create a web application using the dancer script:
50
51           $ dancer2 gen -a MyApp && cd MyApp
52           + MyApp
53           + MyApp/config.yml
54           + MyApp/Makefile.PL
55           + MyApp/MANIFEST.SKIP
56           + MyApp/.dancer
57           + MyApp/cpanfile
58           + MyApp/bin
59           + MyApp/bin/app.psgi
60           + MyApp/environments
61           + MyApp/environments/development.yml
62           + MyApp/environments/production.yml
63           + MyApp/lib
64           + MyApp/lib/MyApp.pm
65           + MyApp/public
66           + MyApp/public/favicon.ico
67           + MyApp/public/500.html
68           + MyApp/public/dispatch.cgi
69           + MyApp/public/404.html
70           + MyApp/public/dispatch.fcgi
71           + MyApp/public/css
72           + MyApp/public/css/error.css
73           + MyApp/public/css/style.css
74           + MyApp/public/images
75           + MyApp/public/images/perldancer.jpg
76           + MyApp/public/images/perldancer-bg.jpg
77           + MyApp/public/javascripts
78           + MyApp/public/javascripts/jquery.js
79           + MyApp/t
80           + MyApp/t/001_base.t
81           + MyApp/t/002_index_route.t
82           + MyApp/views
83           + MyApp/views/index.tt
84           + MyApp/views/layouts
85           + MyApp/views/layouts/main.tt
86
87       It creates a directory named after the name of the app, along with a
88       configuration file, a views directory (where your templates and layouts
89       will live), an environments directory (where environment-specific
90       settings live), a module containing the actual guts of your
91       application, and a script to start it. A default skeleton is used to
92       bootstrap the new application, but you can use the "-s" option to
93       provide another skeleton.  For example:
94
95           $ dancer2 gen -a MyApp -s ~/mydancerskel
96
97       For an example of a skeleton directory check the default one available
98       in the "share/" directory of your Dancer2 distribution.
99
100       (In what follows we will refer to the directory in which you have
101       created your Dancer2 application -- e.g., what "MyApp" was above -- as
102       the "appdir".)
103
104       Because Dancer2 is a PSGI web application framework, you can use the
105       "plackup" tool (provided by Plack) for launching the application:
106
107           plackup -p 5000 bin/app.psgi
108
109       View the web application at:
110
111           http://localhost:5000
112

USAGE

114       When Dancer2 is imported to a script, that script becomes a webapp, and
115       at this point, all the script has to do is declare a list of routes. A
116       route handler is composed by an HTTP method, a path pattern and a code
117       block. "strict", "warnings" and "utf8" pragmas are also imported with
118       Dancer2.
119
120       The code block given to the route handler has to return a string which
121       will be used as the content to render to the client.
122
123       Routes are defined for a given HTTP method. For each method supported,
124       a keyword is exported by the module.
125
126   HTTP Methods
127       Here are some of the standard HTTP methods which you can use to define
128       your route handlers.
129
130GET The GET method retrieves information, and is the most common
131
132           GET requests should be used for typical "fetch" requests -
133           retrieving information. They should not be used for requests which
134           change data on the server or have other effects.
135
136           When defining a route handler for the GET method, Dancer2
137           automatically defines a route handler for the HEAD method (in order
138           to honour HEAD requests for each of your GET route handlers).
139
140           To define a GET action, use the get keyword.
141
142POST The POST method is used to create a resource on the server.
143
144           To define a POST action, use the post keyword.
145
146PUT The PUT method is used to replace an existing resource.
147
148           To define a PUT action, use the put keyword.
149
150           a PUT request should replace the existing resource with that
151           specified - for instance - if you wanted to just update an email
152           address for a user, you'd have to specify all attributes of the
153           user again; to make a partial update, a PATCH request is used.
154
155PATCH The PATCH method updates some attributes of an existing
156           resource.
157
158           To define a PATCH action, use the patch keyword.
159
160DELETE The DELETE method requests that the origin server delete the
161           resource identified by the Request-URI.
162
163           To define a DELETE action, use the del keyword.
164
165       Handling multiple HTTP request methods
166
167       Routes can use "any" to match all, or a specified list of HTTP methods.
168
169       The following will match any HTTP request to the path "/myaction":
170
171           any '/myaction' => sub {
172               # code
173           }
174
175       The following will match GET or POST requests to "/myaction":
176
177           any ['get', 'post'] => '/myaction' => sub {
178               # code
179           };
180
181       For convenience, any route which matches GET requests will also match
182       HEAD requests.
183
184   Route Handlers
185       The route action is the code reference declared. It can access
186       parameters through the specific route_parameters, query_parameters, and
187       body_parameters keywords, which return a Hash::MultiValue object.  This
188       hashref is a merge of the route pattern matches and the request params.
189
190       You can find more details about how params are built and how to access
191       them in the Dancer2::Core::Request documentation.
192
193       Declaring Routes
194
195       To control what happens when a web request is received by your webapp,
196       you'll need to declare "routes". A route declaration indicates which
197       HTTP method(s) it is valid for, the path it matches (e.g. "/foo/bar"),
198       and a coderef to execute, which returns the response.
199
200           get '/hello/:name' => sub {
201               return "Hi there " . route_parameters->get('name');
202           };
203
204       The above route specifies that, for GET requests to "/hello/...", the
205       code block provided should be executed.
206
207       Retrieving request parameters
208
209       The query_parameters, route_parameters, and body_parameters keywords
210       provide a Hash::MultiValue result from the three different parameters.
211
212       Named matching
213
214       A route pattern can contain one or more tokens (a word prefixed with
215       ':').  Each token found in a route pattern is used as a named-pattern
216       match. Any match will be set in the route parameters.
217
218           get '/hello/:name' => sub {
219               return "Hey " . route_parameters->get('name') . ", welcome here!";
220           };
221
222       Tokens can be optional, for example:
223
224           get '/hello/:name?' => sub {
225               my $name = route_parameters->get('name') // 'Whoever you are';
226               return "Hello there, $name";
227           };
228
229       Named matching with type constraints
230
231       Type constraints can be added to tokens.
232
233           get '/user/:id[Int]' => sub {
234               # matches /user/34 but not /user/jamesdean
235               my $user_id = route_parameters->get('id');
236           };
237
238           get '/user/:username[Str]' => sub {
239               # matches /user/jamesdean but not /user/34 since that is caught
240               # by previous route
241               my $username = route_parameters->get('username');
242           };
243
244       You can even use type constraints to add a regexp check:
245
246           get '/book/:date[StrMatch[qr{\d\d\d\d-\d\d-\d\d}]]' => sub {
247               # matches /book/2014-02-04
248               my $date = route_parameters->get('date');
249           };
250
251       The default type library is Dancer2::Core::Types but any type library
252       built using Type::Tiny's Type::Library can be used instead.  If you'd
253       like to use a different default type library you must declare it in the
254       configuration file, for example:
255
256           type_library: My::Type::Library
257
258       Alternatively you can specify the type library in which the type is
259       defined as part of the route definition:
260
261           get '/user/:username[My::Type::Library::Username]' => sub {
262               my $username = route_parameters->get('username');
263           };
264
265       This will load "My::Type::Library" and from it use the type "Username".
266       This allows types to be used that are not part of the type library
267       defined by config's "type_library".
268
269       More complex constructs are allowed such as:
270
271           get '/some/:thing[Int|MyDate]' => sub {
272               ...;
273           };
274
275       See "lookup($name)" in Type::Registry for more details.
276
277       Wildcard Matching
278
279       A route can contain a wildcard (represented by a "*"). Each wildcard
280       match will be placed in a list, which the "splat" keyword returns.
281
282           get '/download/*.*' => sub {
283               my ($file, $ext) = splat;
284               # do something with $file.$ext here
285           };
286
287       An extensive, greedier wildcard represented by "**" (A.K.A.
288       "megasplat") can be used to define a route. The additional path is
289       broken down and returned as an arrayref:
290
291           get '/entry/*/tags/**' => sub {
292               my ( $entry_id, $tags ) = splat;
293               my @tags = @{$tags};
294           };
295
296       The "splat" keyword in the above example for the route
297       /entry/1/tags/one/two would set $entry_id to 1 and $tags to "['one',
298       'two']".
299
300       Mixed named and wildcard matching
301
302       A route can combine named (token) matching and wildcard matching.  This
303       is useful when chaining actions:
304
305           get '/team/:team/**' => sub {
306               var team => route_parameters->get('team');
307               pass;
308           };
309
310           prefix '/team/:team';
311
312           get '/player/*' => sub {
313               my ($player) = splat;
314
315               # etc...
316           };
317
318           get '/score' => sub {
319               return score_for( vars->{'team'} );
320           };
321
322       Regular Expression Matching
323
324       A route can be defined with a Perl regular expression.
325
326       In order to tell Dancer2 to consider the route as a real regexp, the
327       route must be defined explicitly with "qr{}", like the following:
328
329           get qr{/hello/([\w]+)} => sub {
330               my ($name) = splat;
331               return "Hello $name";
332           };
333
334       A route regex may use named capture groups. The "captures" keyword will
335       return a reference to a copy of "%+".
336
337       Conditional Matching
338
339       Routes may include some matching conditions (on content_type, agent,
340       user_agent, content_length and path_info):
341
342           get '/foo', {agent => 'Songbird (\d\.\d)[\d\/]*?'} => sub {
343             'foo method for songbird'
344           }
345
346           get '/foo' => sub {
347             'all browsers except songbird'
348           }
349
350   Prefix
351       A prefix can be defined for each route handler, like this:
352
353           prefix '/home';
354
355       From here, any route handler is defined to /home/*
356
357           get '/page1' => sub {}; # will match '/home/page1'
358
359       You can unset the prefix value
360
361           prefix '/'; # or: prefix undef;
362           get '/page1' => sub {}; # will match /page1
363
364       Alternatively, to prevent you from ever forgetting to undef the prefix,
365       you can use lexical prefix like this:
366
367           prefix '/home' => sub {
368             get '/page1' => sub {}; # will match '/home/page1'
369           }; ## prefix reset to previous value on exit
370
371           get '/page1' => sub {}; # will match /page1
372
373   Delayed responses (Async/Streaming)
374       Dancer2 can provide delayed (otherwise known as asynchronous) responses
375       using the "delayed" keyword. These responses are streamed, although you
376       can set the content all at once, if you prefer.
377
378           get '/status' => sub {
379               delayed {
380                   response_header 'X-Foo' => 'Bar';
381
382                   # flush headers (in case of streaming)
383                   flush;
384
385                   # send content to the user
386                   content 'Hello, world!';
387
388                   # you can write more content
389                   # all streaming
390                   content 'Hello, again!';
391
392                   # when done, close the connection
393                   done;
394
395                   # do whatever you want else, asynchronously
396                   # the user socket closed by now
397                   ...
398               };
399           };
400
401       If you are streaming (calling "content" several times), you must call
402       "flush" first. If you're sending only once, you don't need to call
403       "flush".
404
405       Here is an example of using delayed responses with AnyEvent:
406
407           use Dancer2;
408           use AnyEvent;
409
410           my %timers;
411           my $count = 5;
412           get '/drums' => sub {
413               delayed {
414                   print "Stretching...\n";
415                   flush; # necessary, since we're streaming
416
417                   $timers{'Snare'} = AE::timer 1, 1, delayed {
418                       $timers{'HiHat'} ||= AE::timer 0, 0.5, delayed {
419                           content "Tss...\n";
420                       };
421
422                       content "Bap!\n";
423
424                       if ( $count-- == 0 ) {
425                           %timers = ();
426                           content "Tugu tugu tugu dum!\n";
427                           done;
428
429                           print "<enter sound of applause>\n\n";
430                           $timers{'Applause'} = AE::timer 3, 0, sub {
431                               # the DSL will not available here
432                               # because we didn't call the "delayed" keyword
433                               print "<applause dies out>\n";
434                           };
435                       }
436                   };
437               };
438           };
439
440       If an error happens during a write operation, a warning will be issued
441       to the logger.
442
443       You can handle the error yourself by providing an "on_error" handler:
444
445           get '/' => sub {
446               delayed {
447                   flush;
448                   content "works";
449
450                   # ... user disconnected here ...
451
452                   content "fails";
453
454                   # ... error triggered ...
455
456                   done; # doesn't even get run
457               } on_error => sub {
458                   # delayed{} not needed, DSL already available
459                   my ($error) = @_;
460                   # do something with $error
461               };
462           };
463
464       Here is an example that asynchronously streams the contents of a CSV
465       file:
466
467           use Dancer2;
468           use Text::CSV_XS  qw< csv >;
469           use Path::Tiny    qw< path >;
470           use JSON::MaybeXS qw< encode_json >;
471           # Create CSV parser
472           my $csv = Text::CSV_XS->new({
473               binary    => 1,
474               auto_diag => 1,
475           });
476           get '/' => sub {
477               # delayed response:
478               delayed {
479                   # streaming content
480                   flush;
481                   # Read each row and stream it in JSON
482                   my $fh = path('filename.csv')->openr_utf8;
483                   while ( my $row = $csv->getline($fh) ) {
484                       content encode_json $row;
485                   }
486                   # close user connection
487                   done;
488               } on_error => sub {
489                   my ($error) = @_;
490                   warning 'Failed to stream to user: ' . request->remote_address;
491               };
492           };
493
494       NOTE: If you just want to send a file's contents asynchronously, use
495       send_file($filename) instead of "delayed", as it will automatically
496       take advantage of any asynchronous capability.
497
498   Action Skipping
499       An action can choose not to serve the current request and ask Dancer2
500       to process the request with the next matching route.
501
502       This is done with the pass keyword, like in the following example
503
504           get '/say/:word' => sub {
505               pass if route_parameters->get('word') =~ /^\d+$/;
506               "I say a word: " . route_parameters->get('word');
507           };
508
509           get '/say/:number' => sub {
510               "I say a number: " . route_parameters->get('number');
511           };
512

HOOKS

514       Hooks are code references (or anonymous subroutines) that are triggered
515       at specific moments during the resolution of a request.  They are set
516       up using the hook keyword.
517
518       Many of them are provided by Dancer2's core, but plugins and engines
519       can also define their own.
520
521       •   "before" hooks
522
523           "before" hooks are evaluated before each request within the context
524           of the request and receives as argument the app (a
525           Dancer2::Core::App object).
526
527           It's possible to define variables which will be accessible in the
528           action blocks with the var keyword.
529
530               hook before => sub {
531                   var note => 'Hi there';
532               };
533
534               get '/foo/*' => sub {
535                   my ($match) = splat; # 'oversee';
536                   vars->{note};        # 'Hi there'
537               };
538
539           For another example, this can be used along with session support to
540           easily give non-logged-in users a login page:
541
542               hook before => sub {
543                   if (!session('user') && request->path !~ m{^/login}) {
544                       # Pass the original path requested along to the handler:
545                       forward '/login', { requested_path => request->path };
546                   }
547               };
548
549           The request keyword returns the current Dancer2::Core::Request
550           object representing the incoming request.
551
552       •   "after" hooks
553
554           "after" hooks are evaluated after the response has been built by a
555           route handler, and can alter the response itself, just before it's
556           sent to the client.
557
558           This hook runs after a request has been processed, but before the
559           response is sent.
560
561           It receives a Dancer2::Core::Response object, which it can modify
562           if it needs to make changes to the response which is about to be
563           sent.
564
565           The hook can use other keywords in order to do whatever it wants.
566
567               hook after => sub {
568                   response->content(
569                       q{The "after" hook can alter the response's content here!}
570                   );
571               };
572
573   Templates
574       •   "before_template_render"
575
576           "before_template_render" hooks are called whenever a template is
577           going to be processed, they are passed the tokens hash which they
578           can alter.
579
580               hook before_template_render => sub {
581                   my $tokens = shift;
582                   $tokens->{foo} = 'bar';
583               };
584
585           The tokens hash will then be passed to the template with all the
586           modifications performed by the hook. This is a good way to setup
587           some global vars you like to have in all your templates, like the
588           name of the user logged in or a section name.
589
590       •   "after_template_render"
591
592           "after_template_render" hooks are called after the view has been
593           rendered.  They receive as their first argument the reference to
594           the content that has been produced. This can be used to post-
595           process the content rendered by the template engine.
596
597               hook after_template_render => sub {
598                   my $ref_content = shift;
599                   my $content     = ${$ref_content};
600
601                   # do something with $content
602                   ${$ref_content} = $content;
603               };
604
605       •   "before_layout_render"
606
607           "before_layout_render" hooks are called whenever the layout is
608           going to be applied to the current content. The arguments received
609           by the hook are the current tokens hashref and a reference to the
610           current content.
611
612               hook before_layout_render => sub {
613                   my ($tokens, $ref_content) = @_;
614                   $tokens->{new_stuff} = 42;
615                   $ref_content = \"new content";
616               };
617
618       •   "after_layout_render"
619
620           "after_layout_render" hooks are called once the complete content of
621           the view has been produced, after the layout has been applied to
622           the content.  The argument received by the hook is a reference to
623           the complete content string.
624
625               hook after_layout_render => sub {
626                   my $ref_content = shift;
627                   # do something with ${ $ref_content }, which reflects directly
628                   #   in the caller
629               };
630
631   Error Handling
632       Refer to Error Hooks for details about the following hooks:
633
634       •   "init_error"
635
636       •   "before_error"
637
638       •   "after_error"
639
640       •   "on_route_exception"
641
642   File Rendering
643       Refer to File Handler for details on the following hooks:
644
645       •   "before_file_render"
646
647       •   "after_file_render"
648
649   Serializers
650       •   "before_serializer" is called before serializing the content, and
651           receives the content to serialize as an argument.
652
653             hook before_serializer => sub {
654               my $content = shift;
655               ...
656             };
657
658       •   "after_serializer" is called after the payload has been serialized,
659           and receives the serialized content as an argument.
660
661             hook after_serializer => sub {
662               my $serialized_content = shift;
663               ...
664             };
665

HANDLERS

667   File Handler
668       Whenever a content is produced out of the parsing of a static file, the
669       Dancer2::Handler::File component is used. This component provides two
670       hooks, "before_file_render" and "after_file_render".
671
672       "before_file_render" hooks are called just before starting to parse the
673       file, the hook receives as its first argument the file path that is
674       going to be processed.
675
676           hook before_file_render => sub {
677               my $path = shift;
678           };
679
680       "after_file_render" hooks are called after the file has been parsed and
681       the response content produced. It receives the response object
682       (Dancer2::Core::Response) produced.
683
684           hook after_file_render => sub {
685              my $response = shift;
686           };
687
688   Auto page
689       Whenever a page that matches an existing template needs to be served,
690       the Dancer2::Handler::AutoPage component is used.
691
692   Writing your own
693       A route handler is a class that consumes the
694       Dancer2::Core::Role::Handler role. The class must implement a set of
695       methods: "methods", "regexp" and "code" which will be used to declare
696       the route.
697
698       Let's look at Dancer2::Handler::AutoPage for example.
699
700       First, the matching methods are "get" and "head":
701
702           sub methods { qw(head get) }
703
704       Then, the "regexp" or the path we want to match:
705
706           sub regexp { '/:page' }
707
708       Anything will be matched by this route, since we want to check if
709       there's a view named with the value of the "page" token. If not, the
710       route needs to "pass", letting the dispatching flow to proceed further.
711
712           sub code {
713               sub {
714                   my $app = shift;
715                   my $prefix = shift;
716
717                   my $template = $app->template_engine;
718                   if ( !defined $template ) {
719                       $app->response->has_passed(1);
720                       return;
721                   }
722
723                   my $page       = $app->request->path;
724                   my $layout_dir = $template->layout_dir;
725                   if ( $page =~ m{^/\Q$layout_dir\E/} ) {
726                       $app->response->has_passed(1);
727                       return;
728                   }
729
730                   # remove leading '/', ensuring paths relative to the view
731                   $page =~ s{^/}{};
732                   my $view_path = $template->view_pathname($page);
733
734                   if ( ! $template->pathname_exists( $view_path ) ) {
735                       $app->response->has_passed(1);
736                       return;
737                   }
738
739                   my $ct = $template->process( $page );
740                   return ( $app->request->method eq 'GET' ) ? $ct : '';
741               };
742           }
743
744       The "code" method passed the Dancer2::Core::App object which provides
745       access to anything needed to process the request.
746
747       A "register" is then implemented to add the route to the registry and
748       if the "auto_page setting" is off, it does nothing.
749
750           sub register {
751               my ($self, $app) = @_;
752
753               return unless $app->config->{auto_page};
754
755               $app->add_route(
756                   method => $_,
757                   regexp => $self->regexp,
758                   code   => $self->code,
759               ) for $self->methods;
760           }
761
762       The config parser looks for a "route_handlers" section and any handler
763       defined there is loaded. Thus, any random handler can be added to your
764       app.  For example, the default config file for any Dancer2 application
765       is as follows:
766
767           route_handlers:
768             File:
769               public_dir: /path/to/public
770             AutoPage: 1
771

ERRORS

773   Error Pages
774       When an HTTP error occurs (i.e. the action responds with a status code
775       other than 200), this is how Dancer2 determines what page to display.
776
777       •   Looks in the "views/" directory for a corresponding template file
778           matching the error code (e.g. "500.tt" or "404.tt"). If such a file
779           exists, it's used to report the error.
780
781       •   Next, looks in the "public/" directory for a corresponding HTML
782           file matching the error code (e.g. "500.html" or "404.html"). If
783           such a file exists, it's used to report the error. (Note, however,
784           that if show_stacktrace is set to true, in the case of a 500 error
785           the static HTML page will not be shown, but will be replaced with a
786           default error page containing more informative diagnostics. For
787           more information see Dancer2::Config.)
788
789           (In older versions, show_errors was used instead of
790           show_stacktrace.  Both are supported, but show_errors is
791           deprecated.)
792
793       •   As default, render a generic error page on the fly.
794
795   Execution Errors
796       When an error occurs during the route execution, Dancer2 will render an
797       error page with the HTTP status code 500.
798
799       It's possible either to display the content of the error message or to
800       hide it with a generic error page. This is a choice left to the end-
801       user and can be controlled with the show_stacktrace setting (see
802       above).
803
804   Error Hooks
805       When an error is caught by Dancer2's core, an exception object is built
806       (of the class Dancer2::Core::Error). This class provides a hook to let
807       the user alter the error workflow if needed.
808
809       "init_error" hooks are called whenever an error object is built, the
810       object is passed to the hook.
811
812           hook init_error => sub {
813               my $error = shift;
814               # do something with $error
815           };
816
817       This hook was named before_error_init in Dancer, both names currently
818       are synonyms for backward-compatibility.
819
820       "before_error" hooks are called whenever an error is going to be
821       thrown, it receives the error object as its sole argument.
822
823           hook before_error => sub {
824               my $error = shift;
825               # do something with $error
826           };
827
828       This hook was named before_error_render in Dancer, both names currently
829       are synonyms for backward-compatibility.
830
831       "after_error" hooks are called whenever an error object has been
832       thrown, it receives a Dancer2::Core::Response object as its sole
833       argument.
834
835           hook after_error => sub {
836               my $response = shift;
837           };
838
839       This hook was named after_error_render in Dancer, both names currently
840       are synonyms for backward-compatibility.
841
842       "on_route_exception" is called when an exception has been caught, at
843       the route level, just before rethrowing it higher. This hook receives a
844       Dancer2::Core::App and the error as arguments.
845
846         hook on_route_exception => sub {
847           my ($app, $error) = @_;
848         };
849

SESSIONS

851   Handling sessions
852       It's common to want to use sessions to give your web applications
853       state; for instance, allowing a user to log in, creating a session, and
854       checking that session on subsequent requests.
855
856       By default Dancer 2 has Simple sessions enabled.  It implements a very
857       simple in-memory session storage. This will be fast and useful for
858       testing, but such sessions will not persist between restarts of your
859       app.
860
861       If you'd like to use a different session engine you must declare it in
862       the configuration file.
863
864       For example to use YAML file base sessions you need to add the
865       following to your config.yml:
866
867           session: YAML
868
869       Or, to enable session support from within your code,
870
871           set session => 'YAML';
872
873       (However, controlling settings is best done from your config file.)
874
875       The Dancer2::Session::YAML backend implements a file-based YAML session
876       storage to help with debugging, but shouldn't be used on production
877       systems.
878
879       There are other session backends, such as Dancer2::Session::Memcached,
880       which are recommended for production use.
881
882       You can then use the session keyword to manipulate the session:
883
884       Storing data in the session
885
886       Storing data in the session is as easy as:
887
888           session varname => 'value';
889
890       Retrieving data from the session
891
892       Retrieving data from the session is as easy as:
893
894           session('varname')
895
896       Or, alternatively,
897
898           session->read("varname")
899
900       Controlling where sessions are stored
901
902       For disc-based session backends like Dancer2::Session::YAML, session
903       files are written to the session dir specified by the "session_dir"
904       setting, which defaults to "./sessions" if not specifically set.
905
906       If you need to control where session files are created, you can do so
907       quickly and easily within your config file, for example:
908
909           session: YAML
910           engines:
911             session:
912               YAML:
913                 session_dir: /tmp/dancer-sessions
914
915       If the directory you specify does not exist, Dancer2 will attempt to
916       create it for you.
917
918       Changing session ID
919
920       If you wish to change the session ID (for example on privilege level
921       change):
922
923           my $new_session_id = app->change_session_id
924
925       Destroying a session
926
927       When you're done with your session, you can destroy it:
928
929           app->destroy_session
930
931   Sessions and logging in
932       A common requirement is to check the user is logged in, and, if not,
933       require them to log in before continuing.
934
935       This can easily be handled using a before hook to check their session:
936
937           use Dancer2;
938           set session => "Simple";
939
940           hook before => sub {
941               if (!session('user') && request->path !~ m{^/login}) {
942                   forward '/login', { requested_path => request->path };
943               }
944           };
945
946           get '/' => sub { return "Home Page"; };
947
948           get '/secret' => sub { return "Top Secret Stuff here"; };
949
950           get '/login' => sub {
951               # Display a login page; the original URL they requested is available as
952               # query_parameters->get('requested_path'), so could be put in a hidden field in the form
953               template 'login', { path => query_parameters->get('requested_path') };
954           };
955
956           post '/login' => sub {
957               # Validate the username and password they supplied
958               if (body_parameters->get('user') eq 'bob' && body_parameters->get('pass') eq 'letmein') {
959                   session user => body_parameters->get('user');
960                   redirect body_parameters->get('path') || '/';
961               } else {
962                   redirect '/login?failed=1';
963               }
964           };
965
966           dance();
967
968       Here is what the corresponding "login.tt" file should look like. You
969       should place it in a directory called "views/":
970
971           <html>
972             <head>
973               <title>Session and logging in</title>
974             </head>
975             <body>
976               <form action='/login' method='POST'>
977                   User Name : <input type='text' name='user'/>
978                   Password: <input type='password' name='pass' />
979
980                   <!-- Put the original path requested into a hidden
981                              field so it's sent back in the POST and can be
982                              used to redirect to the right page after login -->
983                   <input type='hidden' name='path' value='<% path %>'/>
984
985                   <input type='submit' value='Login' />
986               </form>
987             </body>
988           </html>
989
990       Of course, you'll probably want to validate your users against a
991       database table, or maybe via IMAP/LDAP/SSH/POP3/local system accounts
992       via PAM etc.  Authen::Simple is probably a good starting point here!
993
994       A simple working example of handling authentication against a database
995       table yourself (using Dancer2::Plugin::Database which provides the
996       "database" keyword, and Crypt::SaltedHash to handle salted hashed
997       passwords (well, you wouldn't store your users passwords in the clear,
998       would you?)) follows:
999
1000           post '/login' => sub {
1001               my $user_value = body_parameters->get('user');
1002               my $pass_value = body_parameters->get('pass');
1003
1004               my $user = database->quick_select('users',
1005                   { username => $user_value }
1006               );
1007               if (!$user) {
1008                   warning "Failed login for unrecognised user $user_value";
1009                   redirect '/login?failed=1';
1010               } else {
1011                   if (Crypt::SaltedHash->validate($user->{password}, $pass_value))
1012                   {
1013                       debug "Password correct";
1014                       # Logged in successfully
1015                       session user => $user;
1016                       redirect body_parameters->get('path') || '/';
1017                   } else {
1018                       debug("Login failed - password incorrect for " . $user_value);
1019                       redirect '/login?failed=1';
1020                   }
1021               }
1022           };
1023
1024       Retrieve complete hash stored in session
1025
1026       Get complete hash stored in session:
1027
1028           my $hash = session;
1029
1030   Writing a session engine
1031       In Dancer 2, a session backend consumes the role
1032       Dancer2::Core::Role::SessionFactory.
1033
1034       The following example using the Redis session demonstrates how session
1035       engines are written in Dancer 2.
1036
1037       First thing to do is to create the class for the session engine, we'll
1038       name it "Dancer2::Session::Redis":
1039
1040            package Dancer2::Session::Redis;
1041            use Moo;
1042            with 'Dancer2::Core::Role::SessionFactory';
1043
1044       we want our backend to have a handle over a Redis connection.  To do
1045       that, we'll create an attribute "redis"
1046
1047            use JSON;
1048            use Redis;
1049            use Dancer2::Core::Types; # brings helper for types
1050
1051            has redis => (
1052                is => 'rw',
1053                isa => InstanceOf['Redis'],
1054                lazy => 1,
1055                builder => '_build_redis',
1056            );
1057
1058       The lazy attribute says to Moo that this attribute will be built
1059       (initialized) only when called the first time. It means that the
1060       connection to Redis won't be opened until necessary.
1061
1062            sub _build_redis {
1063                my ($self) = @_;
1064                Redis->new(
1065                    server => $self->server,
1066                    password => $self->password,
1067                    encoding => undef,
1068                );
1069            }
1070
1071       Two more attributes, "server" and "password" need to be created.  We do
1072       this by defining them in the config file. Dancer2 passes anything
1073       defined in the config to the engine creation.
1074
1075            # config.yml
1076            ...
1077            engines:
1078              session:
1079                Redis:
1080                  server: foo.mydomain.com
1081                  password: S3Cr3t
1082
1083       The server and password entries are now passed to the constructor of
1084       the Redis session engine and can be accessed from there.
1085
1086            has server => (is => 'ro', required => 1);
1087            has password => (is => 'ro');
1088
1089       Next, we define the subroutine "_retrieve" which will return a session
1090       object for a session ID it has passed. Since in this case, sessions are
1091       going to be stored in Redis, the session ID will be the key, the
1092       session the value.  So retrieving is as easy as doing a get and
1093       decoding the JSON string returned:
1094
1095            sub _retrieve {
1096                my ($self, $session_id) = @_;
1097                my $json = $self->redis->get($session_id);
1098                my $hash = from_json( $json );
1099                return bless $hash, 'Dancer2::Core::Session';
1100            }
1101
1102       The "_flush" method is called by Dancer when the session needs to be
1103       stored in the backend. That is actually a write to Redis. The method
1104       receives a "Dancer2::Core::Session" object and is supposed to store it.
1105
1106            sub _flush {
1107                my ($self, $session) = @_;
1108                my $json = encode_json( { %{ $session } } );
1109                $self->redis->set($session->id, $json);
1110            }
1111
1112       For the "_destroy" method which is supposed to remove a session from
1113       the backend, deleting the key from Redis is enough.
1114
1115            sub _destroy {
1116                my ($self, $session_id) = @_;
1117                $self->redis->del($session_id);
1118            }
1119
1120       The "_sessions" method which is supposed to list all the session IDs
1121       currently stored in the backend is done by listing all the keys that
1122       Redis has.
1123
1124            sub _sessions {
1125                my ($self) = @_;
1126                my @keys = $self->redis->keys('*');
1127                return \@keys;
1128            }
1129
1130       The session engine is now ready.
1131
1132       The Session keyword
1133
1134       Dancer2 maintains two session layers.
1135
1136       The first layer, Dancer2::Core::Session provides a session object which
1137       represents the current session. You can read from it as many times as
1138       you want, and write to it as many times as you want.
1139
1140       The second layer is the session engine (Dancer2::Session::Simple is one
1141       example), which is used in order to implement the reading and writing
1142       from the actual storage. This is read only once, when a request comes
1143       in (using a cookie whose value is "dancer.session" by default).  At the
1144       end of a request, all the data you've written will be flushed to the
1145       engine itself, which will do the actual write to the storage (whether
1146       it's in a hash in memory, in Memcache, or in a database).
1147

TEMPLATES

1149       Returning plain content is all well and good for examples or trivial
1150       apps, but soon you'll want to use templates to maintain separation
1151       between your code and your content. Dancer2 makes this easy.
1152
1153       Your route handlers can use the template keyword to render templates.
1154
1155   Views
1156       In Dancer2, a file which holds a template is called a view.  Views are
1157       located in the "appdir/views" directory.
1158
1159       You can change this location by changing the setting 'views'. For
1160       instance if your templates are located in the 'templates' directory, do
1161       the following:
1162
1163           set views => path( app->location , 'templates' );
1164
1165       By default, the internal template engine Dancer2::Template::Simple is
1166       used, but you may want to upgrade to Template Toolkit
1167       <http://www.template-toolkit.org/>. If you do so, you have to enable
1168       this engine in your settings as explained in
1169       Dancer2::Template::TemplateToolkit and you'll also have to install the
1170       Template module.
1171
1172       In order to render a view, just call the template keyword at the end of
1173       the action by giving the view name and the HASHREF of tokens to
1174       interpolate in the view (note that for convenience, the request,
1175       session, params and vars are automatically accessible in the view,
1176       named "request", "session", "params", and "vars") - for example:
1177
1178           hook before => sub { var time => scalar(localtime) };
1179
1180           get '/hello/:name' => sub {
1181               my $name = route_parameters->get('name');
1182               template 'hello.tt', { name => $name };
1183           };
1184
1185       The template "hello.tt" could contain, for example:
1186
1187           <p>Hi there, [% name %]!</p>
1188           <p>You're using [% request.user_agent %]</p>
1189           [% IF session.username %]
1190               <p>You're logged in as [% session.username %]</p>
1191           [% END %]
1192           It's currently [% vars.time %]
1193
1194       For a full list of the tokens automatically added to your template
1195       (like "session", "request", and "vars", refer to
1196       Dancer2::Core::Role::Template).
1197
1198       By default, views use a .tt extension. This can be overridden by
1199       setting the "extension" attribute in the template engine configuration:
1200
1201           set engines => {
1202               template => {
1203                   template_toolkit => {
1204                       extension => 'foo',
1205                   },
1206               },
1207           };
1208
1209   Layouts
1210       A layout is a special view, located in the layouts directory (inside
1211       the views directory) which must have a token named "content". That
1212       token marks the place where to render the action view. This lets you
1213       define a global layout for your actions, and have each individual view
1214       contain only specific content. This is a good thing and helps avoid
1215       lots of needless duplication of HTML. :)
1216
1217       For example, the layout views/layouts/main.tt:
1218
1219           <html>
1220               <head>...</head>
1221               <body>
1222               <div id="header">
1223               ...
1224               </div>
1225
1226               <div id="content">
1227               [% content %]
1228               </div>
1229
1230               </body>
1231           </html>
1232
1233       You can tell your app which layout to use with "layout: name" in the
1234       config file, or within your code:
1235
1236           set layout => 'main';
1237
1238       You can control which layout to use (or whether to use a layout at all)
1239       for a specific request without altering the layout setting by passing
1240       an options hashref as the third param to the template keyword:
1241
1242           template 'index.tt', {}, { layout => undef };
1243
1244       If your application is not mounted under root ("/"), you can use a
1245       "before_template_render" hook instead of hardcoding the path into your
1246       application for your CSS, images and JavaScript:
1247
1248           hook before_template_render => sub {
1249               my $tokens = shift;
1250               $tokens->{uri_base} = request->base->path;
1251           };
1252
1253       Then in your layout, modify your CSS inclusion as follows:
1254
1255           <link rel="stylesheet" href="[% uri_base %]/css/style.css" />
1256
1257       From now on you can mount your application wherever you want, without
1258       any further modification of the CSS inclusion.
1259
1260   Encoding
1261       If you use Plack and have a Unicode problem with your Dancer2
1262       application, don't forget to check if you have set your template engine
1263       to use Unicode, and set the default charset to UTF-8. So, if you are
1264       using template toolkit, your config file will look like this:
1265
1266           charset: UTF-8
1267           engines:
1268             template:
1269               template_toolkit:
1270                 ENCODING: utf8
1271
1272   Default Template Variables
1273       Every template knows about the following variables, which are provided
1274       by Dancer2::Core::Role::Template. Some are similar to the keywords you
1275       can use in the Perl part of your Dancer2 application.
1276
1277perl_version
1278
1279           Current version of perl, effectively $^V
1280           <http://perldoc.perl.org/perlvar.html#%24%5eV>.
1281
1282dancer_version
1283
1284           Current version of Dancer2, effectively "Dancer2->VERSION".
1285
1286settings
1287
1288           A hash of the application configuration. This is like the config
1289           keyword.
1290
1291request
1292
1293           The current request object. This is like the request keyword.
1294
1295params
1296
1297           A hash reference of all the parameters.
1298
1299           Currently the equivalent of "$request->params", and like the params
1300           keyword.
1301
1302vars
1303
1304           The list of request variables, which is what you would get if you
1305           called the vars keyword.
1306
1307session
1308
1309           The current session data, if a session exists. This is like the
1310           session keyword.
1311

STATIC FILES

1313   Static Directory
1314       Static files are served from the ./public directory. You can specify a
1315       different location by setting the "public_dir" option:
1316
1317           set public_dir => path( app->location , 'static' );
1318
1319       When you modify default public_dir you have to set "static_handler"
1320       option.
1321
1322           set static_handler => true;
1323
1324       Note that the public directory name is not included in the URL. A file
1325       ./public/css/style.css is made available as
1326       <http://example.com/css/style.css>.
1327
1328   Static File from a Route Handler
1329       It's possible for a route handler to send a static file, as follows:
1330
1331           get '/download/*' => sub {
1332               my ($file) = splat;
1333
1334               send_file $file;
1335           };
1336
1337       Or even if you want your index page to be a plain old index.html file,
1338       just do:
1339
1340           get '/' => sub {
1341               send_file '/index.html'
1342           };
1343

FILE UPLOADS

1345       Files are uploaded in Dancer2 using the class
1346       Dancer2::Core::Request::Upload.  The objects are accessible within the
1347       route handlers using the "upload" keyword:
1348
1349           post '/upload' => sub {
1350               my $upload     = upload('file_input_name');    # upload object
1351               $upload->copy_to('Uploads/');
1352           };
1353

CONFIGURATION

1355   Configuration and environments
1356       Configuring a Dancer2 application can be done in many ways. The easiest
1357       one (and maybe the dirtiest) is to put all your settings statements at
1358       the top of your script, before calling the dance() method.
1359
1360       Other ways are possible: for example, you can define all your settings
1361       in the file "appdir/config.yml". For this, you must have installed the
1362       YAML module, and of course, write the config file in YAML.
1363
1364       That's better than the first option, but it's still not perfect as you
1365       can't switch easily from an environment to another without rewriting
1366       the config file.
1367
1368       A better solution is to have one config.yml file with default global
1369       settings, like the following:
1370
1371           # appdir/config.yml
1372           logger: 'file'
1373           layout: 'main'
1374
1375       And then write as many environment files as you like in
1376       "appdir/environments". That way, the appropriate environment config
1377       file will be loaded according to the running environment (if none is
1378       specified, it will be 'development').
1379
1380       You can change the running environment when starting your app using the
1381       "plackup" command's "--env" or "--E" switch:
1382
1383           plackup -E production bin/app.psgi
1384
1385       Altenatively, you can set the "DANCER_ENVIRONMENT"
1386       <https://metacpan.org/pod/Dancer2::Config#DANCER_ENVIRONMENT>
1387       environment variable in the shell or in your web server's configuration
1388       file.
1389
1390       Typically, you'll want to set the following values in a development
1391       config file:
1392
1393           # appdir/environments/development.yml
1394           log: 'debug'
1395           startup_info: 1
1396           show_stacktrace:  1
1397
1398       And in a production one:
1399
1400           # appdir/environments/production.yml
1401           log: 'warning'
1402           startup_info: 0
1403           show_stacktrace:  0
1404
1405       Please note that you are not limited to writing configuration files in
1406       YAML.  Dancer2 supports any file format that is supported by
1407       Config::Any, such as JSON, XML, INI files, and Apache-style config
1408       files. See the Dancer2 configuration guide
1409       <https://metacpan.org/pod/Dancer2::Config#MANIPULATING-SETTINGS-VIA-
1410       CONFIGURATION-FILES> for more information.
1411
1412   Accessing configuration information
1413       A Dancer2 application can use the "config" keyword to easily access the
1414       settings within its config file, for instance:
1415
1416           get '/appname' => sub {
1417               return "This is " . config->{appname};
1418           };
1419
1420       This makes keeping your application's settings all in one place simple
1421       and easy - you shouldn't need to worry about implementing all that
1422       yourself. :)
1423
1424   Settings
1425       It's possible to change almost every parameter of the application via
1426       the settings mechanism.
1427
1428       A setting is a key/value pair assigned by the keyword set:
1429
1430           set setting_name => 'setting_value';
1431
1432       More usefully, settings can be defined in a configuration file.
1433       Environment-specific settings can also be defined in environment-
1434       specific files (for instance, you do not want to show error stacktraces
1435       in production, and might want extra logging in development).
1436
1437   Serializers
1438       When writing a webservice, data serialization/deserialization is a
1439       common issue to deal with. Dancer2 can automatically handle that for
1440       you, via a serializer.
1441
1442       When setting up a serializer, a new behaviour is authorized for any
1443       route handler you define: any non-scalar response will be rendered as a
1444       serialized string, via the current serializer.
1445
1446       Here is an example of a route handler that will return a hashref:
1447
1448           use Dancer2;
1449           set serializer => 'JSON';
1450
1451           get '/user/:id/' => sub {
1452               { foo => 42,
1453                 number => 100234,
1454                 list => [qw(one two three)],
1455               }
1456           };
1457
1458       Dancer2 will render the response via the current serializer.
1459
1460       Hence, with the JSON serializer set, the route handler above would
1461       result in a content like the following:
1462
1463           {"number":100234,"foo":42,"list":["one","two","three"]}
1464
1465       If you send a value which is validated serialized data, but is not in
1466       the form a key and value pair (such as a serialized string or a JSON
1467       array), the data will not be available in "params" but will be
1468       available in "request->data".
1469
1470       The following serializers are available, be aware they dynamically
1471       depend on Perl modules you may not have on your system.
1472
1473JSON
1474
1475           Requires JSON.
1476
1477YAML
1478
1479           Requires YAML,
1480
1481XML
1482
1483           Requires XML::Simple.
1484
1485Mutable
1486
1487           Will try to find the appropriate serializer using the Content-Type
1488           and Accept-type header of the request.
1489
1490   Importing using Appname
1491       An app in Dancer2 uses the class name (defined by the "package"
1492       function) to define the App name. Thus separating the App to multiple
1493       files, actually means creating multiple applications. This means that
1494       any engine defined in an application, because the application is a
1495       complete separate scope, will not be available to a different
1496       application:
1497
1498            package MyApp::User {
1499                use Dancer2;
1500                set serializer => 'JSON';
1501                get '/view' => sub {...};
1502            }
1503
1504            package MyApp::User::Edit {
1505                use Dancer2;
1506                get '/edit' => sub {...};
1507            }
1508
1509       These are two different Dancer2 Apps. They have different scopes,
1510       contexts, and thus different engines. While "MyApp::User" has a
1511       serializer defined, "MyApp::User::Edit" will not have that
1512       configuration.
1513
1514       By using the import option "appname", we can ask Dancer2 to extend an
1515       App without creating a new one:
1516
1517            package MyApp::User {
1518                use Dancer2;
1519                set serializer => 'JSON';
1520                get '/view' => sub {...};
1521            }
1522
1523            package MyApp::User::Edit {
1524                use Dancer2 appname => 'MyApp::User'; # extending MyApp::User
1525                get '/edit' => sub {...};
1526            }
1527
1528       The import option "appname" allows you to seamlessly extend Dancer2
1529       Apps without creating unnecessary additional applications or repeat any
1530       definitions.  This allows you to spread your application routes across
1531       multiple files and allow ease of mind when developing it, and
1532       accommodate multiple developers working on the same codebase.
1533
1534            # app.pl
1535            use MyApp::User;
1536            use MyApp::User::Edit;
1537
1538            # single application composed of routes provided in multiple files
1539            MyApp::User->to_app;
1540
1541       This way only one class needs to be loaded while creating an app:
1542
1543            # app.pl:
1544            use MyApp::User;
1545            MyApp::User->to_app;
1546

LOGGING

1548   Configuring logging
1549       It's possible to log messages generated by the application and by
1550       Dancer2 itself.
1551
1552       To start logging, select the logging engine you wish to use with the
1553       "logger" setting; Dancer2 includes built-in log engines named "file"
1554       and "console", which log to a logfile and to the console respectively.
1555
1556       To enable logging to a file, add the following to your config file:
1557
1558           logger: 'file'
1559
1560       Then you can choose which kind of messages you want to actually log:
1561
1562           log: 'core'      # will log debug, info, warnings, errors,
1563                            #   and messages from Dancer2 itself
1564           log: 'debug'     # will log debug, info, warning and errors
1565           log: 'info'      # will log info, warning and errors
1566           log: 'warning'   # will log warning and errors
1567           log: 'error'     # will log only errors
1568
1569       If you're using the "file" logging engine, a directory "appdir/logs"
1570       will be created and will host one logfile per environment. The log
1571       message contains the time it was written, the PID of the current
1572       process, the message and the caller information (file and line).
1573
1574   Logging your own messages
1575       Just call debug <https://metacpan.org/pod/Dancer2::Manual#debug>, info
1576       <https://metacpan.org/pod/Dancer2::Manual#info>, warning
1577       <https://metacpan.org/pod/Dancer2::Manual#warning> or error
1578       <https://metacpan.org/pod/Dancer2::Manual#error> with your message:
1579
1580           debug "This is a debug message from my app.";
1581

TESTING

1583   Using Plack::Test
1584       Plack::Test receives a common web request (using standard HTTP::Request
1585       objects), fakes a web server in order to create a proper PSGI request,
1586       and sends it to the web application. When the web application returns a
1587       PSGI response (which Dancer applications do), it will then convert it
1588       to a common web response (as a standard HTTP::Response object).
1589
1590       This allows you to then create requests in your test, create the code
1591       reference for your web application, call them, and receive a response
1592       object, which can then be tested.
1593
1594       Basic Example
1595
1596       Assuming there is a web application:
1597
1598            # MyApp.pm
1599            package MyApp;
1600            use Dancer2;
1601            get '/' => sub {'OK'};
1602            1;
1603
1604       The following test base.t is created:
1605
1606            # base.t
1607            use strict;
1608            use warnings;
1609            use Test::More tests => 2;
1610            use Plack::Test;
1611            use HTTP::Request;
1612            use MyApp;
1613
1614       Creating a coderef for the application using the "to_app" keyword:
1615
1616            my $app = MyApp->to_app;
1617
1618       Creating a test object from Plack::Test for the application:
1619
1620            my $test = Plack::Test->create($app);
1621
1622       Creating the first request object and sending it to the test object to
1623       receive a response:
1624
1625            my $request  = HTTP::Request->new( GET => '/' );
1626            my $response = $test->request($request);
1627
1628       It can now be tested:
1629
1630            ok( $response->is_success, '[GET /] Successful request' );
1631            is( $response->content, 'OK', '[GET /] Correct content' );
1632
1633       Putting it together
1634
1635            # base.t
1636            use strict;
1637            use warnings;
1638            use Test::More;
1639            use Plack::Test;
1640            use HTTP::Request::Common;
1641            use MyApp;
1642
1643            my $test     = Plack::Test->create( MyApp->to_app );
1644            my $response = $test->request( GET '/' );
1645
1646            ok( $response->is_success, '[GET /] Successful request' );
1647            is( $response->content, 'OK', '[GET /] Correct content' );
1648
1649            done_testing();
1650
1651       Subtests
1652
1653       Tests can be separated using Test::More's "subtest" functionality, thus
1654       creating multiple self-contained tests that don't overwrite each other.
1655
1656       Assuming we have a different app that has two states we want to test:
1657
1658            # MyApp.pm
1659            package MyApp;
1660            use Dancer2;
1661            set serializer => 'JSON';
1662
1663            get '/:user' => sub {
1664                my $user = route_parameters->get('user');
1665
1666                $user and return { user => $user };
1667
1668                return {};
1669            };
1670
1671            1;
1672
1673       This is a contrived example of a route that checks for a user
1674       parameter. If it exists, it returns it in a hash with the key 'user'.
1675       If not, it returns an empty hash
1676
1677            # param.t
1678            use strict;
1679            use warnings;
1680            use Test::More;
1681            use Plack::Test;
1682            use HTTP::Request::Common;
1683            use MyApp;
1684
1685            my $test = Plack::Test->create( MyApp->to_app );
1686
1687            subtest 'A empty request' => sub {
1688                my $res = $test->request( GET '/' );
1689                ok( $res->is_success, 'Successful request' );
1690                is( $res->content '{}', 'Empty response back' );
1691            };
1692
1693            subtest 'Request with user' => sub {
1694                my $res = $test->request( GET '/?user=sawyer_x' );
1695                ok( $res->is_success, 'Successful request' );
1696                is( $res->content '{"user":"sawyer_x"}', 'Empty response back' );
1697            };
1698
1699            done_testing();
1700
1701       Cookies
1702
1703       To handle cookies, which are mostly used for maintaining sessions, the
1704       following modules can be used:
1705
1706       •   Test::WWW::Mechanize::PSGI
1707
1708       •   LWP::Protocol::PSGI
1709
1710       •   HTTP::Cookies
1711
1712       Taking the previous test, assuming it actually creates and uses cookies
1713       for sessions:
1714
1715            # ... all the use statements
1716            use HTTP::Cookies;
1717
1718            my $jar  = HTTP::Cookies->new;
1719            my $test = Plack::Test->create( MyApp->to_app );
1720
1721            subtest 'A empty request' => sub {
1722                my $res = $test->request( GET '/' );
1723                ok( $res->is_success, 'Successful request' );
1724                is( $res->content '{}', 'Empty response back' );
1725                $jar->extract_cookies($res);
1726                ok( $jar->as_string, 'We have cookies!' );
1727            };
1728
1729            subtest 'Request with user' => sub {
1730                my $req = GET '/?user=sawyer_x';
1731                $jar->add_cookie_header($req);
1732                my $res = $test->request($req);
1733                ok( $res->is_success, 'Successful request' );
1734                is( $res->content '{"user":"sawyer_x"}', 'Empty response back' );
1735                $jar->extract_cookies($res);
1736
1737                ok( ! $jar->as_string, 'All cookies deleted' );
1738            };
1739
1740            done_testing();
1741
1742       Here a cookie jar is created, all requests and responses, existing
1743       cookies, as well as cookies that were deleted by the response, are
1744       checked.
1745
1746       Accessing the configuration file
1747
1748       By importing Dancer2 in the command line scripts, there is full access
1749       to the configuration using the imported keywords:
1750
1751            use strict;
1752            use warnings;
1753            use Test::More;
1754            use Plack::Test;
1755            use HTTP::Request::Common;
1756            use MyApp;
1757            use Dancer2;
1758
1759            my $appname = config->{'appname'};
1760            diag "Testing $appname";
1761
1762            # ...
1763

PACKAGING

1765   Carton
1766       What it does
1767
1768       Carton sets up a local copy of your project prerequisites. You only
1769       need to define them in a file and ask Carton to download all of them
1770       and set them up.  When you want to deploy your app, you just carry the
1771       git clone and ask Carton to set up the environment again and you will
1772       then be able to run it.
1773
1774       The benefits are multifold:
1775
1776       •   Local Directory copy
1777
1778           By putting all the dependencies in a local directory, you can make
1779           sure they aren't updated by someone else by accident and their
1780           versions locked to the version you picked.
1781
1782       •   Sync versions
1783
1784           Deciding which versions of the dependent modules your project needs
1785           allows you to sync this with other developers as well. Now you're
1786           all using the same version and they don't change unless you want
1787           update the versions you want. When updated everyone again uses the
1788           same new version of everything.
1789
1790       •   Carry only the requirement, not bundled modules
1791
1792           Instead of bundling the modules, you only actually bundle the
1793           requirements.  Carton builds them for you when you need it.
1794
1795       Setting it up
1796
1797       First set up a new app:
1798
1799            $ dancer2 gen -a MyApp
1800            ...
1801
1802       Delete the files that are not needed:
1803
1804            $ rm -f Makefile.PL MANIFEST MANIFEST.SKIP
1805
1806       Create a git repo:
1807
1808            $ git init && git add . && git commit -m "initial commit"
1809
1810       Add a requirement using the cpanfile format:
1811
1812            $ cat > cpanfile
1813            requires 'Dancer2' => 0.155000;
1814            requires 'Template' => 0;
1815            recommends 'URL::Encode::XS' => 0;
1816            recommends 'CGI::Deurl::XS' => 0;
1817            recommends 'HTTP::Parser::XS' => 0;
1818
1819       Ask carton to set it up:
1820
1821            $ carton install
1822            Installing modules using [...]
1823            Successfully installed [...]
1824            ...
1825            Complete! Modules were install into [...]/local
1826
1827       Now we have two files: cpanfile and cpanfile.snapshot. We add both of
1828       them to our Git repository and we make sure we don't accidentally add
1829       the local/ directory Carton created which holds the modules it
1830       installed:
1831
1832            $ echo local/ >> .gitignore
1833            $ git add .gitignore cpanfile cpanfile.snapshot
1834            $ git commit -m "Start using carton"
1835
1836       When we want to update the versions on the production machine, we
1837       simply call:
1838
1839            $ carton install --deployment
1840
1841       By using --deployment we make sure we only install the modules we have
1842       in our cpanfile.snapshot file and do not fallback to querying the CPAN.
1843
1844   FatPacker
1845       App::FatPacker (using its command line interface, fatpack) packs
1846       dependencies into a single file, allowing you to carry a single file
1847       instead of a directory tree.
1848
1849       As long as your application is pure-Perl, you could create a single
1850       file with your application and all of Dancer2 in it.
1851
1852       The following example will demonstrate how this can be done:
1853
1854       Assuming we have an application in lib/MyApp.pm:
1855
1856            package MyApp;
1857            use Dancer2;
1858            get '/' => sub {'OK'};
1859            1;
1860
1861       And we have a handler in bin/app.pl:
1862
1863            use strict;
1864            use warnings;
1865            use FindBin;
1866            use lib "$FindBin::Bin/../lib";
1867            use MyApp;
1868
1869            MyApp->to_app;
1870
1871       To fatpack it, we begin by tracing the script:
1872
1873            $ fatpack trace bin/app.pl
1874
1875       This creates a fatpacker.trace file. From this we create the packlists:
1876
1877            $ fatpack packlists-for `cat fatpacker.trace` > packlists
1878
1879       The packlists are stored in a file called packlists.
1880
1881       Now we create the tree using the following command:
1882
1883            $ fatpack tree `cat packlists`
1884
1885       The tree is created under the directory fatlib.
1886
1887       Now we create a file containing the dependency tree, and add our script
1888       to it, using the following command:
1889
1890            $ (fatpack file; cat bin/app.pl) > myapp.pl
1891
1892       This creates a file called myapp.pl with everything in it. Dancer2 uses
1893       MIME::Types which has a database of all MIME types and helps translate
1894       those.  The small database file containing all of these types is a
1895       binary and therefore cannot be fatpacked. Hence, it needs to be copied
1896       to the current directory so our script can find it:
1897
1898            $ cp fatlib/MIME/types.db .
1899

MIDDLEWARES

1901   Plack middlewares
1902       If you want to use Plack middlewares, you need to enable them using
1903       Plack::Builder as such:
1904
1905           # in app.psgi or any other handler
1906           use MyApp;
1907           use Plack::Builder;
1908
1909           builder {
1910               enable 'Deflater';
1911               enable 'Session', store => 'File';
1912               enable 'Debug', panels => [ qw<DBITrace Memory Timer> ];
1913               MyApp->to_app;
1914           };
1915
1916       The nice thing about this setup is that it will work seamlessly through
1917       Plack or through the internal web server.
1918
1919           # load dev web server (without middlewares)
1920           perl -Ilib app.psgi
1921
1922           # load plack web server (with middlewares)
1923           plackup -I lib app.psgi
1924
1925       You do not need to provide different files for either server.
1926
1927       Path-based middlewares
1928
1929       If you want to set up a middleware for a specific path, you can do that
1930       using Plack::Builder which uses Plack::App::URLMap:
1931
1932           # in your app.psgi or any other handler
1933           use MyApp;
1934           use Plack::Builder;
1935
1936           my $special_handler = sub { ... };
1937
1938           builder {
1939               mount '/special' => $special_handler;
1940               mount '/'        => MyApp->to_app;
1941           };
1942
1943       Removing default middlewares
1944
1945       By default, a Dancer2 app is automatically wrapped with the following
1946       middleware
1947
1948       •   Plack::Middleware::FixMissingBodyInRedirect
1949
1950       •   Plack::Middleware::Head
1951
1952       You can configure the setting "no_default_middleware" to a true value
1953       to stop your Dancer2 app being wrapped with these default middleware
1954       layers.
1955
1956           # in you Dancer2 app or config.yml
1957           package MyApp;
1958           use Dancer2
1959
1960           set no_default_middleware => true;
1961
1962       This is necessary if you need to add eTag or ContentMD5 headers to
1963       "HEAD" requests, and you are encouraged to manually add those default
1964       middleware back into your PSGI stack.
1965
1966       Running on Perl web servers with plackup
1967
1968       A number of Perl web servers supporting PSGI are available on CPAN:
1969
1970       •   Starman
1971
1972           "Starman" is a high performance web server, with support for
1973           preforking, signals, multiple interfaces, graceful restarts and
1974           dynamic worker pool configuration.
1975
1976       •   Twiggy
1977
1978           "Twiggy" is an "AnyEvent" web server, it's light and fast.
1979
1980       •   Corona
1981
1982           "Corona" is a "Coro" based web server.
1983
1984       To start your application, just run plackup (see Plack and specific
1985       servers above for all available options):
1986
1987          $ plackup bin/app.psgi
1988          $ plackup -E deployment -s Starman --workers=10 -p 5001 -a bin/app.psgi
1989
1990       As you can see, the scaffolded Perl script for your app can be used as
1991       a PSGI startup file.
1992
1993       Enabling content compression
1994
1995       Content compression (gzip, deflate) can be easily enabled via a Plack
1996       middleware (see "Plack::Middleware" in Plack):
1997       Plack::Middleware::Deflater.  It's a middleware to encode the response
1998       body in gzip or deflate, based on the "Accept-Encoding" HTTP request
1999       header.
2000
2001       Enable it as you would enable any Plack middleware. First you need to
2002       install Plack::Middleware::Deflater, then in the handler (usually
2003       app.psgi) edit it to use Plack::Builder, as described above:
2004
2005           use Dancer2;
2006           use MyApp;
2007           use Plack::Builder;
2008
2009           builder {
2010               enable 'Deflater';
2011               MyApp->to_app;
2012           };
2013
2014       To test if content compression works, trace the HTTP request and
2015       response before and after enabling this middleware. Among other things,
2016       you should notice that the response is gzip or deflate encoded, and
2017       contains a header "Content-Encoding" set to "gzip" or "deflate".
2018
2019       Running multiple apps with Plack::Builder
2020
2021       You can use Plack::Builder to mount multiple Dancer2 applications on a
2022       PSGI webserver like Starman.
2023
2024       Start by creating a simple app.psgi file:
2025
2026           use OurWiki;  # first app
2027           use OurForum; # second app
2028           use Plack::Builder;
2029
2030           builder {
2031               mount '/wiki'  => OurWiki->to_app;
2032               mount '/forum' => OurForum->to_app;
2033           };
2034
2035       and now use Starman
2036
2037           plackup -a app.psgi -s Starman
2038
2039       Currently this still demands the same appdir for both (default
2040       circumstance) but in a future version this will be easier to change
2041       while staying very simple to mount.
2042
2043       Running from Apache with Plack
2044
2045       You can run your app from Apache using PSGI (Plack), with a config like
2046       the following:
2047
2048           <VirtualHost myapp.example.com>
2049               ServerName www.myapp.example.com
2050               ServerAlias myapp.example.com
2051               DocumentRoot /websites/myapp.example.com
2052
2053               <Directory /home/myapp/myapp>
2054                   AllowOverride None
2055                   Order allow,deny
2056                   Allow from all
2057               </Directory>
2058
2059               <Location />
2060                   SetHandler perl-script
2061                   PerlResponseHandler Plack::Handler::Apache2
2062                   PerlSetVar psgi_app /websites/myapp.example.com/app.psgi
2063               </Location>
2064
2065               ErrorLog  /websites/myapp.example.com/logs/error_log
2066               CustomLog /websites/myapp.example.com/logs/access_log common
2067           </VirtualHost>
2068
2069       To set the environment you want to use for your application (production
2070       or development), you can set it this way:
2071
2072           <VirtualHost>
2073               ...
2074               SetEnv DANCER_ENVIRONMENT "production"
2075               ...
2076           </VirtualHost>
2077

PLUGINS

2079   Writing a plugin
2080       See "Writing the plugin" in Dancer2::Plugin for information on how to
2081       author a new plugin for Dancer2.
2082

EXPORTS

2084       By default, "use Dancer2" exports all the DSL keywords and sets up the
2085       webapp under the name of the current package. The following tags
2086       control exports and webapp namespace.
2087
2088!keyword
2089
2090           If you want to prevent Dancer2 from exporting specific keywords
2091           (perhaps you plan to implement them yourself in a different way, or
2092           they clash with another module you're loading), you can simply
2093           exclude them:
2094
2095               use Test::More;
2096               use Dancer2 qw(!pass);
2097
2098           The above would import all keywords as usual, with the exception of
2099           "pass".
2100
2101appname
2102
2103           A larger application may split its source between several packages
2104           to aid maintainability. Dancer2 will create a separate application
2105           for each package, each having separate hooks, config and/or
2106           engines. You can force Dancer2 to collect the route and hooks into
2107           a single application with the "appname" tag; e.g.
2108
2109               package MyApp;
2110               use Dancer2;
2111               get '/foo' => sub {...};
2112
2113               package MyApp::Private;
2114               use Dancer2 appname => MyApp;
2115               get '/bar' => sub {...};
2116
2117           The above would add the "bar" route to the MyApp application.
2118           Dancer2 will not create an application with the name
2119           "MyApp::Private".
2120
2121:nopragmas
2122
2123           By default Dancer2 will import three pragmas: strict, warnings, and
2124           utf8. If you require control over the imported pragmas, you can add
2125           :nopragmas to the importing flags, in which case Dancer2 will not
2126           import any pragmas:
2127
2128               use strict;
2129               use warnings;
2130               no warnings 'experimental::smartmatch'; # for example...
2131               use Dancer2 ':nopragmas'; # do not touch the existing pragmas
2132
2133           This way importing "Dancer2" does not change the existing pragmas
2134           setup you have.
2135
2136       When you "use Dancer2", you get an "import" method added into the
2137       current package. This will override previously declared import methods
2138       from other sources, such as Exporter. Dancer2 applications support the
2139       following tags on import:
2140
2141with
2142
2143           The "with" tag allows an app to pass one or more config entries to
2144           another app, when it "use"s it.
2145
2146               package MyApp;
2147               use Dancer2;
2148
2149               BEGIN { set session => 'YAML' };
2150               use Blog with => { session => engine('session') };
2151
2152           In this example, the session engine is passed to the "Blog" app.
2153           That way, anything done in the session will be shared between both
2154           apps.
2155
2156           Anything that is defined in the config entry can be passed that
2157           way. If we want to pass the whole config object, it can be done
2158           like so:
2159
2160               use SomeApp with => { %{config()} };
2161

DSL KEYWORDS

2163       Dancer2 provides you with a DSL (Domain-Specific Language) which makes
2164       implementing your web application trivial.
2165
2166       For example, take the following example:
2167
2168           use Dancer2;
2169
2170           get '/hello/:name' => sub {
2171               my $name = route_parameters->get('name');
2172           };
2173           dance;
2174
2175       "get" and "route_parameters" are keywords provided by Dancer2.
2176
2177       See "DSL Keywords manual" in Dancer2::Manual::Keywords for a complete
2178       list of keywords provided by Dancer2.
2179

AUTHOR

2181       Dancer Core Developers
2182
2184       This software is copyright (c) 2023 by Alexis Sukrieh.
2185
2186       This is free software; you can redistribute it and/or modify it under
2187       the same terms as the Perl 5 programming language system itself.
2188
2189
2190
2191perl v5.38.0                      2023-07-20                Dancer2::Manual(3)
Impressum