1# PODNAME: Dancer::Cookbook
2# ABSTRACT: a quick-start guide to the Dancer web framework
3
4__END__
5
6=pod
7
8=encoding UTF-8
9
10=head1 NAME
11
12Dancer::Cookbook - a quick-start guide to the Dancer web framework
13
14=head1 VERSION
15
16version 1.3513
17
18=head1 DESCRIPTION
19
20A quick-start guide with examples to get you up and running with the Dancer web
21framework.
22
23=head1 BEGINNER'S DANCE
24
25=head2 Your first Dancer web app
26
27Dancer has been designed to be easy to work with. It's trivial to write a
28simple web app, but still has the power to work with larger projects.  To start
29with, let's make an incredibly simple "Hello World" example:
30
31    #!/usr/bin/perl
32
33    use Dancer;
34
35    get '/hello/:name' => sub {
36        return "Why, hello there " . params->{name};
37    };
38
39    dance;
40
41Yes, the above is a fully-functioning web app; running that script will launch
42a webserver listening on the default port (3000). Now you can make a request
43
44    $ curl http://localhost:3000/hello/Bob
45    Why, hello there Bob
46
47(or the name of the machine you ran it on, if it's not your local system),
48and it will say hello.  The C<:name> part is a named parameter within the
49route specification whose value is made available through C<params>
50- more on that later.
51
52Note that you don't need to use the C<strict> and C<warnings> pragma, they are
53already loaded by Dancer.  (If you don't want the C<warnings> pragma (which can
54lead to undesired warnings about use of undef values, for example), then set the
55L<import_warnings|Dancer::Config/import_warnings> setting to a false value.
56
57=head2 Starting a Dancer project
58
59The first simple example is fine for trivial projects, but for anything more
60complex you'll want a more maintainable solution - enter the C<dancer> helper
61script, which will build the framework of your application with a single
62command:
63
64    $ dancer -a mywebapp
65    + mywebapp
66    + mywebapp/bin
67    + mywebapp/bin/app.pl
68    + mywebapp/config.yml
69    + mywebapp/environments
70    + mywebapp/environments/development.yml
71    + mywebapp/environments/production.yml
72    + mywebapp/views
73    + mywebapp/views/index.tt
74    + mywebapp/views/layouts
75    + mywebapp/views/layouts/main.tt
76    + mywebapp/MANIFEST.SKIP
77    + mywebapp/lib
78    + mywebapp/lib/mywebapp.pm
79    + mywebapp/public
80    + mywebapp/public/css
81    + mywebapp/public/css/style.css
82    + mywebapp/public/css/error.css
83    + mywebapp/public/images
84    + mywebapp/public/500.html
85    + mywebapp/public/404.html
86    + mywebapp/public/dispatch.fcgi
87    + mywebapp/public/dispatch.cgi
88    + mywebapp/public/javascripts
89    + mywebapp/public/javascripts/jquery.min.js
90    + mywebapp/t
91    + mywebapp/t/002_index_route.t
92    + mywebapp/t/001_base.t
93    + mywebapp/Makefile.PL
94
95As you can see, it creates a directory named after the name of the app, along
96with a configuration file, a views directory (where your templates and layouts
97will live), an environments directory (where environment-specific settings
98live), a module containing the actual guts of your application, a script to
99start it - or to run your web app via Plack/PSGI - more on that later.
100
101=head1 DANCE ROUTINES: ROUTES
102
103=head2 Declaring routes
104
105To control what happens when a web request is received by your webapp, you'll
106need to declare C<routes>.  A route declaration indicates for which HTTP method(s)
107it is valid, the path it matches (e.g. /foo/bar), and a coderef to execute,
108which returns the response.
109
110    get '/hello/:name' => sub {
111        return "Hi there " . params->{name};
112    };
113
114The above route specifies that, for GET requests to '/hello/...', the code block
115provided should be executed.
116
117=head2 Handling multiple HTTP request methods
118
119Routes can use C<any> to match all, or a specified list of HTTP methods.
120
121The following will match any HTTP request to the path /myaction:
122
123    any '/myaction' => sub {
124        # code
125    }
126
127The following will match GET or POST requests to /myaction:
128
129    any ['get', 'post'] => '/myaction' => sub {
130        # code
131    };
132
133For convenience, any route which matches GET requests will also match HEAD
134requests.
135
136=head2 Retrieving request parameters
137
138The L<params|Dancer/params> keyword returns a hashref of request parameters;
139these will be parameters supplied on the query string, within the path itself
140(with named placeholders), and, for HTTP POST requests, the content of the
141POST body.
142
143=head2 Named parameters in route path declarations
144
145As seen above, you can use C<:somename> in a route's path to capture part of the
146path; this will become available by calling L<params|Dancer/params>.
147
148So, for a web app where you want to display information on a company, you might
149use something like:
150
151    get '/company/view/:companyid' => sub {
152        my $company_id = params->{companyid};
153        # Look up the company and return appropriate page
154    };
155
156=head2 Wildcard path matching and splat
157
158You can also declare wildcards in a path, and retrieve the values they matched
159with the L<splat|Dancer/splat> keyword:
160
161    get '/*/*' => sub {
162        my ($action, $id) = splat;
163        if (my $action eq 'view') {
164            return display_item($id);
165        } elsif ($action eq 'delete') {
166            return delete_item($id);
167        } else {
168            status 'not_found';
169            return "What?";
170        }
171    };
172
173=head2 Before hooks - processed before a request
174
175A before L<hook|Dancer/hook> declares code which should be handled before
176a request is passed to the appropriate route.
177
178    hook 'before' => sub {
179        var note => 'Hi there';
180        request->path_info('/foo/oversee')
181    };
182
183    get '/foo/*' => sub {
184        my ($match) = splat; # 'oversee';
185        vars->{note}; # 'Hi there'
186    };
187
188The above declares a before hook which uses C<var> to set a variable which
189will later be available within the route handler, then amends the path of the
190request to C</foo/oversee>; this means that, whatever path was requested, it
191will be treated as though the path requested was C</foo/oversee>.
192
193=head2 Default route
194
195In case you want to avoid a I<404 error>, or handle multiple routes in the same
196way and you don't feel like configuring all of them, you can set up a default
197route handler.
198
199The default route handler will handle any request that doesn't get served by
200any other route.
201
202All you need to do is set up the following route as the B<last> route:
203
204    any qr{.*} => sub {
205        status 'not_found';
206        template 'special_404', { path => request->path };
207    };
208
209Then you can set up the template as such:
210
211    You tried to reach <% path %>, but it is unavailable at the moment.
212
213    Please try again or contact us at our email at <...>.
214
215=head2 Using the auto_page feature for automatic route creation
216
217For simple "static" pages, you can simply enable the C<auto_page> config
218setting; this means that you need not declare a route handler for those pages;
219if a request is for C</foo/bar>, Dancer will check for a matching view (e.g.
220C</foo/bar.tt> and render it with the default layout etc if found.  For full
221details, see the documentation for the
222L<auto_page setting|Dancer::Config/"auto_page">.
223
224=head2 Why should I use the Ajax plugin
225
226As an Ajax query is just an HTTP query, it's similar to a GET or POST
227route. You may ask yourself why you may want to use the C<ajax>
228keyword (from the L<Dancer::Plugin::Ajax> plugin) instead of a simple
229C<get>.
230
231Let's say you have a path like '/user/:user' in your application. You
232may want to be able to serve this page, with a layout and HTML
233content. But you may also want to be able to call this same url from a
234javascript query using Ajax.
235
236So, instead of having the following code:
237
238    get '/user/:user' => sub {
239         if (request->is_ajax) {
240             # create xml, set headers to text/xml, blablabla
241              header('Content-Type' => 'text/xml');
242              header('Cache-Control' =>  'no-store, no-cache, must-revalidate');
243              to_xml({...})
244         }else{
245             template users, {....}
246         }
247    };
248
249you can have
250
251    get '/user/:user' => sub {
252        template users, {...}
253    }
254
255and
256
257    ajax '/user/:user' => sub {
258         to_xml({...}, RootName => undef);
259    }
260
261Because it's an Ajax query you know you need to return XML content,
262so the content type of the response is set for you.
263
264=head2 Using the prefix feature to split your application
265
266For better maintainability you may want to separate some of your application
267components to different packages. Let's say we have a simple web app with an
268admin section, and want to maintain this in a different package:
269
270    package myapp;
271    use Dancer ':syntax';
272    use myapp::admin;
273
274    prefix undef;
275
276    get '/' => sub {...};
277
278    1;
279
280    package myapp::admin;
281    use Dancer ':syntax';
282
283    prefix '/admin';
284
285    get '/' => sub {...};
286
287    1;
288
289The following routes will be generated for us:
290
291    - get /
292    - get /admin/
293    - head /
294    - head /admin/
295
296=head1 MUSCLE MEMORY: STORING DATA
297
298=head2 Handling sessions
299
300It's common to want to use sessions to give your web applications state; for
301instance, allowing a user to log in, creating a session, and checking that
302session on subsequent requests.
303
304To make use of sessions you must first enable the session engine. Pick the
305session engine you want to use, then declare it in your config file:
306
307    session: Simple
308
309The L<Dancer::Session::Simple> backend implements very simple in-memory session
310storage.  This will be fast and useful for testing, but sessions do not persist
311between restarts of your app.
312
313You can also use the L<Dancer::Session::YAML> backend included with Dancer,
314which stores session data on disc in YAML files (since YAML is a nice
315human-readable format, it makes inspecting the contents of sessions a breeze):
316
317    session: YAML
318
319Or, to enable session support from within your code,
320
321    set session => 'YAML';
322
323(Controlling settings is best done from your config file, though).  'YAML' in
324the example is the session backend to use; this is shorthand for
325L<Dancer::Session::YAML>.  There are other session backends you may wish to use,
326for instance L<Dancer::Session::Memcache>, but the YAML backend is a simple and
327easy to use example which stores session data in a YAML file in sessions).
328
329You can then use the L<session|Dancer/session> keyword to manipulate the
330session:
331
332=head3 Storing data in the session
333
334Storing data in the session is as easy as:
335
336    session varname => 'value';
337
338=head3 Retrieving data from the session
339
340Retrieving data from the session is as easy as:
341
342    session('varname')
343
344Or, alternatively,
345
346    session->{varname}
347
348=head3 Controlling where sessions are stored
349
350For disc-based session back ends like L<Dancer::Session::YAML>,
351L<Dancer::Session::Storable> etc, session files are written to the session dir
352specified by the C<session_dir> setting, which defaults to C<appdir/sessions>.
353
354If you need to control where session files are created, you can do so quickly
355and easily within your config file. For example:
356
357    session_dir: /tmp/dancer-sessions
358
359If the directory you specify does not exist, Dancer will attempt to create it
360for you.
361
362=head3 Destroying a session
363
364When you're done with your session, you can destroy it:
365
366    session->destroy
367
368=head2 Sessions and logging in
369
370A common requirement is to check the user is logged in, and, if not, require
371them to log in before continuing.
372
373This can easily be handled with a before L<hook|Dancer/hook> to check their session:
374
375    hook 'before' => sub {
376        if (! session('user') && request->path_info !~ m{^/login}) {
377            var requested_path => request->path_info;
378            request->path_info('/login');
379        }
380    };
381
382    get '/login' => sub {
383        # Display a login page; the original URL they requested is available as
384        # vars->{requested_path}, so could be put in a hidden field in the form
385        template 'login', { path => vars->{requested_path} };
386    };
387
388    post '/login' => sub {
389        # Validate the username and password they supplied
390        if (params->{user} eq 'bob' && params->{pass} eq 'letmein') {
391            session user => params->{user};
392            redirect params->{path} || '/';
393        } else {
394            redirect '/login?failed=1';
395        }
396    };
397
398In your login page template, you'll want a text field named user, a password
399field named pass, and a hidden field named path, which will be populated with
400the path originally requested, so that it's sent back in the POST submission,
401and can be used by the post route to redirect onwards to the page originally
402requested once you're logged in.
403
404Of course you'll probably want to validate your users against a database table,
405or maybe via IMAP/LDAP/SSH/POP3/local system accounts via PAM etc.
406L<Authen::Simple> is probably a good starting point here!
407
408A simple working example of handling authentication against a database table
409yourself (using L<Dancer::Plugin::Database> which provides the C<database>
410keyword, and L<Crypt::SaltedHash> to handle salted hashed passwords (well, you
411wouldn't store your users' passwords in the clear, would you?)) follows:
412
413    post '/login' => sub {
414        my $user = database->quick_select('users',
415            { username => params->{user} }
416        );
417        if (!$user) {
418            warning "Failed login for unrecognised user " . params->{user};
419            redirect '/login?failed=1';
420        } else {
421            if (Crypt::SaltedHash->validate($user->{password}, params->{pass}))
422            {
423                debug "Password correct";
424                # Logged in successfully
425                session user => $user;
426                redirect params->{path} || '/';
427            } else {
428                debug("Login failed - password incorrect for " . params->{user});
429                redirect '/login?failed=1';
430            }
431        }
432    };
433
434=head3 Retrieve complete hash stored in session
435
436Get complete hash stored in session:
437
438    my $hash = session;
439
440=head1 APPEARANCE
441
442=head2 Using templates - views and layouts
443
444Returning plain content is all well and good for examples or trivial apps, but
445soon you'll want to use templates to maintain separation between your code and
446your content.  Dancer makes this easy.
447
448Your route handlers can use the L<template|Dancer/template> keyword to render
449templates.
450
451=head3 Views
452
453It's possible to render the action's content with a template, this is called a
454view. The `appdir/views' directory is the place where views are located.
455
456You can change this location by changing the setting 'views'.
457
458By default, the internal template engine L<Dancer::Template::Simple> is used,
459but you may want to upgrade to Template::Toolkit. If you do so, you have to
460enable this engine in your settings as explained in
461L<Dancer::Template::TemplateToolkit>.  If you do so, you'll also have to
462import the L<Template> module in your application code.
463
464Note that, by default, Dancer configures the Template::Toolkit engine to use
465C<<% %>> brackets instead of its default C<[% %]> brackets.  You can change this
466by using the following in your config file:
467
468    template: template_toolkit
469
470    engines:
471        template_toolkit:
472            start_tag: '[%'
473            stop_tag: '%]'
474
475All views must have a '.tt' extension. This may change in the future.
476
477To render a view just call the C<template|Dancer/template> keyword at
478the end of the action by giving the view name and the HASHREF of tokens to
479interpolate in the view (note that for convenience, the request, session, params
480and vars are automatically accessible in the view, named C<request>, C<session>,
481C<params> and C<vars>). For example:
482
483    hook 'before' => sub { var time => scalar(localtime) };
484
485    get '/hello/:name' => sub {
486        my $name = params->{name};
487        template 'hello.tt', { name => $name };
488    };
489
490The template 'hello.tt' could contain, for example:
491
492    <p>Hi there, <% name %>!</p>
493    <p>You're using <% request.user_agent %></p>
494    <% IF session.username %>
495        <p>You're logged in as <% session.username %>
496    <% END %>
497    It's currently <% vars.time %>
498
499For a full list of the tokens automatically added to your template
500(like C<session>, C<request> and C<vars>, refer to
501L<Dancer::Template::Abstract>).
502
503=head3 Layouts
504
505A layout is a special view, located in the 'layouts' directory (inside the views
506directory) which must have a token named 'content'. That token marks the place
507to render the action view. This lets you define a global layout for your
508actions, and have each individual view contain only the specific content.  This
509is a good thing to avoid lots of needless duplication of HTML :)
510
511Here is an example of a layout: C<views/layouts/main.tt> :
512
513    <html>
514        <head>...</head>
515        <body>
516        <div id="header">
517        ...
518        </div>
519
520        <div id="content">
521        <% content %>
522        </div>
523
524        </body>
525    </html>
526
527You can tell your app which layout to use with C<layout: name> in the config
528file, or within your code:
529
530    set layout => 'main';
531
532You can control which layout to use (or whether to use a layout at all) for a
533specific request without altering the layout setting by passing an options
534hashref as the third param to the template keyword:
535
536    template 'index.tt', {}, { layout => undef };
537
538If your application is not mounted under root (B</>), you can use a
539before_template_render hook instead of hardcoding the path to your
540application for your css, images and javascript:
541
542    hook 'before_template_render' => sub {
543        my $tokens = shift;
544        $tokens->{uri_base} = request->base->path;
545    };
546
547Then in your layout, modify your css inclusion as follows:
548
549    <link rel="stylesheet" href="<% uri_base %>/css/style.css" />
550
551From now on, you can mount your application wherever you want, without
552any further modification of the css inclusion
553
554=head3 template and unicode
555
556If you use L<Plack> and have some unicode problem with your Dancer application,
557don't forget to check if you have set your template engine to use unicode, and
558set the default charset to UTF-8. So, if you are using template toolkit, your
559config.yml will look like this:
560
561    charset: UTF-8
562    engines:
563      template_toolkit:
564        ENCODING: utf8
565
566=head3 TT's WRAPPER directive in Dancer (META variables, SETs)
567
568Dancer already provides a WRAPPER-like ability, which we call a "layout". The
569reason we do not use TT's WRAPPER (which also makes it incompatible with Dancer) is
570because not all template systems support it. Actually, most don't.
571
572However, you might want to use it, and be able to define META variables and
573regular L<Template::Toolkit> variables.
574
575These few steps will get you there:
576
577=over 4
578
579=item * Disable the layout in Dancer
580
581You can do this by simply commenting (or removing) the C<layout> configuration
582in the F<config.yml> file.
583
584=item * Use Template Toolkit template engine
585
586Change the configuration of the template to Template Toolkit:
587
588    # in config.yml
589    template: "template_toolkit"
590
591=item * Tell the Template Toolkit engine who's your wrapper
592
593    # in config.yml
594    # ...
595    engines:
596        template_toolkit:
597            WRAPPER: layouts/main.tt
598
599=back
600
601Done! Everything will work fine out of the box, including variables and META
602variables.
603
604=head1 SETTING THE STAGE: CONFIGURATION AND LOGGING
605
606=head2 Configuration and environments
607
608Configuring a Dancer application can be done in many ways. The easiest one (and
609maybe the dirtiest) is to put all your settings statements at the top of
610your script, before calling the dance() method.
611
612Other ways are possible. You can define all your settings in the file
613`appdir/config.yml'. For this, you must have installed the YAML module, and of
614course, write the config file in YAML.
615
616That's better than the first option, but it's still not perfect as you can't
617switch easily from one environment to another without rewriting the config.yml
618file.
619
620The better way is to have one config.yml file with default global settings,
621like the following:
622
623    # appdir/config.yml
624    logger: 'file'
625    layout: 'main'
626
627And then write as many environment files as you like in C<appdir/environments>.
628That way the appropriate environment config file will be loaded according to
629the running environment (if none is specified, it will be 'development').
630
631Note that you can change the running environment using the C<--environment>
632command line switch.
633
634Typically, you'll want to set the following values in a development config file:
635
636    # appdir/environments/development.yml
637    log: 'debug'
638    startup_info: 1
639    show_errors:  1
640
641And in a production one:
642
643    # appdir/environments/production.yml
644    log: 'warning'
645    startup_info: 0
646    show_errors:  0
647
648=head2 Accessing configuration information from your app
649
650A Dancer application can use the 'config' keyword to easily access the settings
651within its config file, for instance:
652
653    get '/appname' => sub {
654        return "This is " . config->{appname};
655    };
656
657This makes keeping your application's settings all in one place simple and easy.
658You shouldn't need to worry about implementing all that yourself :)
659
660=head2 Accessing configuration information from a separate script
661
662You may well want to access your webapp's configuration from outside your
663webapp. You could, of course, use the YAML module of your choice and load your
664webapps's config.yml, but chances are that this is not convenient.
665
666Use Dancer instead. Without any ado, magic or too big jumps, you can use the
667values from config.yml and some additional default values:
668
669	# bin/script1.pl
670	use Dancer ':script';
671	print "template:".config->{template}."\n"; #simple
672	print "log:".config->{log}."\n"; #undef
673
674Note that config->{log} should result in an undef error on a default scaffold since
675you did not load the environment and in the default scaffold log is defined in
676the environment and not in config.yml. Hence undef.
677
678If you want to load an environment you need to tell Dancer where to look for it.
679One way to do so, is to tell Dancer where the webapp lives. From there Dancer
680deduces where the config.yml file is (typically $webapp/config.yml).
681
682	# bin/script2.pl
683	use FindBin;
684	use Cwd qw/realpath/;
685	use Dancer ':script';
686
687	#tell the Dancer where the app lives
688	my $appdir=realpath( "$FindBin::Bin/..");
689
690	Dancer::Config::setting('appdir',$appdir);
691	Dancer::Config::load();
692
693	#getter
694	print "environment:".config->{environment}."\n"; #development
695	print "log:".config->{log}."\n"; #value from development environment
696
697By default Dancer loads development environment (typically
698$webapp/environment/development.yml). In contrast to the example before, you
699do have a value from the development environment (environment/development.yml)
700now. Also note that in the above example Cwd and FindBin are used. They are
701likely to be already loaded by Dancer anyways, so it's not a big overhead. You
702could just as well hand over a simple path for the app if you like that better,
703e.g.:
704
705	Dancer::Config::setting('appdir','/path/to/app/dir');
706
707If you want to load an environment other than the default, try this:
708
709	# bin/script2.pl
710	use Dancer ':script';
711
712	#tell the Dancer where the app lives
713	Dancer::Config::setting('appdir','/path/to/app/dir');
714
715	#which environment to load
716	config->{environment}='production';
717
718	Dancer::Config::load();
719
720	#getter
721	print "log:".config->{log}."\n"; #has value from production environment
722
723By the way, you not only get values, you can also set values straightforward
724like we do above with config->{environment}='production'. Of course, this value
725does not get written in any file; it only lives in memory and your webapp
726doesn't have access to it, but you can use it inside your script.
727
728If you don't want to make your script environment-specific, or add extra arguments
729to it, you can also set the environment using a shell variable, DANCER_ENVIRONMENT.
730See also L<Dancer::Config/DANCER_CONFDIR-and-DANCER_ENVDIR>
731
732=head2 Logging
733
734=head3 Configuring logging
735
736It's possible to log messages generated by the application and by Dancer itself.
737
738To start logging, select the logging engine you wish to use with the C<logger>
739setting; Dancer includes built-in log engines named C<file> and C<console>,
740which log to a logfile and to the console respectively.
741
742To enable logging to a file, add the following to your config.yml:
743
744    logger: 'file'
745
746Then you can choose which kind of messages you want to actually log:
747
748    log: 'core'      # will log all messages, including messages from
749                     # Dancer itself
750    log: 'debug'     # will log debug, info, warning and error messages
751    log: 'info'      # will log info, warning and error messages
752    log: 'warning'   # will log warning and error messages
753    log: 'error'     # will log error messages
754
755If you're using the C<file> logging engine, a directory C<appdir/logs> will be
756created and will host one logfile per environment. The log message contains the
757time it was written, the PID of the current process, the message and the caller
758information (file and line).
759
760=head3 Logging your own messages
761
762Just call  L<debug|Dancer/debug>, L<warning|Dancer/warning>,
763L<error|Dancer/error> or L<info|Dancer/info> with your message:
764
765    debug "This is a debug message from my app.";
766
767=head1 RESTING
768
769=head2 Writing a REST application
770
771With Dancer, it's easy to write REST applications. Dancer provides helpers to
772serialize and deserialize for the following data formats:
773
774=over 4
775
776=item JSON
777
778=item YAML
779
780=item XML
781
782=item Data::Dumper
783
784=back
785
786To activate this feature, you only have to set the C<serializer> setting to the
787format you require, for instance in your config.yml:
788
789   serializer: JSON
790
791Or right in your code:
792
793   set serializer => 'JSON';
794
795From now, all HashRefs or ArrayRefs returned by a route will be serialized to
796the format you chose, and all data received from B<POST> or B<PUT> requests
797will be automatically deserialized.
798
799    get '/hello/:name' => sub {
800        # this structure will be returned to the client as
801        # {"name":"$name"}
802        return {name => params->{name}};
803    };
804
805It's possible to let the client choose which serializer he wants to use. For
806this, use the B<mutable> serializer, and an appropriate serializer will be
807chosen from the B<Content-Type> header.
808
809It's also possible to return a custom error, using the
810L<send_error|Dancer/send_error> keyword..
811When you don't use a serializer, the C<send_error> function will take a string
812as the first parameter (the message), and an optional HTTP code. When using a
813serializer, the message can be a string, an ArrayRef or a HashRef:
814
815    get '/hello/:name' => sub {
816        if (...) {
817           send_error("you can't do that");
818           # or
819           send_error({reason => 'access denied', message => "no"});
820        }
821    };
822
823The content of the error will be serialized using the appropriate serializer.
824
825=head2 Deploying your Dancer applications
826
827For examples on deploying your Dancer applications including standalone, behind
828proxy/load-balancing software, and using common web servers including Apache to
829run via CGI/FastCGI etc, see L<Dancer::Deployment>.
830
831=head1 DANCER ON THE STAGE: DEPLOYMENT
832
833=head2 Plack middlewares
834
835If you deploy with Plack and use some Plack middlewares, you can enable them
836directly from Dancer's configuration files.
837
838=head3 Generic middlewares
839
840To enable middlewares in Dancer, you just have to set the plack_middlewares
841setting like the following:
842
843    set plack_middlewares => [
844        [ 'SomeMiddleware' => qw(some options for somemiddleware) ],
845    ];
846
847For instance, if you want to enable L<Plack::Middleware::Debug> in your Dancer
848application, all you have to do is to set C<plack_middlewares> like that:
849
850    set plack_middlewares => [
851        [ 'Debug' => ( 'panels' => [qw(DBITrace Memory Timer)] ) ],
852    ];
853
854Of course, you can also put this configuration into your config.yml file, or
855even in your environment configuration files:
856
857    # environments/development.yml
858    ...
859    plack_middlewares:
860      -
861        - Debug          # first element of the array is the name of the middleware
862        - panels         # following elements are the configuration of the middleware
863        -
864            - DBITrace
865            - Memory
866            - Timer
867
868=head3 Path-based middlewares
869
870If you want to set up a middleware for a specific path, you can do that using
871C<plack_middlewares_map>. You'll need L<Plack::App::URLMap> to do that.
872
873    plack_middlewares_map:
874        '/':      ['Debug']
875        '/timer': ['Timer'],
876
877=head1 DEVELOPMENT TOOLS
878
879=head2 Auto-reloading code
880
881When you are furiously hacking on your Dancer app, it might come in handy to
882have the application auto-detect changes in the code and reload itself.
883
884To do that, you can use L<Plack::Loader::Shotgun>, L<Plack::Middleware::Refresh>,
885or plackup with the C<-r> switch:
886
887   plackup -r bin/appl.pl  (will restart the app whenever a file in ./bin or ./lib is modified
888
889=head1 AUTHOR
890
891Dancer Core Developers
892
893=head1 COPYRIGHT AND LICENSE
894
895This software is copyright (c) 2010 by Alexis Sukrieh.
896
897This is free software; you can redistribute it and/or modify it under
898the same terms as the Perl 5 programming language system itself.
899
900=cut
901