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