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.207000
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 hook
2417 Adds a hook at some position. For example :
2418
2419 hook before_serializer => sub {
2420 my $content = shift;
2421 ...
2422 };
2423
2424 There can be multiple hooks assigned to a given position, and each will
2425 be executed in order.
2426
2427 See the HOOKS section for a list of available hooks.
2428
2429 info
2430 Logs a message of "info" level:
2431
2432 info "This is an info message";
2433
2434 See Dancer2::Core::Role::Logger for details on how to configure where
2435 log messages go.
2436
2437 mime
2438 Shortcut to access the instance object of Dancer2::Core::MIME. You
2439 should read the Dancer2::Core::MIME documentation for full details, but
2440 the most commonly-used methods are summarized below:
2441
2442 # set a new mime type
2443 mime->add_type( foo => 'text/foo' );
2444
2445 # set a mime type alias
2446 mime->add_alias( f => 'foo' );
2447
2448 # get mime type for an alias
2449 my $m = mime->for_name( 'f' );
2450
2451 # get mime type for a file (based on extension)
2452 my $m = mime->for_file( "foo.bar" );
2453
2454 # get current defined default mime type
2455 my $d = mime->default;
2456
2457 # set the default mime type using config.yml
2458 # or using the set keyword
2459 set default_mime_type => 'text/plain';
2460
2461 params
2462 This method should be called from a route handler. It's an alias for
2463 the Dancer2::Core::Request params accessor. It returns a hash (in list
2464 context) or a hash reference (in scalar context) to all defined
2465 parameters. Check "param" below to access quickly to a single parameter
2466 value.
2467
2468 post '/login' => sub {
2469 # get all parameters as a single hash
2470 my %all_parameters = params;
2471
2472 // request all parmameters from a specific source: body, query, route
2473 my %body_parameters = params('body');
2474 my %route_parameters = params('route');
2475 my %query_parameters = params('query');
2476
2477 # any $source that is not body, query, or route generates an exception
2478 params('fake_source'); // Unknown source params "fake_source"
2479 };
2480
2481 We now recommend using one of the specific keywords for parameters
2482 ("route_parameters", "query_parameters", and "body_parameters") instead
2483 of "params" or "param".
2484
2485 param
2486 This method should be called from a route handler. This method is an
2487 accessor to the parameters hash table.
2488
2489 post '/login' => sub {
2490 my $username = param "user";
2491 my $password = param "pass";
2492 # ...
2493 };
2494
2495 We now recommend using one of the specific keywords for parameters
2496 ("route_parameters", "query_parameters", and "body_parameters") instead
2497 of "params" or "param".
2498
2499 route_parameters
2500 Returns a Hash::MultiValue object from the route parameters.
2501
2502 # /hello
2503 get '/:foo' => sub {
2504 my $foo = route_parameters->get('foo');
2505 };
2506
2507 query_parameters
2508 Returns a Hash::MultiValue object from the request parameters.
2509
2510 /?foo=hello
2511 get '/' => sub {
2512 my $name = query_parameters->get('foo');
2513 };
2514
2515 /?name=Alice&name=Bob
2516 get '/' => sub {
2517 my @names = query_parameters->get_all('name');
2518 };
2519
2520 body_parameters
2521 Returns a Hash::MultiValue object from the body parameters.
2522
2523 post '/' => sub {
2524 my $last_name = body_parameters->get('name');
2525 my @all_names = body_parameters->get_all('name');
2526 };
2527
2528 pass
2529 This method should be called from a route handler. Tells Dancer2 to
2530 pass the processing of the request to the next matching route.
2531
2532 WARNING: Issuing a pass immediately exits the current route, and
2533 performs the pass. Thus, any code after a pass is ignored, until the
2534 end of the route. Hence, it's not necessary anymore to use "return"
2535 with pass.
2536
2537 get '/some/route' => sub {
2538 if (...) {
2539 # we want to let the next matching route handler process this one
2540 pass(...);
2541
2542 # this code will be ignored
2543 do_stuff();
2544 }
2545 };
2546
2547 WARNING: You cannot set the content before passing and have it remain,
2548 even if you use the "content" keyword or set it directly in the
2549 response object.
2550
2551 patch
2552 Defines a route for HTTP PATCH requests to the given URL:
2553
2554 patch '/resource' => sub { ... };
2555
2556 ("PATCH" is a relatively new and not-yet-common HTTP verb, which is
2557 intended to work as a "partial-PUT", transferring just the changes;
2558 please see RFC5789 <http://tools.ietf.org/html/rfc5789> for further
2559 details.)
2560
2561 path
2562 Concatenates multiple paths together, without worrying about the
2563 underlying operating system:
2564
2565 my $path = path(dirname($0), 'lib', 'File.pm');
2566
2567 It also normalizes (cleans) the path aesthetically. It does not verify
2568 whether the path exists, though.
2569
2570 post
2571 Defines a route for HTTP POST requests to the given URL:
2572
2573 post '/' => sub {
2574 return "Hello world";
2575 }
2576
2577 prefix
2578 Defines a prefix for each route handler, like this:
2579
2580 prefix '/home';
2581
2582 From here, any route handler is defined to /home/*:
2583
2584 get '/page1' => sub {}; # will match '/home/page1'
2585
2586 You can unset the prefix value:
2587
2588 prefix undef;
2589 get '/page1' => sub {}; # will match /page1
2590
2591 For a safer alternative you can use lexical prefix like this:
2592
2593 prefix '/home' => sub {
2594 ## Prefix is set to '/home' here
2595
2596 get ...;
2597 get ...;
2598 };
2599 ## prefix reset to the previous version here
2600
2601 This makes it possible to nest prefixes:
2602
2603 prefix '/home' => sub {
2604 ## some routes
2605
2606 prefix '/private' => sub {
2607 ## here we are under /home/private...
2608
2609 ## some more routes
2610 };
2611 ## back to /home
2612 };
2613 ## back to the root
2614
2615 Notice: Once you have a prefix set, do not add a caret to the regex:
2616
2617 prefix '/foo';
2618 get qr{^/bar} => sub { ... } # BAD BAD BAD
2619 get qr{/bar} => sub { ... } # Good!
2620
2621 del
2622 Defines a route for HTTP DELETE requests to the given URL:
2623
2624 del '/resource' => sub { ... };
2625
2626 options
2627 Defines a route for HTTP OPTIONS requests to the given URL:
2628
2629 options '/resource' => sub { ... };
2630
2631 put
2632 Defines a route for HTTP PUT requests to the given URL:
2633
2634 put '/resource' => sub { ... };
2635
2636 redirect
2637 Generates a HTTP redirect (302). You can either redirect to a complete
2638 different site or within the application:
2639
2640 get '/twitter', sub {
2641 redirect 'http://twitter.com/me';
2642 # Any code after the redirect will not be executed.
2643 };
2644
2645 WARNING: Issuing a "redirect" immediately exits the current route.
2646 Thus, any code after a "redirect" is ignored, until the end of the
2647 route. Hence, it's not necessary anymore to use "return" with
2648 "redirect".
2649
2650 You can also force Dancer to return a specific 300-ish HTTP response
2651 code:
2652
2653 get '/old/:resource', sub {
2654 redirect '/new/' . route_parameters->get('resource'), 301;
2655 };
2656
2657 request
2658 Returns a Dancer2::Core::Request object representing the current
2659 request.
2660
2661 See the Dancer2::Core::Request documentation for the methods you can
2662 call, for example:
2663
2664 request->referer; # value of the HTTP referer header
2665 request->remote_address; # user's IP address
2666 request->user_agent; # User-Agent header value
2667
2668 request_header
2669 Returns request header(s).
2670
2671 get '/get/headers' => sub {
2672 my $xfoo = request_header 'X-Foo';
2673 ...
2674 };
2675
2676 send_as
2677 Allows the current route handler to return specific content types to
2678 the client using either a specified serializer or as html.
2679
2680 Any Dancer2 serializer may be used. The specified serializer class will
2681 be loaded if required, or an error generated if the class can not be
2682 found. Serializer configuration may be added to your apps "engines"
2683 configuration.
2684
2685 If "html" is specified, the content will be returned assuming it is
2686 HTML with appropriate "Content-Type" headers and encoded using the apps
2687 configured "charset" (or UTF-8).
2688
2689 set serializer => 'YAML';
2690 set template => 'TemplateToolkit';
2691
2692 # returns html (not YAML)
2693 get '/' => sub { send_as html => template 'welcome.tt' };
2694
2695 # return json (not YAML)
2696 get '/json' => sub {
2697 send_as JSON => [ some => { data => 'structure' } ];
2698 };
2699
2700 "send_as" uses "send_file" to return the content immediately. You may
2701 pass any option "send_file" supports as an extra option. For example:
2702
2703 # return json with a custom content_type header
2704 get '/json' => sub {
2705 send_as JSON => [ some => { data => 'structure' } ],
2706 { content_type => 'application/json; charset=UTF-8' },
2707 };
2708
2709 WARNING: Issuing a send_as immediately exits the current route, and
2710 performs the "send_as". Thus, any code after a "send_as" is ignored,
2711 until the end of the route. Hence, it's not necessary to use "return"
2712 with "send_as".
2713
2714 get '/some/route' => sub {
2715 if (...) {
2716 send_as JSON => $some_data;
2717
2718 # this code will be ignored
2719 do_stuff();
2720 }
2721 };
2722
2723 send_error
2724 Returns a HTTP error. By default the HTTP code returned is 500:
2725
2726 get '/photo/:id' => sub {
2727 if (...) {
2728 send_error("Not allowed", 403);
2729 } else {
2730 # return content
2731 }
2732 }
2733
2734 WARNING: Issuing a send_error immediately exits the current route, and
2735 performs the "send_error". Thus, any code after a "send_error" is
2736 ignored, until the end of the route. Hence, it's not necessary anymore
2737 to use "return" with "send_error".
2738
2739 get '/some/route' => sub {
2740 if (...) {
2741 # Something bad happened, stop immediately!
2742 send_error(..);
2743
2744 # this code will be ignored
2745 do_stuff();
2746 }
2747 };
2748
2749 send_file
2750 Lets the current route handler send a file to the client. Note that the
2751 path of the file must be relative to the public directory unless you
2752 use the "system_path" option (see below).
2753
2754 get '/download/:file' => sub {
2755 return send_file(route_parameters->get('file'));
2756 }
2757
2758 WARNING: Issuing a "send_file" immediately exits the current route, and
2759 performs the "send_file". Thus, any code after a "send_file" is
2760 ignored, until the end of the route. Hence, it's not necessary anymore
2761 to use "return" with "send_file".
2762
2763 get '/some/route' => sub {
2764 if (...) {
2765 # OK, send her what she wants...
2766 send_file(...);
2767
2768 # this code will be ignored
2769 do_stuff();
2770 }
2771 };
2772
2773 "send_file" will use PSGI streaming if the server supports it (most, if
2774 not all, do). You can explicitly disable streaming by passing
2775 "streaming => 0" as an option to "send_file".
2776
2777 get '/download/:file' => sub {
2778 send_file( route_parameters->get('file'), streaming => 0 );
2779 }
2780
2781 The content-type will be set depending on the current MIME types
2782 definition (see "mime" if you want to define your own).
2783
2784 If your filename does not have an extension, you are passing in a
2785 filehandle, or you need to force a specific mime type, you can pass it
2786 to "send_file" as follows:
2787
2788 send_file(route_parameters->get('file'), content_type => 'image/png');
2789 send_file($fh, content_type => 'image/png');
2790
2791 Also, you can use your aliases or file extension names on
2792 "content_type", like this:
2793
2794 send_file(route_parameters->get('file'), content_type => 'png');
2795
2796 The encoding of the file or filehandle may be specified by passing both
2797 the "content_type" and "charset" options. For example:
2798
2799 send_file($fh, content_type => 'text/csv', charset => 'utf-8' );
2800
2801 For files outside your public folder, you can use the "system_path"
2802 switch. Just bear in mind that its use needs caution as it can be
2803 dangerous.
2804
2805 send_file('/etc/passwd', system_path => 1);
2806
2807 If you have your data in a scalar variable, "send_file" can be useful
2808 as well. Pass a reference to that scalar, and "send_file" will behave
2809 as if there was a file with that contents:
2810
2811 send_file( \$data, content_type => 'image/png' );
2812
2813 Note that Dancer is unable to guess the content type from the data
2814 contents. Therefore you might need to set the "content_type" properly.
2815 For this kind of usage an attribute named "filename" can be useful. It
2816 is used as the Content-Disposition header, to hint the browser about
2817 the filename it should use.
2818
2819 send_file( \$data, content_type => 'image/png'
2820 filename => 'onion.png' );
2821
2822 By default the Content-Disposition header uses the "attachment" type,
2823 which triggers a "Save" dialog in some browsers. Supply a
2824 "content_disposition" attribute of "inline" to have the file displayed
2825 inline by the browser.
2826
2827 set
2828 Defines a setting:
2829
2830 set something => 'value';
2831
2832 You can set more than one value at once:
2833
2834 set something => 'value', otherthing => 'othervalue';
2835
2836 setting
2837 Returns the value of a given setting:
2838
2839 setting('something'); # 'value'
2840
2841 session
2842 Provides access to all data stored in the user's session (if any).
2843
2844 It can also be used as a setter to store data in the session:
2845
2846 # getter example
2847 get '/user' => sub {
2848 if (session('user')) {
2849 return "Hello, ".session('user')->name;
2850 }
2851 };
2852
2853 # setter example
2854 post '/user/login' => sub {
2855 ...
2856 if ($logged_in) {
2857 session user => $user;
2858 }
2859 ...
2860 };
2861
2862 You may also need to clear a session:
2863
2864 # destroy session
2865 get '/logout' => sub {
2866 ...
2867 app->destroy_session;
2868 ...
2869 };
2870
2871 If you need to fetch the session ID being used for any reason:
2872
2873 my $id = session->id;
2874
2875 splat
2876 Returns the list of captures made from a route handler with a route
2877 pattern which includes wildcards:
2878
2879 get '/file/*.*' => sub {
2880 my ($file, $extension) = splat;
2881 ...
2882 };
2883
2884 There is also the extensive splat (A.K.A. "megasplat"), which allows
2885 extensive greedier matching, available using two asterisks. The
2886 additional path is broken down and returned as an arrayref:
2887
2888 get '/entry/*/tags/**' => sub {
2889 my ( $entry_id, $tags ) = splat;
2890 my @tags = @{$tags};
2891 };
2892
2893 The "splat" keyword in the above example for the route
2894 /entry/1/tags/one/two would set $entry_id to 1 and $tags to "['one',
2895 'two']".
2896
2897 start
2898 Starts the application or the standalone server (depending on the
2899 deployment choices).
2900
2901 This keyword should be called at the very end of the script, once all
2902 routes are defined. At this point, Dancer2 takes over.
2903
2904 to_app
2905 Returns the PSGI coderef for the current (and only the current)
2906 application.
2907
2908 You can call it as a method on the class or as a DSL:
2909
2910 my $app = MyApp->to_app;
2911
2912 # or
2913
2914 my $app = to_app;
2915
2916 There is a Dancer Advent Calendar article
2917 <http://advent.perldancer.org/2014/9> covering this keyword and its
2918 usage further.
2919
2920 psgi_app
2921 Provides the same functionality as "to_app" but uses the deprecated
2922 Dispatcher engine. You should use "to_app" instead.
2923
2924 status
2925 Changes the status code provided by an action. By default, an action
2926 will produce an "HTTP 200 OK" status code, meaning everything is OK:
2927
2928 get '/download/:file' => {
2929 if (! -f route_parameters->get('file')) {
2930 status 'not_found';
2931 return "File does not exist, unable to download";
2932 }
2933 # serving the file...
2934 };
2935
2936 In that example, Dancer will notice that the status has changed, and
2937 will render the response accordingly.
2938
2939 The "status" keyword receives either a numeric status code or its name
2940 in lower case, with underscores as a separator for blanks - see the
2941 list in "HTTP CODES" in Dancer2::Core::HTTP. As an example, The above
2942 call translates to setting the code to 404.
2943
2944 template
2945 Returns the response of processing the given template with the given
2946 parameters (and optional settings), wrapping it in the default or
2947 specified layout too, if layouts are in use.
2948
2949 An example of a route handler which returns the result of using
2950 template to build a response with the current template engine:
2951
2952 get '/' => sub {
2953 ...
2954 return template 'some_view', { token => 'value'};
2955 };
2956
2957 Note that "template" simply returns the content, so when you use it in
2958 a route handler, if execution of the route handler should stop at that
2959 point, make sure you use "return" to ensure your route handler returns
2960 the content.
2961
2962 Since "template" just returns the result of rendering the template, you
2963 can also use it to perform other templating tasks, e.g. generating
2964 emails:
2965
2966 post '/some/route' => sub {
2967 if (...) {
2968 email {
2969 to => 'someone@example.com',
2970 from => 'foo@example.com',
2971 subject => 'Hello there',
2972 msg => template('emails/foo', { name => body_parameters->get('name') }),
2973 };
2974
2975 return template 'message_sent';
2976 } else {
2977 return template 'error';
2978 }
2979 };
2980
2981 Compatibility notice: "template" was changed in version 1.3090 to
2982 immediately interrupt execution of a route handler and return the
2983 content, as it's typically used at the end of a route handler to return
2984 content. However, this caused issues for some people who were using
2985 "template" to generate emails etc, rather than accessing the template
2986 engine directly, so this change has been reverted in 1.3091.
2987
2988 The first parameter should be a template available in the views
2989 directory, the second one (optional) is a hashref of tokens to
2990 interpolate, and the third (again optional) is a hashref of options.
2991
2992 For example, to disable the layout for a specific request:
2993
2994 get '/' => sub {
2995 template 'index', {}, { layout => undef };
2996 };
2997
2998 Or to request a specific layout, of course:
2999
3000 get '/user' => sub {
3001 template 'user', {}, { layout => 'user' };
3002 };
3003
3004 Some tokens are automatically added to your template ("perl_version",
3005 "dancer_version", "settings", "request", "vars" and, if you have
3006 sessions enabled, "session"). Check Default Template Variables for
3007 further details.
3008
3009 to_dumper ($structure)
3010 Serializes a structure with Data::Dumper.
3011
3012 Calling this function will not trigger the serialization's hooks.
3013
3014 to_json ($structure, \%options)
3015 Serializes a structure to JSON. You should probably use "encode_json"
3016 instead which handles encoding the result for you.
3017
3018 to_yaml ($structure)
3019 Serializes a structure to YAML.
3020
3021 Calling this function will not trigger the serialization's hooks.
3022
3023 true
3024 Constant that returns a true value (1).
3025
3026 upload
3027 Provides access to file uploads. Any uploaded file is accessible as a
3028 Dancer2::Core::Request::Upload object. You can access all parsed
3029 uploads via:
3030
3031 post '/some/route' => sub {
3032 my $file = upload('file_input_foo');
3033 # $file is a Dancer2::Core::Request::Upload object
3034 };
3035
3036 If you named multiple inputs of type "file" with the same name, the
3037 "upload" keyword would return an Array of
3038 Dancer2::Core::Request::Upload objects:
3039
3040 post '/some/route' => sub {
3041 my ($file1, $file2) = upload('files_input');
3042 # $file1 and $file2 are Dancer2::Core::Request::Upload objects
3043 };
3044
3045 You can also access the raw hashref of parsed uploads via the current
3046 "request" object:
3047
3048 post '/some/route' => sub {
3049 my $all_uploads = request->uploads;
3050 # $all_uploads->{'file_input_foo'} is a Dancer2::Core::Request::Upload object
3051 # $all_uploads->{'files_input'} is an arrayref of Dancer2::Core::Request::Upload objects
3052 };
3053
3054 Note that you can also access the filename of the upload received via
3055 the "body_parameters" keyword:
3056
3057 post '/some/route' => sub {
3058 # body_parameters->get('files_input') is the filename of the file uploaded
3059 };
3060
3061 See Dancer2::Core::Request::Upload for details about the interface
3062 provided.
3063
3064 uri_for
3065 Returns a fully-qualified URI for the given path:
3066
3067 get '/' => sub {
3068 redirect uri_for('/path');
3069 # can be something like: http://localhost:5000/path
3070 };
3071
3072 Query string parameters can be provided by passing a hashref as a
3073 second param:
3074
3075 uri_for('/path', { foo => 'bar' });
3076 # would return e.g. http://localhost:5000/path?foo=bar
3077
3078 By default, the parameters will be URL encoded:
3079
3080 uri_for('/path', { foo => 'hope;faith' });
3081 # would return http://localhost:5000/path?foo=hope%3Bfaith
3082
3083 If desired (for example, if you've already encoded your query
3084 parameters and you want to prevent double encoding) you can disable URL
3085 encoding via a third parameter:
3086
3087 uri_for('/path', { foo => 'qux%3Dquo' }, 1);
3088 # would return http://localhost:5000/path?foo=qux%3Dquo
3089
3090 captures
3091 Returns a reference to a copy of "%+", if there are named captures in
3092 the route's regular expression.
3093
3094 Named captures are a feature of Perl 5.10, and are not supported in
3095 earlier versions:
3096
3097 get qr{
3098 / (?<object> user | ticket | comment )
3099 / (?<action> delete | find )
3100 / (?<id> \d+ )
3101 /?$
3102 }x
3103 , sub {
3104 my $value_for = captures;
3105 "i don't want to $$value_for{action} the $$value_for{object} $$value_for{id} !"
3106 };
3107
3108 var
3109 Provides an accessor for variables shared between hooks and route
3110 handlers. Given a key/value pair, it sets a variable:
3111
3112 hook before => sub {
3113 var foo => 42;
3114 };
3115
3116 Later, route handlers and other hooks will be able to read that
3117 variable:
3118
3119 get '/path' => sub {
3120 my $foo = var 'foo';
3121 ...
3122 };
3123
3124 vars
3125 Returns the hashref of all shared variables set during the hook/route
3126 chain with the "var" keyword:
3127
3128 get '/path' => sub {
3129 if (vars->{foo} eq 42) {
3130 ...
3131 }
3132 };
3133
3134 warning
3135 Logs a warning message through the current logger engine:
3136
3137 warning "This is a warning";
3138
3139 See Dancer2::Core::Role::Logger for details on how to configure where
3140 log messages go.
3141
3143 Dancer Core Developers
3144
3146 This software is copyright (c) 2018 by Alexis Sukrieh.
3147
3148 This is free software; you can redistribute it and/or modify it under
3149 the same terms as the Perl 5 programming language system itself.
3150
3151
3152
3153perl v5.28.1 2018-11-14 Dancer2::Manual(3)