1Dancer2::Manual(3) User Contributed Perl Documentation Dancer2::Manual(3)
2
3
4
6 Dancer2::Manual - A gentle introduction to Dancer2
7
9 version 0.300004
10
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
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
49 Create a web application using the dancer script:
50
51 $ dancer2 -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 -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
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
130 · GET 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
142 · POST The POST method is used to create a resource on the server.
143
144 To define a POST action, use the post keyword.
145
146 · PUT 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
155 · PATCH The PATCH method updates some attributes of an existing
156 resource.
157
158 To define a PATCH action, use the patch keyword.
159
160 · DELETE 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 For Perl 5.10+, a route regex may use named capture groups. The
335 "captures" keyword will 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
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
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
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_errors is set to true, in the case of a 500 error the
785 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 · As default, render a generic error page on the fly.
790
791 Execution Errors
792 When an error occurs during the route execution, Dancer2 will render an
793 error page with the HTTP status code 500.
794
795 It's possible either to display the content of the error message or to
796 hide it with a generic error page. This is a choice left to the end-
797 user and can be controlled with the show_errors setting (see above).
798
799 Note that you can also choose to consider all warnings in your route
800 handlers as errors when the setting warnings is set to 1.
801
802 Error Hooks
803 When an error is caught by Dancer2's core, an exception object is built
804 (of the class Dancer2::Core::Error). This class provides a hook to let
805 the user alter the error workflow if needed.
806
807 "init_error" hooks are called whenever an error object is built, the
808 object is passed to the hook.
809
810 hook init_error => sub {
811 my $error = shift;
812 # do something with $error
813 };
814
815 This hook was named before_error_init in Dancer, both names currently
816 are synonyms for backward-compatibility.
817
818 "before_error" hooks are called whenever an error is going to be
819 thrown, it receives the error object as its sole argument.
820
821 hook before_error => sub {
822 my $error = shift;
823 # do something with $error
824 };
825
826 This hook was named before_error_render in Dancer, both names currently
827 are synonyms for backward-compatibility.
828
829 "after_error" hooks are called whenever an error object has been
830 thrown, it receives a Dancer2::Core::Response object as its sole
831 argument.
832
833 hook after_error => sub {
834 my $response = shift;
835 };
836
837 This hook was named after_error_render in Dancer, both names currently
838 are synonyms for backward-compatibility.
839
840 "on_route_exception" is called when an exception has been caught, at
841 the route level, just before rethrowing it higher. This hook receives a
842 Dancer2::Core::App and the error as arguments.
843
844 hook on_route_exception => sub {
845 my ($app, $error) = @_;
846 };
847
849 Handling sessions
850 It's common to want to use sessions to give your web applications
851 state; for instance, allowing a user to log in, creating a session, and
852 checking that session on subsequent requests.
853
854 By default Dancer 2 has Simple sessions enabled. It implements a very
855 simple in-memory session storage. This will be fast and useful for
856 testing, but such sessions will not persist between restarts of your
857 app.
858
859 If you'd like to use a different session engine you must declare it in
860 the configuration file.
861
862 For example to use YAML file base sessions you need to add the
863 following to your config.yml:
864
865 session: YAML
866
867 Or, to enable session support from within your code,
868
869 set session => 'YAML';
870
871 (However, controlling settings is best done from your config file.)
872
873 The Dancer2::Session::YAML backend implements a file-based YAML session
874 storage to help with debugging, but shouldn't be used on production
875 systems.
876
877 There are other session backends, such as Dancer2::Session::Memcached,
878 which are recommended for production use.
879
880 You can then use the session keyword to manipulate the session:
881
882 Storing data in the session
883
884 Storing data in the session is as easy as:
885
886 session varname => 'value';
887
888 Retrieving data from the session
889
890 Retrieving data from the session is as easy as:
891
892 session('varname')
893
894 Or, alternatively,
895
896 session->read("varname")
897
898 Controlling where sessions are stored
899
900 For disc-based session backends like Dancer2::Session::YAML, session
901 files are written to the session dir specified by the "session_dir"
902 setting, which defaults to "./sessions" if not specifically set.
903
904 If you need to control where session files are created, you can do so
905 quickly and easily within your config file, for example:
906
907 session: YAML
908 engines:
909 session:
910 YAML:
911 session_dir: /tmp/dancer-sessions
912
913 If the directory you specify does not exist, Dancer2 will attempt to
914 create it for you.
915
916 Changing session ID
917
918 If you wish to change the session ID (for example on privilege level
919 change):
920
921 my $new_session_id = app->change_session_id
922
923 Destroying a session
924
925 When you're done with your session, you can destroy it:
926
927 app->destroy_session
928
929 Sessions and logging in
930 A common requirement is to check the user is logged in, and, if not,
931 require them to log in before continuing.
932
933 This can easily be handled using a before hook to check their session:
934
935 use Dancer2;
936 set session => "Simple";
937
938 hook before => sub {
939 if (!session('user') && request->path !~ m{^/login}) {
940 forward '/login', { requested_path => request->path };
941 }
942 };
943
944 get '/' => sub { return "Home Page"; };
945
946 get '/secret' => sub { return "Top Secret Stuff here"; };
947
948 get '/login' => sub {
949 # Display a login page; the original URL they requested is available as
950 # query_parameters->get('requested_path'), so could be put in a hidden field in the form
951 template 'login', { path => query_parameters->get('requested_path') };
952 };
953
954 post '/login' => sub {
955 # Validate the username and password they supplied
956 if (body_parameters->get('user') eq 'bob' && body_parameters->get('pass') eq 'letmein') {
957 session user => body_parameters->get('user');
958 redirect body_parameters->get('path') || '/';
959 } else {
960 redirect '/login?failed=1';
961 }
962 };
963
964 dance();
965
966 Here is what the corresponding "login.tt" file should look like. You
967 should place it in a directory called "views/":
968
969 <html>
970 <head>
971 <title>Session and logging in</title>
972 </head>
973 <body>
974 <form action='/login' method='POST'>
975 User Name : <input type='text' name='user'/>
976 Password: <input type='password' name='pass' />
977
978 <!-- Put the original path requested into a hidden
979 field so it's sent back in the POST and can be
980 used to redirect to the right page after login -->
981 <input type='hidden' name='path' value='<% path %>'/>
982
983 <input type='submit' value='Login' />
984 </form>
985 </body>
986 </html>
987
988 Of course, you'll probably want to validate your users against a
989 database table, or maybe via IMAP/LDAP/SSH/POP3/local system accounts
990 via PAM etc. Authen::Simple is probably a good starting point here!
991
992 A simple working example of handling authentication against a database
993 table yourself (using Dancer2::Plugin::Database which provides the
994 "database" keyword, and Crypt::SaltedHash to handle salted hashed
995 passwords (well, you wouldn't store your users passwords in the clear,
996 would you?)) follows:
997
998 post '/login' => sub {
999 my $user_value = body_parameters->get('user');
1000 my $pass_value = body_parameters->get('pass');
1001
1002 my $user = database->quick_select('users',
1003 { username => $user_value }
1004 );
1005 if (!$user) {
1006 warning "Failed login for unrecognised user $user_value";
1007 redirect '/login?failed=1';
1008 } else {
1009 if (Crypt::SaltedHash->validate($user->{password}, $pass_value))
1010 {
1011 debug "Password correct";
1012 # Logged in successfully
1013 session user => $user;
1014 redirect body_parameters->get('path') || '/';
1015 } else {
1016 debug("Login failed - password incorrect for " . $user_value);
1017 redirect '/login?failed=1';
1018 }
1019 }
1020 };
1021
1022 Retrieve complete hash stored in session
1023
1024 Get complete hash stored in session:
1025
1026 my $hash = session;
1027
1028 Writing a session engine
1029 In Dancer 2, a session backend consumes the role
1030 Dancer2::Core::Role::SessionFactory.
1031
1032 The following example using the Redis session demonstrates how session
1033 engines are written in Dancer 2.
1034
1035 First thing to do is to create the class for the session engine, we'll
1036 name it "Dancer2::Session::Redis":
1037
1038 package Dancer2::Session::Redis;
1039 use Moo;
1040 with 'Dancer2::Core::Role::SessionFactory';
1041
1042 we want our backend to have a handle over a Redis connection. To do
1043 that, we'll create an attribute "redis"
1044
1045 use JSON;
1046 use Redis;
1047 use Dancer2::Core::Types; # brings helper for types
1048
1049 has redis => (
1050 is => 'rw',
1051 isa => InstanceOf['Redis'],
1052 lazy => 1,
1053 builder => '_build_redis',
1054 );
1055
1056 The lazy attribute says to Moo that this attribute will be built
1057 (initialized) only when called the first time. It means that the
1058 connection to Redis won't be opened until necessary.
1059
1060 sub _build_redis {
1061 my ($self) = @_;
1062 Redis->new(
1063 server => $self->server,
1064 password => $self->password,
1065 encoding => undef,
1066 );
1067 }
1068
1069 Two more attributes, "server" and "password" need to be created. We do
1070 this by defining them in the config file. Dancer2 passes anything
1071 defined in the config to the engine creation.
1072
1073 # config.yml
1074 ...
1075 engines:
1076 session:
1077 Redis:
1078 server: foo.mydomain.com
1079 password: S3Cr3t
1080
1081 The server and password entries are now passed to the constructor of
1082 the Redis session engine and can be accessed from there.
1083
1084 has server => (is => 'ro', required => 1);
1085 has password => (is => 'ro');
1086
1087 Next, we define the subroutine "_retrieve" which will return a session
1088 object for a session ID it has passed. Since in this case, sessions are
1089 going to be stored in Redis, the session ID will be the key, the
1090 session the value. So retrieving is as easy as doing a get and
1091 decoding the JSON string returned:
1092
1093 sub _retrieve {
1094 my ($self, $session_id) = @_;
1095 my $json = $self->redis->get($session_id);
1096 my $hash = from_json( $json );
1097 return bless $hash, 'Dancer2::Core::Session';
1098 }
1099
1100 The "_flush" method is called by Dancer when the session needs to be
1101 stored in the backend. That is actually a write to Redis. The method
1102 receives a "Dancer2::Core::Session" object and is supposed to store it.
1103
1104 sub _flush {
1105 my ($self, $session) = @_;
1106 my $json = encode_json( { %{ $session } } );
1107 $self->redis->set($session->id, $json);
1108 }
1109
1110 For the "_destroy" method which is supposed to remove a session from
1111 the backend, deleting the key from Redis is enough.
1112
1113 sub _destroy {
1114 my ($self, $session_id) = @_;
1115 $self->redis->del($session_id);
1116 }
1117
1118 The "_sessions" method which is supposed to list all the session IDs
1119 currently stored in the backend is done by listing all the keys that
1120 Redis has.
1121
1122 sub _sessions {
1123 my ($self) = @_;
1124 my @keys = $self->redis->keys('*');
1125 return \@keys;
1126 }
1127
1128 The session engine is now ready.
1129
1130 The Session keyword
1131
1132 Dancer2 maintains two session layers.
1133
1134 The first layer, Dancer2::Core::Session provides a session object which
1135 represents the current session. You can read from it as many times as
1136 you want, and write to it as many times as you want.
1137
1138 The second layer is the session engine (Dancer2::Session::Simple is one
1139 example), which is used in order to implement the reading and writing
1140 from the actual storage. This is read only once, when a request comes
1141 in (using a cookie whose value is "dancer.session" by default). At the
1142 end of a request, all the data you've written will be flushed to the
1143 engine itself, which will do the actual write to the storage (whether
1144 it's in a hash in memory, in Memcache, or in a database).
1145
1147 Returning plain content is all well and good for examples or trivial
1148 apps, but soon you'll want to use templates to maintain separation
1149 between your code and your content. Dancer2 makes this easy.
1150
1151 Your route handlers can use the template keyword to render templates.
1152
1153 Views
1154 In Dancer2, a file which holds a template is called a view. Views are
1155 located in the "appdir/views" directory.
1156
1157 You can change this location by changing the setting 'views'. For
1158 instance if your templates are located in the 'templates' directory, do
1159 the following:
1160
1161 set views => path( app->location , 'templates' );
1162
1163 By default, the internal template engine Dancer2::Template::Simple is
1164 used, but you may want to upgrade to Template Toolkit
1165 <http://www.template-toolkit.org/>. If you do so, you have to enable
1166 this engine in your settings as explained in
1167 Dancer2::Template::TemplateToolkit and you'll also have to install the
1168 Template module.
1169
1170 In order to render a view, just call the template keyword at the end of
1171 the action by giving the view name and the HASHREF of tokens to
1172 interpolate in the view (note that for convenience, the request,
1173 session, params and vars are automatically accessible in the view,
1174 named "request", "session", "params", and "vars") - for example:
1175
1176 hook before => sub { var time => scalar(localtime) };
1177
1178 get '/hello/:name' => sub {
1179 my $name = route_parameters->get('name');
1180 template 'hello.tt', { name => $name };
1181 };
1182
1183 The template "hello.tt" could contain, for example:
1184
1185 <p>Hi there, [% name %]!</p>
1186 <p>You're using [% request.user_agent %]</p>
1187 [% IF session.username %]
1188 <p>You're logged in as [% session.username %]</p>
1189 [% END %]
1190 It's currently [% vars.time %]
1191
1192 For a full list of the tokens automatically added to your template
1193 (like "session", "request", and "vars", refer to
1194 Dancer2::Core::Role::Template).
1195
1196 By default, views use a .tt extension. This can be overridden by
1197 setting the "extension" attribute in the template engine configuration:
1198
1199 set engines => {
1200 template => {
1201 template_toolkit => {
1202 extension => 'foo',
1203 },
1204 },
1205 };
1206
1207 Layouts
1208 A layout is a special view, located in the layouts directory (inside
1209 the views directory) which must have a token named "content". That
1210 token marks the place where to render the action view. This lets you
1211 define a global layout for your actions, and have each individual view
1212 contain only specific content. This is a good thing and helps avoid
1213 lots of needless duplication of HTML. :)
1214
1215 For example, the layout views/layouts/main.tt:
1216
1217 <html>
1218 <head>...</head>
1219 <body>
1220 <div id="header">
1221 ...
1222 </div>
1223
1224 <div id="content">
1225 [% content %]
1226 </div>
1227
1228 </body>
1229 </html>
1230
1231 You can tell your app which layout to use with "layout: name" in the
1232 config file, or within your code:
1233
1234 set layout => 'main';
1235
1236 You can control which layout to use (or whether to use a layout at all)
1237 for a specific request without altering the layout setting by passing
1238 an options hashref as the third param to the template keyword:
1239
1240 template 'index.tt', {}, { layout => undef };
1241
1242 If your application is not mounted under root ("/"), you can use a
1243 "before_template_render" hook instead of hardcoding the path into your
1244 application for your CSS, images and JavaScript:
1245
1246 hook before_template_render => sub {
1247 my $tokens = shift;
1248 $tokens->{uri_base} = request->base->path;
1249 };
1250
1251 Then in your layout, modify your CSS inclusion as follows:
1252
1253 <link rel="stylesheet" href="[% uri_base %]/css/style.css" />
1254
1255 From now on you can mount your application wherever you want, without
1256 any further modification of the CSS inclusion.
1257
1258 Encoding
1259 If you use Plack and have a Unicode problem with your Dancer2
1260 application, don't forget to check if you have set your template engine
1261 to use Unicode, and set the default charset to UTF-8. So, if you are
1262 using template toolkit, your config file will look like this:
1263
1264 charset: UTF-8
1265 engines:
1266 template:
1267 template_toolkit:
1268 ENCODING: utf8
1269
1270 Default Template Variables
1271 Every template knows about the following variables, which are provided
1272 by Dancer2::Core::Role::Template. Some are similar to the keywords you
1273 can use in the Perl part of your Dancer2 application.
1274
1275 · perl_version
1276
1277 Current version of perl, effectively $^V
1278 <http://perldoc.perl.org/perlvar.html#%24%5eV>.
1279
1280 · dancer_version
1281
1282 Current version of Dancer2, effectively "Dancer2->VERSION".
1283
1284 · settings
1285
1286 A hash of the application configuration. This is like the config
1287 keyword.
1288
1289 · request
1290
1291 The current request object. This is like the request keyword.
1292
1293 · params
1294
1295 A hash reference of all the parameters.
1296
1297 Currently the equivalent of "$request->params", and like the params
1298 keyword.
1299
1300 · vars
1301
1302 The list of request variables, which is what you would get if you
1303 called the vars keyword.
1304
1305 · session
1306
1307 The current session data, if a session exists. This is like the
1308 session keyword.
1309
1311 Static Directory
1312 Static files are served from the ./public directory. You can specify a
1313 different location by setting the "public_dir" option:
1314
1315 set public_dir => path( app->location , 'static' );
1316
1317 When you modify default public_dir you have to set "static_handler"
1318 option.
1319
1320 set static_handler => true;
1321
1322 Note that the public directory name is not included in the URL. A file
1323 ./public/css/style.css is made available as
1324 <http://example.com/css/style.css>.
1325
1326 Static File from a Route Handler
1327 It's possible for a route handler to send a static file, as follows:
1328
1329 get '/download/*' => sub {
1330 my ($file) = splat;
1331
1332 send_file $file;
1333 };
1334
1335 Or even if you want your index page to be a plain old index.html file,
1336 just do:
1337
1338 get '/' => sub {
1339 send_file '/index.html'
1340 };
1341
1343 Files are uploaded in Dancer2 using the class
1344 Dancer2::Core::Request::Upload. The objects are accessible within the
1345 route handlers using the "upload" keyword:
1346
1347 post '/upload' => sub {
1348 my $upload = upload('file_input_name'); # upload object
1349 $upload->copy_to('Uploads/');
1350 };
1351
1353 Configuration and environments
1354 Configuring a Dancer2 application can be done in many ways. The easiest
1355 one (and maybe the dirtiest) is to put all your settings statements at
1356 the top of your script, before calling the "dance()" method.
1357
1358 Other ways are possible: for example, you can define all your settings
1359 in the file "appdir/config.yml". For this, you must have installed the
1360 YAML module, and of course, write the config file in YAML.
1361
1362 That's better than the first option, but it's still not perfect as you
1363 can't switch easily from an environment to another without rewriting
1364 the config file.
1365
1366 A better solution is to have one config.yml file with default global
1367 settings, like the following:
1368
1369 # appdir/config.yml
1370 logger: 'file'
1371 layout: 'main'
1372
1373 And then write as many environment files as you like in
1374 "appdir/environments". That way, the appropriate environment config
1375 file will be loaded according to the running environment (if none is
1376 specified, it will be 'development').
1377
1378 You can change the running environment when starting your app using the
1379 "plackup" command's "--env" or "--E" switch:
1380
1381 plackup -E production bin/app.psgi
1382
1383 Altenatively, you can set the "DANCER_ENVIRONMENT"
1384 <https://metacpan.org/pod/Dancer2::Config#DANCER_ENVIRONMENT>
1385 environment variable in the shell or in your web server's configuration
1386 file.
1387
1388 Typically, you'll want to set the following values in a development
1389 config file:
1390
1391 # appdir/environments/development.yml
1392 log: 'debug'
1393 startup_info: 1
1394 show_errors: 1
1395
1396 And in a production one:
1397
1398 # appdir/environments/production.yml
1399 log: 'warning'
1400 startup_info: 0
1401 show_errors: 0
1402
1403 Please note that you are not limited to writing configuration files in
1404 YAML. Dancer2 supports any file format that is supported by
1405 Config::Any, such as JSON, XML, INI files, and Apache-style config
1406 files. See the Dancer2 configuration guide
1407 <https://metacpan.org/pod/Dancer2::Config#MANIPULATING-SETTINGS-VIA-
1408 CONFIGURATION-FILES> for more information.
1409
1410 Accessing configuration information
1411 A Dancer2 application can use the "config" keyword to easily access the
1412 settings within its config file, for instance:
1413
1414 get '/appname' => sub {
1415 return "This is " . config->{appname};
1416 };
1417
1418 This makes keeping your application's settings all in one place simple
1419 and easy - you shouldn't need to worry about implementing all that
1420 yourself. :)
1421
1422 Settings
1423 It's possible to change almost every parameter of the application via
1424 the settings mechanism.
1425
1426 A setting is a key/value pair assigned by the keyword set:
1427
1428 set setting_name => 'setting_value';
1429
1430 More usefully, settings can be defined in a configuration file.
1431 Environment-specific settings can also be defined in environment-
1432 specific files (for instance, you do not want to show error stacktraces
1433 in production, and might want extra logging in development).
1434
1435 Serializers
1436 When writing a webservice, data serialization/deserialization is a
1437 common issue to deal with. Dancer2 can automatically handle that for
1438 you, via a serializer.
1439
1440 When setting up a serializer, a new behaviour is authorized for any
1441 route handler you define: any non-scalar response will be rendered as a
1442 serialized string, via the current serializer.
1443
1444 Here is an example of a route handler that will return a hashref:
1445
1446 use Dancer2;
1447 set serializer => 'JSON';
1448
1449 get '/user/:id/' => sub {
1450 { foo => 42,
1451 number => 100234,
1452 list => [qw(one two three)],
1453 }
1454 };
1455
1456 Dancer2 will render the response via the current serializer.
1457
1458 Hence, with the JSON serializer set, the route handler above would
1459 result in a content like the following:
1460
1461 {"number":100234,"foo":42,"list":["one","two","three"]}
1462
1463 If you send a value which is validated serialized data, but is not in
1464 the form a key and value pair (such as a serialized string or a JSON
1465 array), the data will not be available in "params" but will be
1466 available in "request->data".
1467
1468 The following serializers are available, be aware they dynamically
1469 depend on Perl modules you may not have on your system.
1470
1471 · JSON
1472
1473 Requires JSON.
1474
1475 · YAML
1476
1477 Requires YAML,
1478
1479 · XML
1480
1481 Requires XML::Simple.
1482
1483 · Mutable
1484
1485 Will try to find the appropriate serializer using the Content-Type
1486 and Accept-type header of the request.
1487
1488 Importing using Appname
1489 An app in Dancer2 uses the class name (defined by the "package"
1490 function) to define the App name. Thus separating the App to multiple
1491 files, actually means creating multiple applications. This means that
1492 any engine defined in an application, because the application is a
1493 complete separate scope, will not be available to a different
1494 application:
1495
1496 package MyApp::User {
1497 use Dancer2;
1498 set serializer => 'JSON';
1499 get '/view' => sub {...};
1500 }
1501
1502 package MyApp::User::Edit {
1503 use Dancer2;
1504 get '/edit' => sub {...};
1505 }
1506
1507 These are two different Dancer2 Apps. They have different scopes,
1508 contexts, and thus different engines. While "MyApp::User" has a
1509 serializer defined, "MyApp::User::Edit" will not have that
1510 configuration.
1511
1512 By using the import option "appname", we can ask Dancer2 to extend an
1513 App without creating a new one:
1514
1515 package MyApp::User {
1516 use Dancer2;
1517 set serializer => 'JSON';
1518 get '/view' => sub {...};
1519 }
1520
1521 package MyApp::User::Edit {
1522 use Dancer2 appname => 'MyApp::User'; # extending MyApp::User
1523 get '/edit' => sub {...};
1524 }
1525
1526 The import option "appname" allows you to seamlessly extend Dancer2
1527 Apps without creating unnecessary additional applications or repeat any
1528 definitions. This allows you to spread your application routes across
1529 multiple files and allow ease of mind when developing it, and
1530 accommodate multiple developers working on the same codebase.
1531
1532 # app.pl
1533 use MyApp::User;
1534 use MyApp::User::Edit;
1535
1536 # single application composed of routes provided in multiple files
1537 MyApp::User->to_app;
1538
1539 This way only one class needs to be loaded while creating an app:
1540
1541 # app.pl:
1542 use MyApp::User;
1543 MyApp::User->to_app;
1544
1546 Configuring logging
1547 It's possible to log messages generated by the application and by
1548 Dancer2 itself.
1549
1550 To start logging, select the logging engine you wish to use with the
1551 "logger" setting; Dancer2 includes built-in log engines named "file"
1552 and "console", which log to a logfile and to the console respectively.
1553
1554 To enable logging to a file, add the following to your config file:
1555
1556 logger: 'file'
1557
1558 Then you can choose which kind of messages you want to actually log:
1559
1560 log: 'core' # will log debug, info, warnings, errors,
1561 # and messages from Dancer2 itself
1562 log: 'debug' # will log debug, info, warning and errors
1563 log: 'info' # will log info, warning and errors
1564 log: 'warning' # will log warning and errors
1565 log: 'error' # will log only errors
1566
1567 If you're using the "file" logging engine, a directory "appdir/logs"
1568 will be created and will host one logfile per environment. The log
1569 message contains the time it was written, the PID of the current
1570 process, the message and the caller information (file and line).
1571
1572 Logging your own messages
1573 Just call debug <https://metacpan.org/pod/Dancer2::Manual#debug>, info
1574 <https://metacpan.org/pod/Dancer2::Manual#info>, warning
1575 <https://metacpan.org/pod/Dancer2::Manual#warning> or error
1576 <https://metacpan.org/pod/Dancer2::Manual#error> with your message:
1577
1578 debug "This is a debug message from my app.";
1579
1581 Using Plack::Test
1582 Plack::Test receives a common web request (using standard HTTP::Request
1583 objects), fakes a web server in order to create a proper PSGI request,
1584 and sends it to the web application. When the web application returns a
1585 PSGI response (which Dancer applications do), it will then convert it
1586 to a common web response (as a standard HTTP::Response object).
1587
1588 This allows you to then create requests in your test, create the code
1589 reference for your web application, call them, and receive a response
1590 object, which can then be tested.
1591
1592 Basic Example
1593
1594 Assuming there is a web application:
1595
1596 # MyApp.pm
1597 package MyApp;
1598 use Dancer2;
1599 get '/' => sub {'OK'};
1600 1;
1601
1602 The following test base.t is created:
1603
1604 # base.t
1605 use strict;
1606 use warnings;
1607 use Test::More tests => 2;
1608 use Plack::Test;
1609 use HTTP::Request;
1610 use MyApp;
1611
1612 Creating a coderef for the application using the "to_app" keyword:
1613
1614 my $app = MyApp->to_app;
1615
1616 Creating a test object from Plack::Test for the application:
1617
1618 my $test = Plack::Test->create($app);
1619
1620 Creating the first request object and sending it to the test object to
1621 receive a response:
1622
1623 my $request = HTTP::Request->new( GET => '/' );
1624 my $response = $test->request($request);
1625
1626 It can now be tested:
1627
1628 ok( $response->is_success, '[GET /] Successful request' );
1629 is( $response->content, 'OK', '[GET /] Correct content' );
1630
1631 Putting it together
1632
1633 # base.t
1634 use strict;
1635 use warnings;
1636 use Test::More;
1637 use Plack::Test;
1638 use HTTP::Request::Common;
1639 use MyApp;
1640
1641 my $test = Plack::Test->create( MyApp->to_app );
1642 my $response = $test->request( GET '/' );
1643
1644 ok( $response->is_success, '[GET /] Successful request' );
1645 is( $response->content, 'OK', '[GET /] Correct content' );
1646
1647 done_testing();
1648
1649 Subtests
1650
1651 Tests can be separated using Test::More's "subtest" functionality, thus
1652 creating multiple self-contained tests that don't overwrite each other.
1653
1654 Assuming we have a different app that has two states we want to test:
1655
1656 # MyApp.pm
1657 package MyApp;
1658 use Dancer2;
1659 set serializer => 'JSON';
1660
1661 get '/:user' => sub {
1662 my $user = route_parameters->get('user');
1663
1664 $user and return { user => $user };
1665
1666 return {};
1667 };
1668
1669 1;
1670
1671 This is a contrived example of a route that checks for a user
1672 parameter. If it exists, it returns it in a hash with the key 'user'.
1673 If not, it returns an empty hash
1674
1675 # param.t
1676 use strict;
1677 use warnings;
1678 use Test::More;
1679 use Plack::Test;
1680 use HTTP::Request::Common;
1681 use MyApp;
1682
1683 my $test = Plack::Test->create( MyApp->to_app );
1684
1685 subtest 'A empty request' => sub {
1686 my $res = $test->request( GET '/' );
1687 ok( $res->is_success, 'Successful request' );
1688 is( $res->content '{}', 'Empty response back' );
1689 };
1690
1691 subtest 'Request with user' => sub {
1692 my $res = $test->request( GET '/?user=sawyer_x' );
1693 ok( $res->is_success, 'Successful request' );
1694 is( $res->content '{"user":"sawyer_x"}', 'Empty response back' );
1695 };
1696
1697 done_testing();
1698
1699 Cookies
1700
1701 To handle cookies, which are mostly used for maintaining sessions, the
1702 following modules can be used:
1703
1704 · Test::WWW::Mechanize::PSGI
1705
1706 · LWP::Protocol::PSGI
1707
1708 · HTTP::Cookies
1709
1710 Taking the previous test, assuming it actually creates and uses cookies
1711 for sessions:
1712
1713 # ... all the use statements
1714 use HTTP::Cookies;
1715
1716 my $jar = HTTP::Cookies->new;
1717 my $test = Plack::Test->create( MyApp->to_app );
1718
1719 subtest 'A empty request' => sub {
1720 my $res = $test->request( GET '/' );
1721 ok( $res->is_success, 'Successful request' );
1722 is( $res->content '{}', 'Empty response back' );
1723 $jar->extract_cookies($res);
1724 ok( $jar->as_string, 'We have cookies!' );
1725 };
1726
1727 subtest 'Request with user' => sub {
1728 my $req = GET '/?user=sawyer_x';
1729 $jar->add_cookie_header($req);
1730 my $res = $test->request($req);
1731 ok( $res->is_success, 'Successful request' );
1732 is( $res->content '{"user":"sawyer_x"}', 'Empty response back' );
1733 $jar->extract_cookies($res);
1734
1735 ok( ! $jar->as_string, 'All cookies deleted' );
1736 };
1737
1738 done_testing();
1739
1740 Here a cookie jar is created, all requests and responses, existing
1741 cookies, as well as cookies that were deleted by the response, are
1742 checked.
1743
1744 Accessing the configuration file
1745
1746 By importing Dancer2 in the command line scripts, there is full access
1747 to the configuration using the imported keywords:
1748
1749 use strict;
1750 use warnings;
1751 use Test::More;
1752 use Plack::Test;
1753 use HTTP::Request::Common;
1754 use MyApp;
1755 use Dancer2;
1756
1757 my $appname = config->{'appname'};
1758 diag "Testing $appname";
1759
1760 # ...
1761
1763 Carton
1764 What it does
1765
1766 Carton sets up a local copy of your project prerequisites. You only
1767 need to define them in a file and ask Carton to download all of them
1768 and set them up. When you want to deploy your app, you just carry the
1769 git clone and ask Carton to set up the environment again and you will
1770 then be able to run it.
1771
1772 The benefits are multifold:
1773
1774 · Local Directory copy
1775
1776 By putting all the dependencies in a local directory, you can make
1777 sure they aren't updated by someone else by accident and their
1778 versions locked to the version you picked.
1779
1780 · Sync versions
1781
1782 Deciding which versions of the dependent modules your project needs
1783 allows you to sync this with other developers as well. Now you're
1784 all using the same version and they don't change unless you want
1785 update the versions you want. When updated everyone again uses the
1786 same new version of everything.
1787
1788 · Carry only the requirement, not bundled modules
1789
1790 Instead of bundling the modules, you only actually bundle the
1791 requirements. Carton builds them for you when you need it.
1792
1793 Setting it up
1794
1795 First set up a new app:
1796
1797 $ dancer2 -a MyApp
1798 ...
1799
1800 Delete the files that are not needed:
1801
1802 $ rm -f Makefile.PL MANIFEST MANIFEST.SKIP
1803
1804 Create a git repo:
1805
1806 $ git init && git add . && git commit -m "initial commit"
1807
1808 Add a requirement using the cpanfile format:
1809
1810 $ cat > cpanfile
1811 requires 'Dancer2' => 0.155000;
1812 requires 'Template' => 0;
1813 recommends 'URL::Encode::XS' => 0;
1814 recommends 'CGI::Deurl::XS' => 0;
1815 recommends 'HTTP::Parser::XS' => 0;
1816
1817 Ask carton to set it up:
1818
1819 $ carton install
1820 Installing modules using [...]
1821 Successfully installed [...]
1822 ...
1823 Complete! Modules were install into [...]/local
1824
1825 Now we have two files: cpanfile and cpanfile.snapshot. We add both of
1826 them to our Git repository and we make sure we don't accidentally add
1827 the local/ directory Carton created which holds the modules it
1828 installed:
1829
1830 $ echo local/ >> .gitignore
1831 $ git add .gitignore cpanfile cpanfile.snapshot
1832 $ git commit -m "Start using carton"
1833
1834 When we want to update the versions on the production machine, we
1835 simply call:
1836
1837 $ carton install --deployment
1838
1839 By using --deployment we make sure we only install the modules we have
1840 in our cpanfile.snapshot file and do not fallback to querying the CPAN.
1841
1842 FatPacker
1843 App::FatPacker (using its command line interface, fatpack) packs
1844 dependencies into a single file, allowing you to carry a single file
1845 instead of a directory tree.
1846
1847 As long as your application is pure-Perl, you could create a single
1848 file with your application and all of Dancer2 in it.
1849
1850 The following example will demonstrate how this can be done:
1851
1852 Assuming we have an application in lib/MyApp.pm:
1853
1854 package MyApp;
1855 use Dancer2;
1856 get '/' => sub {'OK'};
1857 1;
1858
1859 And we have a handler in bin/app.pl:
1860
1861 use strict;
1862 use warnings;
1863 use FindBin;
1864 use lib "$FindBin::Bin/../lib";
1865 use MyApp;
1866
1867 MyApp->to_app;
1868
1869 To fatpack it, we begin by tracing the script:
1870
1871 $ fatpack trace bin/app.pl
1872
1873 This creates a fatpacker.trace file. From this we create the packlists:
1874
1875 $ fatpack packlists-for `cat fatpacker.trace` > packlists
1876
1877 The packlists are stored in a file called packlists.
1878
1879 Now we create the tree using the following command:
1880
1881 $ fatpack tree `cat packlists`
1882
1883 The tree is created under the directory fatlib.
1884
1885 Now we create a file containing the dependency tree, and add our script
1886 to it, using the following command:
1887
1888 $ (fatpack file; cat bin/app.pl) > myapp.pl
1889
1890 This creates a file called myapp.pl with everything in it. Dancer2 uses
1891 MIME::Types which has a database of all MIME types and helps translate
1892 those. The small database file containing all of these types is a
1893 binary and therefore cannot be fatpacked. Hence, it needs to be copied
1894 to the current directory so our script can find it:
1895
1896 $ cp fatlib/MIME/types.db .
1897
1899 Plack middlewares
1900 If you want to use Plack middlewares, you need to enable them using
1901 Plack::Builder as such:
1902
1903 # in app.psgi or any other handler
1904 use MyApp;
1905 use Plack::Builder;
1906
1907 builder {
1908 enable 'Deflater';
1909 enable 'Session', store => 'File';
1910 enable 'Debug', panels => [ qw<DBITrace Memory Timer> ];
1911 MyApp->to_app;
1912 };
1913
1914 The nice thing about this setup is that it will work seamlessly through
1915 Plack or through the internal web server.
1916
1917 # load dev web server (without middlewares)
1918 perl -Ilib app.psgi
1919
1920 # load plack web server (with middlewares)
1921 plackup -I lib app.psgi
1922
1923 You do not need to provide different files for either server.
1924
1925 Path-based middlewares
1926
1927 If you want to set up a middleware for a specific path, you can do that
1928 using Plack::Builder which uses Plack::App::URLMap:
1929
1930 # in your app.psgi or any other handler
1931 use MyApp;
1932 use Plack::Builder;
1933
1934 my $special_handler = sub { ... };
1935
1936 builder {
1937 mount '/special' => $special_handler;
1938 mount '/' => MyApp->to_app;
1939 };
1940
1941 Removing default middlewares
1942
1943 By default, a Dancer2 app is automatically wrapped with the following
1944 middleware
1945
1946 · Plack::Middleware::FixMissingBodyInRedirect
1947
1948 · Plack::Middleware::Head
1949
1950 You can configure the setting "no_default_middleware" to a true value
1951 to stop your Dancer2 app being wrapped with these default middleware
1952 layers.
1953
1954 # in you Dancer2 app or config.yml
1955 package MyApp;
1956 use Dancer2
1957
1958 set no_default_middleware => true;
1959
1960 This is necessary if you need to add eTag or ContentMD5 headers to
1961 "HEAD" requests, and you are encouraged to manually add those default
1962 middleware back into your PSGI stack.
1963
1964 Running on Perl web servers with plackup
1965
1966 A number of Perl web servers supporting PSGI are available on CPAN:
1967
1968 · Starman
1969
1970 "Starman" is a high performance web server, with support for
1971 preforking, signals, multiple interfaces, graceful restarts and
1972 dynamic worker pool configuration.
1973
1974 · Twiggy
1975
1976 "Twiggy" is an "AnyEvent" web server, it's light and fast.
1977
1978 · Corona
1979
1980 "Corona" is a "Coro" based web server.
1981
1982 To start your application, just run plackup (see Plack and specific
1983 servers above for all available options):
1984
1985 $ plackup bin/app.psgi
1986 $ plackup -E deployment -s Starman --workers=10 -p 5001 -a bin/app.psgi
1987
1988 As you can see, the scaffolded Perl script for your app can be used as
1989 a PSGI startup file.
1990
1991 Enabling content compression
1992
1993 Content compression (gzip, deflate) can be easily enabled via a Plack
1994 middleware (see "Plack::Middleware" in Plack):
1995 Plack::Middleware::Deflater. It's a middleware to encode the response
1996 body in gzip or deflate, based on the "Accept-Encoding" HTTP request
1997 header.
1998
1999 Enable it as you would enable any Plack middleware. First you need to
2000 install Plack::Middleware::Deflater, then in the handler (usually
2001 app.psgi) edit it to use Plack::Builder, as described above:
2002
2003 use Dancer2;
2004 use MyApp;
2005 use Plack::Builder;
2006
2007 builder {
2008 enable 'Deflater';
2009 MyApp->to_app;
2010 };
2011
2012 To test if content compression works, trace the HTTP request and
2013 response before and after enabling this middleware. Among other things,
2014 you should notice that the response is gzip or deflate encoded, and
2015 contains a header "Content-Encoding" set to "gzip" or "deflate".
2016
2017 Running multiple apps with Plack::Builder
2018
2019 You can use Plack::Builder to mount multiple Dancer2 applications on a
2020 PSGI webserver like Starman.
2021
2022 Start by creating a simple app.psgi file:
2023
2024 use OurWiki; # first app
2025 use OurForum; # second app
2026 use Plack::Builder;
2027
2028 builder {
2029 mount '/wiki' => OurWiki->to_app;
2030 mount '/forum' => OurForum->to_app;
2031 };
2032
2033 and now use Starman
2034
2035 plackup -a app.psgi -s Starman
2036
2037 Currently this still demands the same appdir for both (default
2038 circumstance) but in a future version this will be easier to change
2039 while staying very simple to mount.
2040
2041 Running from Apache with Plack
2042
2043 You can run your app from Apache using PSGI (Plack), with a config like
2044 the following:
2045
2046 <VirtualHost myapp.example.com>
2047 ServerName www.myapp.example.com
2048 ServerAlias myapp.example.com
2049 DocumentRoot /websites/myapp.example.com
2050
2051 <Directory /home/myapp/myapp>
2052 AllowOverride None
2053 Order allow,deny
2054 Allow from all
2055 </Directory>
2056
2057 <Location />
2058 SetHandler perl-script
2059 PerlResponseHandler Plack::Handler::Apache2
2060 PerlSetVar psgi_app /websites/myapp.example.com/app.psgi
2061 </Location>
2062
2063 ErrorLog /websites/myapp.example.com/logs/error_log
2064 CustomLog /websites/myapp.example.com/logs/access_log common
2065 </VirtualHost>
2066
2067 To set the environment you want to use for your application (production
2068 or development), you can set it this way:
2069
2070 <VirtualHost>
2071 ...
2072 SetEnv DANCER_ENVIRONMENT "production"
2073 ...
2074 </VirtualHost>
2075
2077 Writing a plugin
2078 See "Writing the plugin" in Dancer2::Plugin for information on how to
2079 author a new plugin for Dancer2.
2080
2082 By default, "use Dancer2" exports all the DSL keywords and sets up the
2083 webapp under the name of the current package. The following tags
2084 control exports and webapp namespace.
2085
2086 · !keyword
2087
2088 If you want to prevent Dancer2 from exporting specific keywords
2089 (perhaps you plan to implement them yourself in a different way, or
2090 they clash with another module you're loading), you can simply
2091 exclude them:
2092
2093 use Test::More;
2094 use Dancer2 qw(!pass);
2095
2096 The above would import all keywords as usual, with the exception of
2097 "pass".
2098
2099 · appname
2100
2101 A larger application may split its source between several packages
2102 to aid maintainability. Dancer2 will create a separate application
2103 for each package, each having separate hooks, config and/or
2104 engines. You can force Dancer2 to collect the route and hooks into
2105 a single application with the "appname" tag; e.g.
2106
2107 package MyApp;
2108 use Dancer2;
2109 get '/foo' => sub {...};
2110
2111 package MyApp::Private;
2112 use Dancer2 appname => MyApp;
2113 get '/bar' => sub {...};
2114
2115 The above would add the "bar" route to the MyApp application.
2116 Dancer2 will not create an application with the name
2117 "MyApp::Private".
2118
2119 · :nopragmas
2120
2121 By default Dancer2 will import three pragmas: strict, warnings, and
2122 utf8. If you require control over the imported pragmas, you can add
2123 :nopragmas to the importing flags, in which case Dancer2 will not
2124 import any pragmas:
2125
2126 use strict;
2127 use warnings;
2128 no warnings 'experimental::smartmatch'; # for example...
2129 use Dancer2 ':nopragmas'; # do not touch the existing pragmas
2130
2131 This way importing "Dancer2" does not change the existing pragmas
2132 setup you have.
2133
2134 When you "use Dancer2", you get an "import" method added into the
2135 current package. This will override previously declared import methods
2136 from other sources, such as Exporter. Dancer2 applications support the
2137 following tags on import:
2138
2139 · with
2140
2141 The "with" tag allows an app to pass one or more config entries to
2142 another app, when it "use"s it.
2143
2144 package MyApp;
2145 use Dancer2;
2146
2147 BEGIN { set session => 'YAML' };
2148 use Blog with => { session => engine('session') };
2149
2150 In this example, the session engine is passed to the "Blog" app.
2151 That way, anything done in the session will be shared between both
2152 apps.
2153
2154 Anything that is defined in the config entry can be passed that
2155 way. If we want to pass the whole config object, it can be done
2156 like so:
2157
2158 use SomeApp with => { %{config()} };
2159
2161 Dancer2 provides you with a DSL (Domain-Specific Language) which makes
2162 implementing your web application trivial.
2163
2164 For example, take the following example:
2165
2166 use Dancer2;
2167
2168 get '/hello/:name' => sub {
2169 my $name = route_parameters->get('name');
2170 };
2171 dance;
2172
2173 "get" and "route_parameters" are keywords provided by Dancer2.
2174
2175 This document lists all keywords provided by Dancer2. It does not cover
2176 additional keywords which may be provided by loaded plugins; see the
2177 documentation for plugins you use to see which additional keywords they
2178 make available to you.
2179
2180 any
2181 Defines a route for multiple HTTP methods at once:
2182
2183 any ['get', 'post'] => '/myaction' => sub {
2184 # code
2185 };
2186
2187 Or even, a route handler that would match any HTTP methods:
2188
2189 any '/myaction' => sub {
2190 # code
2191 };
2192
2193 cookies
2194 Accesses cookies values, it returns a hashref of Dancer2::Core::Cookie
2195 objects:
2196
2197 get '/some_action' => sub {
2198 my $cookie = cookies->{name};
2199 return $cookie->value;
2200 };
2201
2202 In case you have stored something other than a scalar in your cookie:
2203
2204 get '/some_action' => sub {
2205 my $cookie = cookies->{oauth};
2206 my %values = $cookie->value;
2207 return ($values{token}, $values{token_secret});
2208 };
2209
2210 cookie
2211 Accesses a cookie value (or sets it). Note that this method will
2212 eventually be preferred over "set_cookie".
2213
2214 cookie lang => "fr-FR"; # set a cookie and return its value
2215 cookie lang => "fr-FR", expires => "2 hours"; # extra cookie info
2216 cookie "lang" # return a cookie value
2217
2218 If your cookie value is a key/value URI string, like
2219
2220 token=ABC&user=foo
2221
2222 "cookie" will only return the first part ("token=ABC") if called in
2223 scalar context. Use list context to fetch them all:
2224
2225 my @values = cookie "name";
2226
2227 config
2228 Accesses the configuration of the application:
2229
2230 get '/appname' => sub {
2231 return "This is " . config->{appname};
2232 };
2233
2234 content
2235 Sets the content for the response. This only works within a delayed
2236 response.
2237
2238 This will crash:
2239
2240 get '/' => sub {
2241 # THIS WILL CRASH
2242 content 'Hello, world!';
2243 };
2244
2245 But this will work just fine:
2246
2247 get '/' => sub {
2248 delayed {
2249 content 'Hello, world!';
2250 ...
2251 };
2252 };
2253
2254 content_type
2255 Sets the content-type rendered, for the current route handler:
2256
2257 get '/cat/:txtfile' => sub {
2258 content_type 'text/plain';
2259
2260 # here we can dump the contents of route_parameters->get('txtfile')
2261 };
2262
2263 You can use abbreviations for content types. For instance:
2264
2265 get '/svg/:id' => sub {
2266 content_type 'svg';
2267
2268 # here we can dump the image with id route_parameters->get('id')
2269 };
2270
2271 Note that if you want to change the default content-type for every
2272 route, it is easier to change the "content_type" setting instead.
2273
2274 dance
2275 Alias for the "start" keyword.
2276
2277 dancer_version
2278 Returns the version of Dancer. If you need the major version, do
2279 something like:
2280
2281 int(dancer_version);
2282
2283 debug
2284 Logs a message of debug level:
2285
2286 debug "This is a debug message";
2287
2288 See Dancer2::Core::Role::Logger for details on how to configure where
2289 log messages go.
2290
2291 decode_json ($string)
2292 Deserializes a JSON structure from an UTF-8 binary string.
2293
2294 dirname
2295 Returns the dirname of the path given:
2296
2297 my $dir = dirname($some_path);
2298
2299 encode_json ($structure)
2300 Serializes a structure to a UTF-8 binary JSON string.
2301
2302 Calling this function will not trigger the serialization's hooks.
2303
2304 engine
2305 Given a namespace, returns the current engine object
2306
2307 my $template_engine = engine 'template';
2308 my $html = $template_engine->apply_renderer(...);
2309 $template_engine->apply_layout($html);
2310
2311 error
2312 Logs a message of error level:
2313
2314 error "This is an error message";
2315
2316 See Dancer2::Core::Role::Logger for details on how to configure where
2317 log messages go.
2318
2319 false
2320 Constant that returns a false value (0).
2321
2322 forward
2323 Runs an "internal redirect" of the current route to another route. More
2324 formally; when "forward" is executed, the current dispatch of the route
2325 is aborted, the request is modified (altering query params or request
2326 method), and the modified request following a new route is dispatched
2327 again. Any remaining code (route and hooks) from the current dispatch
2328 will never be run and the modified route's dispatch will execute hooks
2329 for the new route normally.
2330
2331 It effectively lets you chain routes together in a clean manner.
2332
2333 get '/demo/articles/:article_id' => sub {
2334
2335 # you'll have to implement this next sub yourself :)
2336 change_the_main_database_to_demo();
2337
2338 forward "/articles/" . route_parameters->get('article_id');
2339 };
2340
2341 In the above example, the users that reach /demo/articles/30 will
2342 actually reach /articles/30 but we've changed the database to demo
2343 before.
2344
2345 This is pretty cool because it lets us retain our paths and offer a
2346 demo database by merely going to /demo/....
2347
2348 You'll notice that in the example we didn't indicate whether it was GET
2349 or POST. That is because "forward" chains the same type of route the
2350 user reached. If it was a GET, it will remain a GET (but if you do need
2351 to change the method, you can do so; read on below for details.)
2352
2353 Also notice that "forward" only redirects to a new route. It does not
2354 redirect the requests involving static files. This is because static
2355 files are handled before Dancer2 tries to match the request to a route
2356 - static files take higher precedence.
2357
2358 This means that you will not be able to "forward" to a static file. If
2359 you wish to do so, you have two options: either redirect (asking the
2360 browser to make another request, but to a file path instead) or use
2361 "send_file" to provide a file.
2362
2363 WARNING: Any code after a "forward" is ignored, until the end of the
2364 route. It's not necessary to use "return" with "forward" anymore.
2365
2366 get '/foo/:article_id' => sub {
2367 if ($condition) {
2368 forward "/articles/" . route_parameters->get('article_id');
2369 # The following code WILL NOT BE executed
2370 do_stuff();
2371 }
2372
2373 more_stuff();
2374 };
2375
2376 Note that "forward" doesn't parse GET arguments. So, you can't use
2377 something like:
2378
2379 forward '/home?authorized=1';
2380
2381 But "forward" supports an optional hashref with parameters to be added
2382 to the actual parameters:
2383
2384 forward '/home', { authorized => 1 };
2385
2386 Finally, you can add some more options to the "forward" method, in a
2387 third argument, also as a hashref. That option is currently only used
2388 to change the method of your request. Use with caution.
2389
2390 forward '/home', { auth => 1 }, { method => 'POST' };
2391
2392 from_dumper ($structure)
2393 Deserializes a Data::Dumper structure.
2394
2395 from_json ($string, \%options)
2396 Deserializes a JSON structure from a string. You should probably use
2397 "decode_json" which expects a UTF-8 encoded binary string and handles
2398 decoding it for you.
2399
2400 from_yaml ($structure)
2401 Deserializes a YAML structure.
2402
2403 get
2404 Defines a route for HTTP GET requests to the given path:
2405
2406 get '/' => sub {
2407 return "Hello world";
2408 }
2409
2410 Note that a route to match HEAD requests is automatically created as
2411 well.
2412
2413 halt
2414 Sets a response object with the content given.
2415
2416 When used as a return value from a hook, this breaks the execution flow
2417 and renders the response immediately:
2418
2419 hook before => sub {
2420 if ($some_condition) {
2421 halt("Unauthorized");
2422
2423 # this code is not executed
2424 do_stuff();
2425 }
2426 };
2427
2428 get '/' => sub {
2429 "hello there";
2430 };
2431
2432 WARNING: Issuing a halt immediately exits the current route, and
2433 performs the halt. Thus, any code after a halt is ignored, until the
2434 end of the route. Hence, it's not necessary anymore to use "return"
2435 with halt.
2436
2437 response_headers
2438 Adds custom headers to response:
2439
2440 get '/send/headers', sub {
2441 response_headers 'X-Foo' => 'bar', 'X-Bar' => 'foo';
2442 }
2443
2444 response_header
2445 Adds a custom header to response:
2446
2447 get '/send/header', sub {
2448 response_header 'x-my-header' => 'shazam!';
2449 }
2450
2451 Note that it will overwrite the old value of the header, if any. To
2452 avoid that, see "push_response_header".
2453
2454 push_response_header
2455 Do the same as "response_header", but allow for multiple headers with
2456 the same name.
2457
2458 get '/send/header', sub {
2459 push_response_header 'x-my-header' => '1';
2460 push_response_header 'x-my-header' => '2';
2461 # will result in two headers "x-my-header" in the response
2462 }
2463
2464 prepare_app
2465 You can introduce code you want to run when your app is loaded, similar
2466 to the "prepare_app" in Plack::Middleware.
2467
2468 prepare_app {
2469 my $app = shift;
2470
2471 ... # do your thing
2472 };
2473
2474 You should not close over the App instance, since you receive it as a
2475 first argument. If you close over it, you will have a memory leak.
2476
2477 my $app = app();
2478
2479 prepare_app {
2480 do_something_with_app($app); # MEMORY LEAK
2481 };
2482
2483 hook
2484 Adds a hook at some position. For example :
2485
2486 hook before_serializer => sub {
2487 my $content = shift;
2488 ...
2489 };
2490
2491 There can be multiple hooks assigned to a given position, and each will
2492 be executed in order.
2493
2494 See the HOOKS section for a list of available hooks.
2495
2496 info
2497 Logs a message of "info" level:
2498
2499 info "This is an info message";
2500
2501 See Dancer2::Core::Role::Logger for details on how to configure where
2502 log messages go.
2503
2504 mime
2505 Shortcut to access the instance object of Dancer2::Core::MIME. You
2506 should read the Dancer2::Core::MIME documentation for full details, but
2507 the most commonly-used methods are summarized below:
2508
2509 # set a new mime type
2510 mime->add_type( foo => 'text/foo' );
2511
2512 # set a mime type alias
2513 mime->add_alias( f => 'foo' );
2514
2515 # get mime type for an alias
2516 my $m = mime->for_name( 'f' );
2517
2518 # get mime type for a file (based on extension)
2519 my $m = mime->for_file( "foo.bar" );
2520
2521 # get current defined default mime type
2522 my $d = mime->default;
2523
2524 # set the default mime type using config.yml
2525 # or using the set keyword
2526 set default_mime_type => 'text/plain';
2527
2528 params
2529 This method should be called from a route handler. It's an alias for
2530 the Dancer2::Core::Request params accessor. It returns a hash (in list
2531 context) or a hash reference (in scalar context) to all defined
2532 parameters. Check "param" below to access quickly to a single parameter
2533 value.
2534
2535 post '/login' => sub {
2536 # get all parameters as a single hash
2537 my %all_parameters = params;
2538
2539 // request all parmameters from a specific source: body, query, route
2540 my %body_parameters = params('body');
2541 my %route_parameters = params('route');
2542 my %query_parameters = params('query');
2543
2544 # any $source that is not body, query, or route generates an exception
2545 params('fake_source'); // Unknown source params "fake_source"
2546 };
2547
2548 We now recommend using one of the specific keywords for parameters
2549 ("route_parameters", "query_parameters", and "body_parameters") instead
2550 of "params" or "param".
2551
2552 param
2553 This method should be called from a route handler. This method is an
2554 accessor to the parameters hash table.
2555
2556 post '/login' => sub {
2557 my $username = param "user";
2558 my $password = param "pass";
2559 # ...
2560 };
2561
2562 We now recommend using one of the specific keywords for parameters
2563 ("route_parameters", "query_parameters", and "body_parameters") instead
2564 of "params" or "param".
2565
2566 route_parameters
2567 Returns a Hash::MultiValue object from the route parameters.
2568
2569 # /hello
2570 get '/:foo' => sub {
2571 my $foo = route_parameters->get('foo');
2572 };
2573
2574 query_parameters
2575 Returns a Hash::MultiValue object from the request parameters.
2576
2577 /?foo=hello
2578 get '/' => sub {
2579 my $name = query_parameters->get('foo');
2580 };
2581
2582 /?name=Alice&name=Bob
2583 get '/' => sub {
2584 my @names = query_parameters->get_all('name');
2585 };
2586
2587 body_parameters
2588 Returns a Hash::MultiValue object from the body parameters.
2589
2590 post '/' => sub {
2591 my $last_name = body_parameters->get('name');
2592 my @all_names = body_parameters->get_all('name');
2593 };
2594
2595 pass
2596 This method should be called from a route handler. Tells Dancer2 to
2597 pass the processing of the request to the next matching route.
2598
2599 WARNING: Issuing a pass immediately exits the current route, and
2600 performs the pass. Thus, any code after a pass is ignored, until the
2601 end of the route. Hence, it's not necessary anymore to use "return"
2602 with pass.
2603
2604 get '/some/route' => sub {
2605 if (...) {
2606 # we want to let the next matching route handler process this one
2607 pass(...);
2608
2609 # this code will be ignored
2610 do_stuff();
2611 }
2612 };
2613
2614 WARNING: You cannot set the content before passing and have it remain,
2615 even if you use the "content" keyword or set it directly in the
2616 response object.
2617
2618 patch
2619 Defines a route for HTTP PATCH requests to the given URL:
2620
2621 patch '/resource' => sub { ... };
2622
2623 ("PATCH" is a relatively new and not-yet-common HTTP verb, which is
2624 intended to work as a "partial-PUT", transferring just the changes;
2625 please see RFC5789 <http://tools.ietf.org/html/rfc5789> for further
2626 details.)
2627
2628 path
2629 Concatenates multiple paths together, without worrying about the
2630 underlying operating system:
2631
2632 my $path = path(dirname($0), 'lib', 'File.pm');
2633
2634 It also normalizes (cleans) the path aesthetically. It does not verify
2635 whether the path exists, though.
2636
2637 post
2638 Defines a route for HTTP POST requests to the given URL:
2639
2640 post '/' => sub {
2641 return "Hello world";
2642 }
2643
2644 prefix
2645 Defines a prefix for each route handler, like this:
2646
2647 prefix '/home';
2648
2649 From here, any route handler is defined to /home/*:
2650
2651 get '/page1' => sub {}; # will match '/home/page1'
2652
2653 You can unset the prefix value:
2654
2655 prefix undef;
2656 get '/page1' => sub {}; # will match /page1
2657
2658 For a safer alternative you can use lexical prefix like this:
2659
2660 prefix '/home' => sub {
2661 ## Prefix is set to '/home' here
2662
2663 get ...;
2664 get ...;
2665 };
2666 ## prefix reset to the previous version here
2667
2668 This makes it possible to nest prefixes:
2669
2670 prefix '/home' => sub {
2671 ## some routes
2672
2673 prefix '/private' => sub {
2674 ## here we are under /home/private...
2675
2676 ## some more routes
2677 };
2678 ## back to /home
2679 };
2680 ## back to the root
2681
2682 Notice: Once you have a prefix set, do not add a caret to the regex:
2683
2684 prefix '/foo';
2685 get qr{^/bar} => sub { ... } # BAD BAD BAD
2686 get qr{/bar} => sub { ... } # Good!
2687
2688 del
2689 Defines a route for HTTP DELETE requests to the given URL:
2690
2691 del '/resource' => sub { ... };
2692
2693 options
2694 Defines a route for HTTP OPTIONS requests to the given URL:
2695
2696 options '/resource' => sub { ... };
2697
2698 put
2699 Defines a route for HTTP PUT requests to the given URL:
2700
2701 put '/resource' => sub { ... };
2702
2703 redirect
2704 Generates a HTTP redirect (302). You can either redirect to a complete
2705 different site or within the application:
2706
2707 get '/twitter', sub {
2708 redirect 'http://twitter.com/me';
2709 # Any code after the redirect will not be executed.
2710 };
2711
2712 WARNING: Issuing a "redirect" immediately exits the current route.
2713 Thus, any code after a "redirect" is ignored, until the end of the
2714 route. Hence, it's not necessary anymore to use "return" with
2715 "redirect".
2716
2717 You can also force Dancer to return a specific 300-ish HTTP response
2718 code:
2719
2720 get '/old/:resource', sub {
2721 redirect '/new/' . route_parameters->get('resource'), 301;
2722 };
2723
2724 request
2725 Returns a Dancer2::Core::Request object representing the current
2726 request.
2727
2728 See the Dancer2::Core::Request documentation for the methods you can
2729 call, for example:
2730
2731 request->referer; # value of the HTTP referer header
2732 request->remote_address; # user's IP address
2733 request->user_agent; # User-Agent header value
2734
2735 request_header
2736 Returns request header(s).
2737
2738 get '/get/headers' => sub {
2739 my $xfoo = request_header 'X-Foo';
2740 ...
2741 };
2742
2743 send_as
2744 Allows the current route handler to return specific content types to
2745 the client using either a specified serializer or as html.
2746
2747 Any Dancer2 serializer may be used. The specified serializer class will
2748 be loaded if required, or an error generated if the class can not be
2749 found. Serializer configuration may be added to your apps "engines"
2750 configuration.
2751
2752 If "html" is specified, the content will be returned assuming it is
2753 HTML with appropriate "Content-Type" headers and encoded using the apps
2754 configured "charset" (or UTF-8).
2755
2756 set serializer => 'YAML';
2757 set template => 'TemplateToolkit';
2758
2759 # returns html (not YAML)
2760 get '/' => sub { send_as html => template 'welcome.tt' };
2761
2762 # return json (not YAML)
2763 get '/json' => sub {
2764 send_as JSON => [ some => { data => 'structure' } ];
2765 };
2766
2767 "send_as" uses "send_file" to return the content immediately. You may
2768 pass any option "send_file" supports as an extra option. For example:
2769
2770 # return json with a custom content_type header
2771 get '/json' => sub {
2772 send_as JSON => [ some => { data => 'structure' } ],
2773 { content_type => 'application/json; charset=UTF-8' },
2774 };
2775
2776 WARNING: Issuing a send_as immediately exits the current route, and
2777 performs the "send_as". Thus, any code after a "send_as" is ignored,
2778 until the end of the route. Hence, it's not necessary to use "return"
2779 with "send_as".
2780
2781 get '/some/route' => sub {
2782 if (...) {
2783 send_as JSON => $some_data;
2784
2785 # this code will be ignored
2786 do_stuff();
2787 }
2788 };
2789
2790 send_error
2791 Returns a HTTP error. By default the HTTP code returned is 500:
2792
2793 get '/photo/:id' => sub {
2794 if (...) {
2795 send_error("Not allowed", 403);
2796 } else {
2797 # return content
2798 }
2799 }
2800
2801 WARNING: Issuing a send_error immediately exits the current route, and
2802 performs the "send_error". Thus, any code after a "send_error" is
2803 ignored, until the end of the route. Hence, it's not necessary anymore
2804 to use "return" with "send_error".
2805
2806 get '/some/route' => sub {
2807 if (...) {
2808 # Something bad happened, stop immediately!
2809 send_error(..);
2810
2811 # this code will be ignored
2812 do_stuff();
2813 }
2814 };
2815
2816 send_file
2817 Lets the current route handler send a file to the client. Note that the
2818 path of the file must be relative to the public directory unless you
2819 use the "system_path" option (see below).
2820
2821 get '/download/:file' => sub {
2822 return send_file(route_parameters->get('file'));
2823 }
2824
2825 WARNING: Issuing a "send_file" immediately exits the current route, and
2826 performs the "send_file". Thus, any code after a "send_file" is
2827 ignored, until the end of the route. Hence, it's not necessary anymore
2828 to use "return" with "send_file".
2829
2830 get '/some/route' => sub {
2831 if (...) {
2832 # OK, send her what she wants...
2833 send_file(...);
2834
2835 # this code will be ignored
2836 do_stuff();
2837 }
2838 };
2839
2840 "send_file" will use PSGI streaming if the server supports it (most, if
2841 not all, do). You can explicitly disable streaming by passing
2842 "streaming => 0" as an option to "send_file".
2843
2844 get '/download/:file' => sub {
2845 send_file( route_parameters->get('file'), streaming => 0 );
2846 }
2847
2848 The content-type will be set depending on the current MIME types
2849 definition (see "mime" if you want to define your own).
2850
2851 If your filename does not have an extension, you are passing in a
2852 filehandle, or you need to force a specific mime type, you can pass it
2853 to "send_file" as follows:
2854
2855 send_file(route_parameters->get('file'), content_type => 'image/png');
2856 send_file($fh, content_type => 'image/png');
2857
2858 Also, you can use your aliases or file extension names on
2859 "content_type", like this:
2860
2861 send_file(route_parameters->get('file'), content_type => 'png');
2862
2863 The encoding of the file or filehandle may be specified by passing both
2864 the "content_type" and "charset" options. For example:
2865
2866 send_file($fh, content_type => 'text/csv', charset => 'utf-8' );
2867
2868 For files outside your public folder, you can use the "system_path"
2869 switch. Just bear in mind that its use needs caution as it can be
2870 dangerous.
2871
2872 send_file('/etc/passwd', system_path => 1);
2873
2874 If you have your data in a scalar variable, "send_file" can be useful
2875 as well. Pass a reference to that scalar, and "send_file" will behave
2876 as if there was a file with that contents:
2877
2878 send_file( \$data, content_type => 'image/png' );
2879
2880 Note that Dancer is unable to guess the content type from the data
2881 contents. Therefore you might need to set the "content_type" properly.
2882 For this kind of usage an attribute named "filename" can be useful. It
2883 is used as the Content-Disposition header, to hint the browser about
2884 the filename it should use.
2885
2886 send_file( \$data, content_type => 'image/png'
2887 filename => 'onion.png' );
2888
2889 By default the Content-Disposition header uses the "attachment" type,
2890 which triggers a "Save" dialog in some browsers. Supply a
2891 "content_disposition" attribute of "inline" to have the file displayed
2892 inline by the browser.
2893
2894 set
2895 Defines a setting:
2896
2897 set something => 'value';
2898
2899 You can set more than one value at once:
2900
2901 set something => 'value', otherthing => 'othervalue';
2902
2903 setting
2904 Returns the value of a given setting:
2905
2906 setting('something'); # 'value'
2907
2908 session
2909 Provides access to all data stored in the user's session (if any).
2910
2911 It can also be used as a setter to store data in the session:
2912
2913 # getter example
2914 get '/user' => sub {
2915 if (session('user')) {
2916 return "Hello, ".session('user')->name;
2917 }
2918 };
2919
2920 # setter example
2921 post '/user/login' => sub {
2922 ...
2923 if ($logged_in) {
2924 session user => $user;
2925 }
2926 ...
2927 };
2928
2929 You may also need to clear a session:
2930
2931 # destroy session
2932 get '/logout' => sub {
2933 ...
2934 app->destroy_session;
2935 ...
2936 };
2937
2938 If you need to fetch the session ID being used for any reason:
2939
2940 my $id = session->id;
2941
2942 splat
2943 Returns the list of captures made from a route handler with a route
2944 pattern which includes wildcards:
2945
2946 get '/file/*.*' => sub {
2947 my ($file, $extension) = splat;
2948 ...
2949 };
2950
2951 There is also the extensive splat (A.K.A. "megasplat"), which allows
2952 extensive greedier matching, available using two asterisks. The
2953 additional path is broken down and returned as an arrayref:
2954
2955 get '/entry/*/tags/**' => sub {
2956 my ( $entry_id, $tags ) = splat;
2957 my @tags = @{$tags};
2958 };
2959
2960 The "splat" keyword in the above example for the route
2961 /entry/1/tags/one/two would set $entry_id to 1 and $tags to "['one',
2962 'two']".
2963
2964 start
2965 Starts the application or the standalone server (depending on the
2966 deployment choices).
2967
2968 This keyword should be called at the very end of the script, once all
2969 routes are defined. At this point, Dancer2 takes over.
2970
2971 to_app
2972 Returns the PSGI coderef for the current (and only the current)
2973 application.
2974
2975 You can call it as a method on the class or as a DSL:
2976
2977 my $app = MyApp->to_app;
2978
2979 # or
2980
2981 my $app = to_app;
2982
2983 There is a Dancer Advent Calendar article
2984 <http://advent.perldancer.org/2014/9> covering this keyword and its
2985 usage further.
2986
2987 psgi_app
2988 Provides the same functionality as "to_app" but uses the deprecated
2989 Dispatcher engine. You should use "to_app" instead.
2990
2991 status
2992 Changes the status code provided by an action. By default, an action
2993 will produce an "HTTP 200 OK" status code, meaning everything is OK:
2994
2995 get '/download/:file' => {
2996 if (! -f route_parameters->get('file')) {
2997 status 'not_found';
2998 return "File does not exist, unable to download";
2999 }
3000 # serving the file...
3001 };
3002
3003 In that example, Dancer will notice that the status has changed, and
3004 will render the response accordingly.
3005
3006 The "status" keyword receives either a numeric status code or its name
3007 in lower case, with underscores as a separator for blanks - see the
3008 list in "HTTP CODES" in Dancer2::Core::HTTP. As an example, The above
3009 call translates to setting the code to 404.
3010
3011 template
3012 Returns the response of processing the given template with the given
3013 parameters (and optional settings), wrapping it in the default or
3014 specified layout too, if layouts are in use.
3015
3016 An example of a route handler which returns the result of using
3017 template to build a response with the current template engine:
3018
3019 get '/' => sub {
3020 ...
3021 return template 'some_view', { token => 'value'};
3022 };
3023
3024 Note that "template" simply returns the content, so when you use it in
3025 a route handler, if execution of the route handler should stop at that
3026 point, make sure you use "return" to ensure your route handler returns
3027 the content.
3028
3029 Since "template" just returns the result of rendering the template, you
3030 can also use it to perform other templating tasks, e.g. generating
3031 emails:
3032
3033 post '/some/route' => sub {
3034 if (...) {
3035 email {
3036 to => 'someone@example.com',
3037 from => 'foo@example.com',
3038 subject => 'Hello there',
3039 msg => template('emails/foo', { name => body_parameters->get('name') }),
3040 };
3041
3042 return template 'message_sent';
3043 } else {
3044 return template 'error';
3045 }
3046 };
3047
3048 Compatibility notice: "template" was changed in version 1.3090 to
3049 immediately interrupt execution of a route handler and return the
3050 content, as it's typically used at the end of a route handler to return
3051 content. However, this caused issues for some people who were using
3052 "template" to generate emails etc, rather than accessing the template
3053 engine directly, so this change has been reverted in 1.3091.
3054
3055 The first parameter should be a template available in the views
3056 directory, the second one (optional) is a hashref of tokens to
3057 interpolate, and the third (again optional) is a hashref of options.
3058
3059 For example, to disable the layout for a specific request:
3060
3061 get '/' => sub {
3062 template 'index', {}, { layout => undef };
3063 };
3064
3065 Or to request a specific layout, of course:
3066
3067 get '/user' => sub {
3068 template 'user', {}, { layout => 'user' };
3069 };
3070
3071 Some tokens are automatically added to your template ("perl_version",
3072 "dancer_version", "settings", "request", "vars" and, if you have
3073 sessions enabled, "session"). Check Default Template Variables for
3074 further details.
3075
3076 to_dumper ($structure)
3077 Serializes a structure with Data::Dumper.
3078
3079 Calling this function will not trigger the serialization's hooks.
3080
3081 to_json ($structure, \%options)
3082 Serializes a structure to JSON. You should probably use "encode_json"
3083 instead which handles encoding the result for you.
3084
3085 to_yaml ($structure)
3086 Serializes a structure to YAML.
3087
3088 Calling this function will not trigger the serialization's hooks.
3089
3090 true
3091 Constant that returns a true value (1).
3092
3093 upload
3094 Provides access to file uploads. Any uploaded file is accessible as a
3095 Dancer2::Core::Request::Upload object. You can access all parsed
3096 uploads via:
3097
3098 post '/some/route' => sub {
3099 my $file = upload('file_input_foo');
3100 # $file is a Dancer2::Core::Request::Upload object
3101 };
3102
3103 If you named multiple inputs of type "file" with the same name, the
3104 "upload" keyword would return an Array of
3105 Dancer2::Core::Request::Upload objects:
3106
3107 post '/some/route' => sub {
3108 my ($file1, $file2) = upload('files_input');
3109 # $file1 and $file2 are Dancer2::Core::Request::Upload objects
3110 };
3111
3112 You can also access the raw hashref of parsed uploads via the current
3113 "request" object:
3114
3115 post '/some/route' => sub {
3116 my $all_uploads = request->uploads;
3117 # $all_uploads->{'file_input_foo'} is a Dancer2::Core::Request::Upload object
3118 # $all_uploads->{'files_input'} is an arrayref of Dancer2::Core::Request::Upload objects
3119 };
3120
3121 Note that you can also access the filename of the upload received via
3122 the "body_parameters" keyword:
3123
3124 post '/some/route' => sub {
3125 # body_parameters->get('files_input') is the filename of the file uploaded
3126 };
3127
3128 See Dancer2::Core::Request::Upload for details about the interface
3129 provided.
3130
3131 uri_for
3132 Returns a fully-qualified URI for the given path:
3133
3134 get '/' => sub {
3135 redirect uri_for('/path');
3136 # can be something like: http://localhost:5000/path
3137 };
3138
3139 Query string parameters can be provided by passing a hashref as a
3140 second param:
3141
3142 uri_for('/path', { foo => 'bar' });
3143 # would return e.g. http://localhost:5000/path?foo=bar
3144
3145 By default, the parameters will be URL encoded:
3146
3147 uri_for('/path', { foo => 'hope;faith' });
3148 # would return http://localhost:5000/path?foo=hope%3Bfaith
3149
3150 If desired (for example, if you've already encoded your query
3151 parameters and you want to prevent double encoding) you can disable URL
3152 encoding via a third parameter:
3153
3154 uri_for('/path', { foo => 'qux%3Dquo' }, 1);
3155 # would return http://localhost:5000/path?foo=qux%3Dquo
3156
3157 captures
3158 Returns a reference to a copy of "%+", if there are named captures in
3159 the route's regular expression.
3160
3161 Named captures are a feature of Perl 5.10, and are not supported in
3162 earlier versions:
3163
3164 get qr{
3165 / (?<object> user | ticket | comment )
3166 / (?<action> delete | find )
3167 / (?<id> \d+ )
3168 /?$
3169 }x
3170 , sub {
3171 my $value_for = captures;
3172 "i don't want to $$value_for{action} the $$value_for{object} $$value_for{id} !"
3173 };
3174
3175 var
3176 Provides an accessor for variables shared between hooks and route
3177 handlers. Given a key/value pair, it sets a variable:
3178
3179 hook before => sub {
3180 var foo => 42;
3181 };
3182
3183 Later, route handlers and other hooks will be able to read that
3184 variable:
3185
3186 get '/path' => sub {
3187 my $foo = var 'foo';
3188 ...
3189 };
3190
3191 vars
3192 Returns the hashref of all shared variables set during the hook/route
3193 chain with the "var" keyword:
3194
3195 get '/path' => sub {
3196 if (vars->{foo} eq 42) {
3197 ...
3198 }
3199 };
3200
3201 warning
3202 Logs a warning message through the current logger engine:
3203
3204 warning "This is a warning";
3205
3206 See Dancer2::Core::Role::Logger for details on how to configure where
3207 log messages go.
3208
3210 Dancer Core Developers
3211
3213 This software is copyright (c) 2020 by Alexis Sukrieh.
3214
3215 This is free software; you can redistribute it and/or modify it under
3216 the same terms as the Perl 5 programming language system itself.
3217
3218
3219
3220perl v5.32.0 2020-07-28 Dancer2::Manual(3)