1Catalyst::Manual::CookbUosoekr(3C)ontributed Perl DocumeCnattaatliyosnt::Manual::Cookbook(3)
2
3
4

NAME

6       Catalyst::Manual::Cookbook - Cooking with Catalyst
7

DESCRIPTION

9       Yummy code like your mum used to bake!
10

RECIPES

Basics

13       These recipes cover some basic stuff that is worth knowing for Catalyst
14       developers.
15
16   Delivering a Custom Error Page
17       By default, Catalyst will display its own error page whenever it
18       encounters an error in your application. When running under "-Debug"
19       mode, the error page is a useful screen including the error message and
20       Data::Dump output of the relevant parts of the $c context object.  When
21       not in "-Debug", users see a simple "Please come back later" screen.
22
23       To use a custom error page, use a special "end" method to short-circuit
24       the error processing. The following is an example; you might want to
25       adjust it further depending on the needs of your application (for
26       example, any calls to "fillform" will probably need to go into this
27       "end" method; see Catalyst::Plugin::FillInForm).
28
29           sub end : Private {
30               my ( $self, $c ) = @_;
31
32               if ( scalar @{ $c->error } ) {
33                   $c->stash->{errors}   = $c->error;
34                   for my $error ( @{ $c->error } ) {
35                       $c->log->error($error);
36                   }
37                   $c->stash->{template} = 'errors.tt';
38                   $c->forward('MyApp::View::TT');
39                   $c->clear_errors;
40               }
41
42               return 1 if $c->response->status =~ /^3\d\d$/;
43               return 1 if $c->response->body;
44
45               unless ( $c->response->content_type ) {
46                   $c->response->content_type('text/html; charset=utf-8');
47               }
48
49               $c->forward('MyApp::View::TT');
50           }
51
52       You can manually set errors in your code to trigger this page by
53       calling
54
55           $c->error( 'You broke me!' );
56
57   Disable statistics
58       Just add this line to your application class if you don't want those
59       nifty statistics in your debug messages.
60
61           sub Catalyst::Log::info { }
62
63   Enable debug status in the environment
64       Normally you enable the debugging info by adding the "-Debug" flag to
65       your "use Catalyst" statement . However, you can also enable it using
66       environment variable, so you can (for example) get debug info without
67       modifying your application scripts. Just set "CATALYST_DEBUG" or
68       "<MYAPP>_DEBUG" to a true value.
69
70   Sessions
71       When you have your users identified, you will want to somehow remember
72       that fact, to save them from having to identify themselves for every
73       single page. One way to do this is to send the username and password
74       parameters in every single page, but that's ugly, and won't work for
75       static pages.
76
77       Sessions are a method of saving data related to some transaction, and
78       giving the whole collection a single ID. This ID is then given to the
79       user to return to us on every page they visit while logged in. The
80       usual way to do this is using a browser cookie.
81
82       Catalyst uses two types of plugins to represent sessions:
83
84       State
85
86       A State module is used to keep track of the state of the session
87       between the users browser, and your application.
88
89       A common example is the Cookie state module, which sends the browser a
90       cookie containing the session ID. It will use default value for the
91       cookie name and domain, so will "just work" when used.
92
93       Store
94
95       A Store module is used to hold all the data relating to your session,
96       for example the users ID, or the items for their shopping cart. You can
97       store data in memory (FastMmap), in a file (File) or in a database
98       (DBI).
99
100       Authentication magic
101
102       If you have included the session modules in your application, the
103       Authentication modules will automagically use your session to save and
104       retrieve the user data for you.
105
106       Using a session
107
108       Once the session modules are loaded, the session is available as
109       "$c->session", and can be written to and read from as a simple hash
110       reference.
111
112       EXAMPLE
113
114         package MyApp;
115         use Moose;
116         use namespace::autoclean;
117
118         use Catalyst  qw/
119                                Session
120                                Session::Store::FastMmap
121                                Session::State::Cookie
122                          /;
123         extends 'Catalyst';
124         __PACKAGE__->setup;
125
126         package MyApp::Controller::Foo;
127         use Moose;
128         use namespace::autoclean;
129         BEGIN { extends 'Catalyst::Controller' };
130         ## Write data into the session
131
132         sub add_item : Local {
133            my ( $self, $c ) = @_;
134
135            my $item_id = $c->req->params->{item};
136
137            push @{ $c->session->{items} }, $item_id;
138
139         }
140
141         ## A page later we retrieve the data from the session:
142
143         sub get_items : Local {
144            my ( $self, $c ) = @_;
145
146            $c->stash->{items_to_display} = $c->session->{items};
147
148         }
149
150       More information
151
152       <http://search.cpan.org/dist/Catalyst-Plugin-Session>
153
154       <http://search.cpan.org/dist/Catalyst-Plugin-Session-State-Cookie>
155
156       <http://search.cpan.org/dist/Catalyst-Plugin-Session-State-URI>
157
158       <http://search.cpan.org/dist/Catalyst-Plugin-Session-Store-FastMmap>
159
160       <http://search.cpan.org/dist/Catalyst-Plugin-Session-Store-File>
161
162       <http://search.cpan.org/dist/Catalyst-Plugin-Session-Store-DBI>
163
164   Configure your application
165       You configure your application with the "config" method in your
166       application class. This can be hard-coded, or brought in from a
167       separate configuration file.
168
169       Using Config::General
170
171       Config::General is a method for creating flexible and readable
172       configuration files. It's a great way to keep your Catalyst application
173       configuration in one easy-to-understand location.
174
175       Now create "myapp.conf" in your application home:
176
177         name     MyApp
178
179         # session; perldoc Catalyst::Plugin::Session::FastMmap
180         <Session>
181           expires 3600
182           rewrite 0
183           storage /tmp/myapp.session
184         </Session>
185
186         # emails; perldoc Catalyst::Plugin::Email
187         # this passes options as an array :(
188         Mail SMTP
189         Mail localhost
190
191       This is equivalent to:
192
193         # configure base package
194         __PACKAGE__->config( name => MyApp );
195         # configure authentication
196         __PACKAGE__->config(
197               'Plugin::Authentication' => {
198                   user_class => 'MyApp::Model::MyDB::Customer',
199                   ...
200               },
201         _;
202         # configure sessions
203         __PACKAGE__->config(
204           session => {
205               expires => 3600,
206               ...
207           },
208         );
209         # configure email sending
210         __PACKAGE__->config( email => [qw/SMTP localhost/] );
211
212       Catalyst explains precedence of multiple sources for configuration
213       values, how to access the values in your components, and many 'base'
214       config variables used internally.
215
216       See also Config::General.
217

Skipping your VCS's directories

219       Catalyst uses Module::Pluggable to load Models, Views, and Controllers.
220       Module::Pluggable will scan through all directories and load modules it
221       finds.  Sometimes you might want to skip some of these directories, for
222       example when your version control system makes a subdirectory with
223       meta-information in every version-controlled directory.  While Catalyst
224       skips subversion and CVS directories already, there are other source
225       control systems.  Here is the configuration you need to add their
226       directories to the list to skip.
227
228       You can make Catalyst skip these directories using the Catalyst config:
229
230         # Configure the application
231         __PACKAGE__->config(
232             name => 'MyApp',
233             setup_components => { except => qr/SCCS/ },
234         );
235
236       See the Module::Pluggable manual page for more information on except
237       and other options.
238

Users and Access Control

240       Most multiuser, and some single-user web applications require that
241       users identify themselves, and the application is often required to
242       define those roles.  The recipes below describe some ways of doing
243       this.
244
245   Authentication (logging in)
246       This is extensively covered in other documentation; see in particular
247       Catalyst::Plugin::Authentication and the Authentication chapter of the
248       Tutorial at Catalyst::Manual::Tutorial::06_Authorization.
249
250   Pass-through login (and other actions)
251       An easy way of having assorted actions that occur during the processing
252       of a request that are orthogonal to its actual purpose - logins, silent
253       commands etc. Provide actions for these, but when they're required for
254       something else fill e.g. a form variable __login and have a sub begin
255       like so:
256
257           sub begin : Private {
258             my ($self, $c) = @_;
259             foreach my $action (qw/login docommand foo bar whatever/) {
260               if ($c->req->params->{"__${action}"}) {
261                 $c->forward($action);
262               }
263             }
264           }
265
266   Authentication/Authorization
267       This is done in several steps:
268
269       Verification
270           Getting the user to identify themselves, by giving you some piece
271           of information known only to you and the user. Then you can assume
272           that the user is who they say they are. This is called credential
273           verification.
274
275       Authorization
276           Making sure the user only accesses functions you want them to
277           access. This is done by checking the verified user's data against
278           your internal list of groups, or allowed persons for the current
279           page.
280
281       Modules
282
283       The Catalyst Authentication system is made up of many interacting
284       modules, to give you the most flexibility possible.
285
286       Credential verifiers
287
288       A Credential module tables the user input, and passes it to a Store, or
289       some other system, for verification. Typically, a user object is
290       created by either this module or the Store and made accessible by a
291       "$c->user" call.
292
293       Examples:
294
295        Password - Simple username/password checking.
296        HTTPD    - Checks using basic HTTP auth.
297        TypeKey  - Check using the typekey system.
298
299       Storage backends
300
301       A Storage backend contains the actual data representing the users. It
302       is queried by the credential verifiers. Updating the store is not done
303       within this system; you will need to do it yourself.
304
305       Examples:
306
307        DBIC     - Storage using a database via DBIx::Class.
308        Minimal  - Storage using a simple hash (for testing).
309
310       User objects
311
312       A User object is created by either the storage backend or the
313       credential verifier, and is filled with the retrieved user information.
314
315       Examples:
316
317        Hash     - A simple hash of keys and values.
318
319       ACL authorization
320
321       ACL stands for Access Control List. The ACL plugin allows you to
322       regulate access on a path-by-path basis, by listing which users, or
323       roles, have access to which paths.
324
325       Roles authorization
326
327       Authorization by roles is for assigning users to groups, which can then
328       be assigned to ACLs, or just checked when needed.
329
330       Logging in
331
332       When you have chosen your modules, all you need to do is call the
333       "$c->authenticate" method. If called with no parameters, it will try to
334       find suitable parameters, such as username and password, or you can
335       pass it these values.
336
337       Checking roles
338
339       Role checking is done by using the "$c->check_user_roles" method.  This
340       will check using the currently logged-in user (via "$c->user"). You
341       pass it the name of a role to check, and it returns true if the user is
342       a member.
343
344       EXAMPLE
345
346         package MyApp;
347         use Moose;
348         use namespace::autoclean;
349         extends qw/Catalyst/;
350         use Catalyst qw/
351           Authentication
352           Authorization::Roles
353         /;
354
355         __PACKAGE__->config(
356            authentication => {
357                default_realm => 'test',
358                realms => {
359                    test => {
360                        credential => {
361                            class          => 'Password',
362                            password_field => 'password',
363                            password_type  => 'self_check',
364                        },
365                        store => {
366                            class => 'Htpasswd',
367                            file => 'htpasswd',
368                        },
369                    },
370                },
371            },
372         );
373
374         package MyApp::Controller::Root;
375         use Moose;
376         use namespace::autoclean;
377
378         BEGIN { extends 'Catalyst::Controller' }
379
380         __PACKAGE__->config(namespace => '');
381
382         sub login : Local {
383            my ($self, $c) = @_;
384
385            if ( my $user = $c->req->params->{user}
386                and my $password = $c->req->param->{password} )
387            {
388                if ( $c->authenticate( username => $user, password => $password ) ) {
389                     $c->res->body( "hello " . $c->user->name );
390                } else {
391                   # login incorrect
392                }
393            }
394            else {
395                # invalid form input
396            }
397         }
398
399         sub restricted : Local {
400            my ( $self, $c ) = @_;
401
402            $c->detach("unauthorized")
403              unless $c->check_user_roles( "admin" );
404
405            # do something restricted here
406         }
407
408       Using authentication in a testing environment
409
410       Ideally, to write tests for authentication/authorization code one would
411       first set up a test database with known data, then use
412       Test::WWW::Mechanize::Catalyst to simulate a user logging in.
413       Unfortunately this can be rather awkward, which is why it's a good
414       thing that the authentication framework is so flexible.
415
416       Instead of using a test database, one can simply change the
417       authentication store to something a bit easier to deal with in a
418       testing environment. Additionally, this has the advantage of not
419       modifying one's database, which can be problematic if one forgets to
420       use the testing instead of production database.
421
422       Alternatively, if you want to authenticate real users, but not have to
423       worry about their passwords, you can use
424       Catalyst::Authentication::Credential::Testing to force all users to
425       authenticate with a global password.
426
427       More information
428
429       Catalyst::Plugin::Authentication has a longer explanation.
430
431   Authorization
432       Introduction
433
434       Authorization is the step that comes after authentication.
435       Authentication establishes that the user agent is really representing
436       the user we think it's representing, and then authorization determines
437       what this user is allowed to do.
438
439       Role Based Access Control
440
441       Under role based access control each user is allowed to perform any
442       number of roles. For example, at a zoo no one but specially trained
443       personnel can enter the moose cage (Mynd you, møøse bites kan be pretty
444       nasti!). For example:
445
446           package Zoo::Controller::MooseCage;
447
448           sub feed_moose : Local {
449               my ( $self, $c ) = @_;
450
451               $c->model( "Moose" )->eat( $c->req->params->{food} );
452           }
453
454       With this action, anyone can just come into the moose cage and feed the
455       moose, which is a very dangerous thing. We need to restrict this
456       action, so that only a qualified moose feeder can perform that action.
457
458       The Authorization::Roles plugin lets us perform role based access
459       control checks. Let's load it:
460
461           use parent qw/Catalyst/;
462           use Catalyst qw/
463                           Authentication
464                           Authorization::Roles
465                         /;
466
467       And now our action should look like this:
468
469           sub feed_moose : Local {
470               my ( $self, $c ) = @_;
471
472               if ( $c->check_roles( "moose_feeder" ) ) {
473                   $c->model( "Moose" )->eat( $c->req->params->{food} );
474               } else {
475                   $c->stash->{error} = "unauthorized";
476               }
477           }
478
479       This checks "$c->user", and only if the user has all the roles in the
480       list, a true value is returned.
481
482       "check_roles" has a sister method, "assert_roles", which throws an
483       exception if any roles are missing.
484
485       Some roles that might actually make sense in, say, a forum application:
486
487       ·   administrator
488
489       ·   moderator
490
491       each with a distinct task (system administration versus content
492       administration).
493
494       Access Control Lists
495
496       Checking for roles all the time can be tedious and error prone.
497
498       The Authorization::ACL plugin lets us declare where we'd like checks to
499       be done automatically for us.
500
501       For example, we may want to completely block out anyone who isn't a
502       "moose_feeder" from the entire "MooseCage" controller:
503
504           Zoo->deny_access_unless( "/moose_cage", [qw/moose_feeder/] );
505
506       The role list behaves in the same way as "check_roles". However, the
507       ACL plugin isn't limited to just interacting with the Roles plugin. We
508       can use a code reference instead. For example, to allow either moose
509       trainers or moose feeders into the moose cage, we can create a more
510       complex check:
511
512           Zoo->deny_access_unless( "/moose_cage", sub {
513               my $c = shift;
514               $c->check_roles( "moose_trainer" ) || $c->check_roles( "moose_feeder" );
515           });
516
517       The more specific a role, the earlier it will be checked. Let's say
518       moose feeders are now restricted to only the "feed_moose" action, while
519       moose trainers get access everywhere:
520
521           Zoo->deny_access_unless( "/moose_cage", [qw/moose_trainer/] );
522           Zoo->allow_access_if( "/moose_cage/feed_moose", [qw/moose_feeder/]);
523
524       When the "feed_moose" action is accessed the second check will be made.
525       If the user is a "moose_feeder", then access will be immediately
526       granted. Otherwise, the next rule in line will be tested - the one
527       checking for a "moose_trainer".  If this rule is not satisfied, access
528       will be immediately denied.
529
530       Rules applied to the same path will be checked in the order they were
531       added.
532
533       Lastly, handling access denial events is done by creating an
534       "access_denied" private action:
535
536           sub access_denied : Private {
537               my ( $self, $c, $action ) = @_;
538           }
539
540       This action works much like auto, in that it is inherited across
541       namespaces (not like object oriented code). This means that the
542       "access_denied" action which is nearest to the action which was blocked
543       will be triggered.
544
545       If this action does not exist, an error will be thrown, which you can
546       clean up in your "end" private action instead.
547
548       Also, it's important to note that if you restrict access to "/" then
549       "end", "default", etc. will also be restricted.
550
551          MyApp->acl_allow_root_internals;
552
553       will create rules that permit access to "end", "begin", and "auto" in
554       the root of your app (but not in any other controller).
555

Models

557       Models are where application data belongs.  Catalyst is extremely
558       flexible with the kind of models that it can use.  The recipes here are
559       just the start.
560
561   Using existing DBIC (etc.) classes with Catalyst
562       Many people have existing Model classes that they would like to use
563       with Catalyst (or, conversely, they want to write Catalyst models that
564       can be used outside of Catalyst, e.g.  in a cron job). It's trivial to
565       write a simple component in Catalyst that slurps in an outside Model:
566
567           package MyApp::Model::DB;
568
569           use base qw/Catalyst::Model::DBIC::Schema/;
570
571           __PACKAGE__->config(
572               schema_class => 'Some::DBIC::Schema',
573               connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}],
574           );
575
576           1;
577
578       and that's it! Now "Some::DBIC::Schema" is part of your Cat app as
579       "MyApp::Model::DB".
580
581   DBIx::Class as a Catalyst Model
582       See Catalyst::Model::DBIC::Schema.
583
584   Create accessors to preload static data once per server instance
585       When you have data that you want to load just once from the model at
586       startup, instead of for each request, use mk_group_accessors to create
587       accessors and tie them to resultsets in your package that inherits from
588       DBIx::Class::Schema:
589
590           package My::Schema;
591           use base qw/DBIx::Class::Schema/;
592           __PACKAGE__->register_class('RESULTSOURCEMONIKER',
593                                       'My::Schema::RESULTSOURCE');
594           __PACKAGE__->mk_group_accessors('simple' =>
595                                       qw(ACCESSORNAME1 ACCESSORNAME2 ACCESSORNAMEn));
596
597           sub connection {
598               my ($self, @rest) = @_;
599               $self->next::method(@rest);
600               # $self is now a live My::Schema object, complete with DB connection
601
602               $self->ACCESSORNAME1([ $self->resultset('RESULTSOURCEMONIKER')->all ]);
603               $self->ACCESSORNAME2([ $self->resultset('RESULTSOURCEMONIKER')->search({ COLUMN => { '<' => '30' } })->all ]);
604               $self->ACCESSORNAMEn([ $self->resultset('RESULTSOURCEMONIKER')->find(1) ]);
605           }
606
607           1;
608
609       and now in the controller, you can now access any of these without a
610       per-request fetch:
611
612           $c->stash->{something} = $c->model('My::Schema')->schema->ACCESSORNAME;
613
614   XMLRPC
615       Unlike SOAP, XMLRPC is a very simple (and elegant) web-services
616       protocol, exchanging small XML messages like these:
617
618       Request:
619
620           POST /api HTTP/1.1
621           TE: deflate,gzip;q=0.3
622           Connection: TE, close
623           Accept: text/xml
624           Accept: multipart/*
625           Host: 127.0.0.1:3000
626           User-Agent: SOAP::Lite/Perl/0.60
627           Content-Length: 192
628           Content-Type: text/xml
629
630           <?xml version="1.0" encoding="UTF-8"?>
631           <methodCall>
632               <methodName>add</methodName>
633               <params>
634                   <param><value><int>1</int></value></param>
635                   <param><value><int>2</int></value></param>
636               </params>
637           </methodCall>
638
639       Response:
640
641           Connection: close
642           Date: Tue, 20 Dec 2005 07:45:55 GMT
643           Content-Length: 133
644           Content-Type: text/xml
645           Status: 200
646           X-Catalyst: 5.70
647
648           <?xml version="1.0" encoding="us-ascii"?>
649           <methodResponse>
650               <params>
651                   <param><value><int>3</int></value></param>
652               </params>
653           </methodResponse>
654
655       Now follow these few steps to implement the application:
656
657       1. Install Catalyst (5.61 or later), Catalyst::Plugin::XMLRPC (0.06 or
658       later) and SOAP::Lite (for XMLRPCsh.pl).
659
660       2. Create an application framework:
661
662           % catalyst.pl MyApp
663           ...
664           % cd MyApp
665
666       3. Add the XMLRPC plugin to MyApp.pm
667
668           use Catalyst qw/-Debug Static::Simple XMLRPC/;
669
670       4. Add an API controller
671
672           % ./script/myapp_create.pl controller API
673
674       5. Add a XMLRPC redispatch method and an add method with Remote
675       attribute to lib/MyApp/Controller/API.pm
676
677           sub default :Path {
678               my ( $self, $c ) = @_;
679               $c->xmlrpc;
680           }
681
682           sub add : Remote {
683               my ( $self, $c, $a, $b ) = @_;
684               return $a + $b;
685           }
686
687       The default action is the entry point for each XMLRPC request. It will
688       redispatch every request to methods with Remote attribute in the same
689       class.
690
691       The "add" method is not a traditional action; it has no private or
692       public path. Only the XMLRPC dispatcher knows it exists.
693
694       6. That's it! You have built your first web service. Let's test it with
695       XMLRPCsh.pl (part of SOAP::Lite):
696
697           % ./script/myapp_server.pl
698           ...
699           % XMLRPCsh.pl http://127.0.0.1:3000/api
700           Usage: method[(parameters)]
701           > add( 1, 2 )
702           --- XMLRPC RESULT ---
703           '3'
704
705       Tip
706
707       Your return data type is usually auto-detected, but you can easily
708       enforce a specific one.
709
710           sub add : Remote {
711               my ( $self, $c, $a, $b ) = @_;
712               return RPC::XML::int->new( $a + $b );
713           }
714

Views

716       Views pertain to the display of your application.  As with models,
717       Catalyst is uncommonly flexible.  The recipes below are just a start.
718
719   Catalyst::View::TT
720       One of the first things you probably want to do when starting a new
721       Catalyst application is set up your View. Catalyst doesn't care how you
722       display your data; you can choose to generate HTML, PDF files, or plain
723       text if you wanted.
724
725       Most Catalyst applications use a template system to generate their
726       HTML, and though there are several template systems available, Template
727       Toolkit is probably the most popular.
728
729       Once again, the Catalyst developers have done all the hard work, and
730       made things easy for the rest of us. Catalyst::View::TT provides the
731       interface to Template Toolkit, and provides Helpers which let us set it
732       up that much more easily.
733
734       Creating your View
735
736       Catalyst::View::TT provides two different helpers for us to use: TT and
737       TTSite.
738
739       TT
740
741       Create a basic Template Toolkit View using the provided helper script:
742
743           script/myapp_create.pl view TT TT
744
745       This will create lib/MyApp/View/MyView.pm, which is going to be pretty
746       empty to start. However, it sets everything up that you need to get
747       started. You can now define which template you want and forward to your
748       view. For instance:
749
750           sub hello : Local {
751               my ( $self, $c ) = @_;
752
753               $c->stash->{template} = 'hello.tt';
754
755               $c->forward( $c->view('TT') );
756           }
757
758       In practice you wouldn't do the forwarding manually, but would use
759       Catalyst::Action::RenderView.
760
761       TTSite
762
763       Although the TT helper does create a functional, working view, you may
764       find yourself having to create the same template files and changing the
765       same options every time you create a new application. The TTSite helper
766       saves us even more time by creating the basic templates and setting
767       some common options for us.
768
769       Once again, you can use the helper script:
770
771           script/myapp_create.pl view TT TTSite
772
773       This time, the helper sets several options for us in the generated
774       View.
775
776           __PACKAGE__->config({
777               CATALYST_VAR => 'Catalyst',
778               INCLUDE_PATH => [
779                   MyApp->path_to( 'root', 'src' ),
780                   MyApp->path_to( 'root', 'lib' )
781               ],
782               PRE_PROCESS  => 'config/main',
783               WRAPPER      => 'site/wrapper',
784               ERROR        => 'error.tt2',
785               TIMER        => 0
786           });
787
788       ·   INCLUDE_PATH defines the directories that Template Toolkit should
789           search for the template files.
790
791       ·   PRE_PROCESS is used to process configuration options which are
792           common to every template file.
793
794       ·   WRAPPER is a file which is processed with each template, usually
795           used to easily provide a common header and footer for every page.
796
797       In addition to setting these options, the TTSite helper also created
798       the template and config files for us! In the 'root' directory, you'll
799       notice two new directories: src and lib.
800
801       Several configuration files in root/lib/config are called by
802       PRE_PROCESS.
803
804       The files in root/lib/site are the site-wide templates, called by
805       WRAPPER, and display the html framework, control the layout, and
806       provide the templates for the header and footer of your page. Using the
807       template organization provided makes it much easier to standardize
808       pages and make changes when they are (inevitably) needed.
809
810       The template files that you will create for your application will go
811       into root/src, and you don't need to worry about putting the <html> or
812       <head> sections; just put in the content. The WRAPPER will the rest of
813       the page around your template for you.
814
815       $c->stash
816
817       Of course, having the template system include the header and footer for
818       you isn't all that we want our templates to do. We need to be able to
819       put data into our templates, and have it appear where and how we want
820       it, right? That's where the stash comes in.
821
822       In our controllers, we can add data to the stash, and then access it
823       from the template. For instance:
824
825           sub hello : Local {
826               my ( $self, $c ) = @_;
827
828               $c->stash->{name} = 'Adam';
829
830               $c->stash->{template} = 'hello.tt';
831
832               $c->forward( $c->view('TT') );
833           }
834
835       Then, in hello.tt:
836
837           <strong>Hello, [% name %]!</strong>
838
839       When you view this page, it will display "Hello, Adam!"
840
841       All of the information in your stash is available, by its name/key, in
842       your templates. And your data don't have to be plain, old, boring
843       scalars. You can pass array references and hash references, too.
844
845       In your controller:
846
847           sub hello : Local {
848               my ( $self, $c ) = @_;
849
850               $c->stash->{names} = [ 'Adam', 'Dave', 'John' ];
851
852               $c->stash->{template} = 'hello.tt';
853
854               $c->forward( $c->view('TT') );
855           }
856
857       In hello.tt:
858
859           [% FOREACH name IN names %]
860               <strong>Hello, [% name %]!</strong><br />
861           [% END %]
862
863       This allowed us to loop through each item in the arrayref, and display
864       a line for each name that we have.
865
866       This is the most basic usage, but Template Toolkit is quite powerful,
867       and allows you to truly keep your presentation logic separate from the
868       rest of your application.
869
870       $c->uri_for()
871
872       One of my favorite things about Catalyst is the ability to move an
873       application around without having to worry that everything is going to
874       break. One of the areas that used to be a problem was with the http
875       links in your template files. For example, suppose you have an
876       application installed at http://www.domain.com/Calendar. The links
877       point to "/Calendar", "/Calendar/2005", "/Calendar/2005/10", etc.  If
878       you move the application to be at
879       http://www.mydomain.com/Tools/Calendar, then all of those links will
880       suddenly break.
881
882       That's where $c->uri_for() comes in. This function will merge its
883       parameters with either the base location for the app, or its current
884       namespace. Let's take a look at a couple of examples.
885
886       In your template, you can use the following:
887
888           <a href="[% c.uri_for('/login') %]">Login Here</a>
889
890       Although the parameter starts with a forward slash, this is relative to
891       the application root, not the webserver root. This is important to
892       remember. So, if your application is installed at
893       http://www.domain.com/Calendar, then the link would be
894       http://www.mydomain.com/Calendar/Login. If you move your application to
895       a different domain or path, then that link will still be correct.
896
897       Likewise,
898
899           <a href="[% c.uri_for('2005','10', '24') %]">October, 24 2005</a>
900
901       The first parameter does NOT have a forward slash, and so it will be
902       relative to the current namespace. If the application is installed at
903       http://www.domain.com/Calendar. and if the template is called from
904       MyApp::Controller::Display, then the link would become
905       http://www.domain.com/Calendar/Display/2005/10/24.
906
907       If you want to link to a parent uri of your current namespace you can
908       prefix the arguments with multiple '../':
909
910           <a href="[% c.uri_for('../../view', stashed_object.id) %]">User view</a>
911
912       Once again, this allows you to move your application around without
913       having to worry about broken links. But there's something else, as
914       well. Since the links are generated by uri_for, you can use the same
915       template file by several different controllers, and each controller
916       will get the links that its supposed to. Since we believe in Don't
917       Repeat Yourself, this is particularly helpful if you have common
918       elements in your site that you want to keep in one file.
919
920       Further Reading:
921
922       <http://search.cpan.org/perldoc?Catalyst>
923
924       <http://search.cpan.org/perldoc?Catalyst%3A%3AView%3A%3ATT>
925
926       <http://search.cpan.org/perldoc?Template>
927
928   Adding RSS feeds
929       Adding RSS feeds to your Catalyst applications is simple. We'll see two
930       different approaches here, but the basic premise is that you forward to
931       the normal view action first to get the objects, then handle the output
932       differently.
933
934       Using XML::Feed
935
936       Assuming we have a "view" action that populates 'entries' with some
937       DBIx::Class iterator, the code would look something like this:
938
939           sub rss : Local {
940               my ($self,$c) = @_;
941               $c->forward('view'); # get the entries
942
943               my $feed = XML::Feed->new('RSS');
944               $feed->title( $c->config->{name} . ' RSS Feed' );
945               $feed->link( $c->req->base ); # link to the site.
946               $feed->description('Catalyst advent calendar'); Some description
947
948               # Process the entries
949               while( my $entry = $c->stash->{entries}->next ) {
950                   my $feed_entry = XML::Feed::Entry->new('RSS');
951                   $feed_entry->title($entry->title);
952                   $feed_entry->link( $c->uri_for($entry->link) );
953                   $feed_entry->issued( DateTime->from_epoch(epoch => $entry->created) );
954                   $feed->add_entry($feed_entry);
955               }
956               $c->res->body( $feed->as_xml );
957          }
958
959       With this approach you're pretty sure to get something that validates.
960
961       Note that for both of the above approaches, you'll need to set the
962       content type like this:
963
964           $c->res->content_type('application/rss+xml');
965
966       Final words
967
968       You could generalize the second variant easily by replacing 'RSS' with
969       a variable, so you can generate Atom feeds with the same code.
970
971       Now, go ahead and make RSS feeds for all your stuff. The world *needs*
972       updates on your goldfish!
973
974   Forcing the browser to download content
975       Sometimes you need your application to send content for download. For
976       example, you can generate a comma-separated values (CSV) file for your
977       users to download and import into their spreadsheet program.
978
979       Let's say you have an "Orders" controller which generates a CSV file in
980       the "export" action (i.e., "http://localhost:3000/orders/export"):
981
982           sub export : Local Args(0) {
983               my ( $self, $c ) = @_;
984
985               # In a real application, you'd generate this from the database
986               my $csv = "1,5.99\n2,29.99\n3,3.99\n";
987
988               $c->res->content_type('text/comma-separated-values');
989               $c->res->body($csv);
990           }
991
992       Normally the browser uses the last part of the URI to generate a
993       filename for data it cannot display. In this case your browser would
994       likely ask you to save a file named "export".
995
996       Luckily you can have the browser download the content with a specific
997       filename by setting the "Content-Disposition" header:
998
999           my $filename = 'Important Orders.csv';
1000           $c->res->header('Content-Disposition', qq[attachment; filename="$filename"]);
1001
1002       Note the use of quotes around the filename; this ensures that any
1003       spaces in the filename are handled by the browser.
1004
1005       Put this right before calling "$c->res->body" and your browser will
1006       download a file named "Important Orders.csv" instead of "export".
1007
1008       You can also use this to have the browser download content which it
1009       normally displays, such as JPEG images or even HTML. Just be sure to
1010       set the appropriate content type and disposition.
1011

Controllers

1013       Controllers are the main point of communication between the web server
1014       and your application.  Here we explore some aspects of how they work.
1015
1016   Action Types
1017       Introduction
1018
1019       A Catalyst application is driven by one or more Controller modules.
1020       There are a number of ways that Catalyst can decide which of the
1021       methods in your controller modules it should call. Controller methods
1022       are also called actions, because they determine how your catalyst
1023       application should (re-)act to any given URL. When the application is
1024       started up, catalyst looks at all your actions, and decides which URLs
1025       they map to.
1026
1027       Type attributes
1028
1029       Each action is a normal method in your controller, except that it has
1030       an attribute attached. These can be one of several types.
1031
1032       Assume our Controller module starts with the following package
1033       declaration:
1034
1035        package MyApp::Controller::Buckets;
1036
1037       and we are running our application on localhost, port 3000 (the test
1038       server default).
1039
1040       Path
1041           A Path attribute also takes an argument, this can be either a
1042           relative or an absolute path. A relative path will be relative to
1043           the controller namespace, an absolute path will represent an exact
1044           matching URL.
1045
1046            sub my_handles : Path('handles') { .. }
1047
1048           becomes
1049
1050            http://localhost:3000/buckets/handles
1051
1052           and
1053
1054            sub my_handles : Path('/handles') { .. }
1055
1056           becomes
1057
1058            http://localhost:3000/handles
1059
1060           See also: Catalyst::DispatchType::Path
1061
1062       Local
1063           When using a Local attribute, no parameters are needed, instead,
1064           the name of the action is matched in the URL. The namespaces
1065           created by the name of the controller package is always part of the
1066           URL.
1067
1068            sub my_handles : Local { .. }
1069
1070           becomes
1071
1072            http://localhost:3000/buckets/my_handles
1073
1074       Global
1075           A Global attribute is similar to a Local attribute, except that the
1076           namespace of the controller is ignored, and matching starts at
1077           root.
1078
1079            sub my_handles : Global { .. }
1080
1081           becomes
1082
1083            http://localhost:3000/my_handles
1084
1085       Regex
1086           By now you should have figured that a Regex attribute is just what
1087           it sounds like. This one takes a regular expression, and matches
1088           starting from root. These differ from the rest as they can match
1089           multiple URLs.
1090
1091            sub my_handles : Regex('^handles') { .. }
1092
1093           matches
1094
1095            http://localhost:3000/handles
1096
1097           and
1098
1099            http://localhost:3000/handles_and_other_parts
1100
1101           etc.
1102
1103           See also: Catalyst::DispatchType::Regex
1104
1105       LocalRegex
1106           A LocalRegex is similar to a Regex, except it only matches below
1107           the current controller namespace.
1108
1109            sub my_handles : LocalRegex(^handles') { .. }
1110
1111           matches
1112
1113            http://localhost:3000/buckets/handles
1114
1115           and
1116
1117            http://localhost:3000/buckets/handles_and_other_parts
1118
1119           etc.
1120
1121       Chained
1122           See Catalyst::DispatchType::Chained for a description of how the
1123           chained dispatch type works.
1124
1125       Private
1126           Last but not least, there is the Private attribute, which allows
1127           you to create your own internal actions, which can be forwarded to,
1128           but won't be matched as URLs.
1129
1130            sub my_handles : Private { .. }
1131
1132           becomes nothing at all..
1133
1134           Catalyst also predefines some special Private actions, which you
1135           can override, these are:
1136
1137           default
1138               The default action will be called, if no other matching action
1139               is found. If you don't have one of these in your namespace, or
1140               any sub part of your namespace, you'll get an error page
1141               instead. If you want to find out where it was the user was
1142               trying to go, you can look in the request object using
1143               "$c->req->path".
1144
1145                sub default :Path { .. }
1146
1147               works for all unknown URLs, in this controller namespace, or
1148               every one if put directly into MyApp.pm.
1149
1150           index
1151               The index action is called when someone tries to visit the
1152               exact namespace of your controller. If index, default and
1153               matching Path actions are defined, then index will be used
1154               instead of default and Path.
1155
1156                sub index :Path :Args(0) { .. }
1157
1158               becomes
1159
1160                http://localhost:3000/buckets
1161
1162           begin
1163               The begin action is called at the beginning of every request
1164               involving this namespace directly, before other matching
1165               actions are called. It can be used to set up variables/data for
1166               this particular part of your app. A single begin action is
1167               called, its always the one most relevant to the current
1168               namespace.
1169
1170                sub begin : Private { .. }
1171
1172               is called once when
1173
1174                http://localhost:3000/bucket/(anything)?
1175
1176               is visited.
1177
1178           end Like begin, this action is always called for the namespace it
1179               is in, after every other action has finished. It is commonly
1180               used to forward processing to the View component. A single end
1181               action is called, its always the one most relevant to the
1182               current namespace.
1183
1184                sub end : Private { .. }
1185
1186               is called once after any actions when
1187
1188                http://localhost:3000/bucket/(anything)?
1189
1190               is visited.
1191
1192           auto
1193               Lastly, the auto action is magic in that every auto action in
1194               the chain of paths up to and including the ending namespace,
1195               will be called. (In contrast, only one of the begin/end/default
1196               actions will be called, the relevant one).
1197
1198                package MyApp::Controller::Root;
1199                sub auto : Private { .. }
1200
1201               and
1202
1203                sub auto : Private { .. }
1204
1205               will both be called when visiting
1206
1207                http://localhost:3000/bucket/(anything)?
1208
1209       A word of warning
1210
1211       You can put root actions in your main MyApp.pm file, but this is
1212       deprecated, please put your actions into your Root controller.
1213
1214       Flowchart
1215
1216       A graphical flowchart of how the dispatcher works can be found on the
1217       wiki at
1218       <http://dev.catalyst.perl.org/attachment/wiki/WikiStart/catalyst-flow.png>.
1219
1220   DRY Controllers with Chained actions
1221       Imagine that you would like the following paths in your application:
1222
1223       /cd/<ID>/track/<ID>
1224           Displays info on a particular track.
1225
1226           In the case of a multi-volume CD, this is the track sequence.
1227
1228       /cd/<ID>/volume/<ID>/track/<ID>
1229           Displays info on a track on a specific volume.
1230
1231       Here is some example code, showing how to do this with chained
1232       controllers:
1233
1234           package CD::Controller;
1235           use base qw/Catalyst::Controller/;
1236
1237           sub root : Chained('/') PathPart('/cd') CaptureArgs(1) {
1238               my ($self, $c, $cd_id) = @_;
1239               $c->stash->{cd_id} = $cd_id;
1240               $c->stash->{cd} = $self->model('CD')->find_by_id($cd_id);
1241           }
1242
1243           sub trackinfo : Chained('track') PathPart('') Args(0) RenderView {
1244               my ($self, $c) = @_;
1245           }
1246
1247           package CD::Controller::ByTrackSeq;
1248           use base qw/CD::Controller/;
1249
1250           sub track : Chained('root') PathPart('track') CaptureArgs(1) {
1251               my ($self, $c, $track_seq) = @_;
1252               $c->stash->{track} = $self->stash->{cd}->find_track_by_seq($track_seq);
1253           }
1254
1255           package CD::Controller::ByTrackVolNo;
1256           use base qw/CD::Controller/;
1257
1258           sub volume : Chained('root') PathPart('volume') CaptureArgs(1) {
1259               my ($self, $c, $volume) = @_;
1260               $c->stash->{volume} = $volume;
1261           }
1262
1263           sub track : Chained('volume') PathPart('track') CaptureArgs(1) {
1264               my ($self, $c, $track_no) = @_;
1265               $c->stash->{track} = $self->stash->{cd}->find_track_by_vol_and_track_no(
1266                   $c->stash->{volume}, $track_no
1267               );
1268           }
1269
1270       Note that adding other actions (i.e. chain endpoints) which operate on
1271       a track is simply a matter of adding a new sub to CD::Controller - no
1272       code is duplicated, even though there are two different methods of
1273       looking up a track.
1274
1275       This technique can be expanded as needed to fulfil your requirements -
1276       for example, if you inherit the first action of a chain from a base
1277       class, then mixing in a different base class can be used to duplicate
1278       an entire URL hierarchy at a different point within your application.
1279
1280   Component-based Subrequests
1281       See Catalyst::Plugin::SubRequest.
1282
1283   File uploads
1284       Single file upload with Catalyst
1285
1286       To implement uploads in Catalyst, you need to have a HTML form similar
1287       to this:
1288
1289           <form action="/upload" method="post" enctype="multipart/form-data">
1290             <input type="hidden" name="form_submit" value="yes">
1291             <input type="file" name="my_file">
1292             <input type="submit" value="Send">
1293           </form>
1294
1295       It's very important not to forget "enctype="multipart/form-data"" in
1296       the form.
1297
1298       Catalyst Controller module 'upload' action:
1299
1300           sub upload : Global {
1301               my ($self, $c) = @_;
1302
1303               if ( $c->request->parameters->{form_submit} eq 'yes' ) {
1304
1305                   if ( my $upload = $c->request->upload('my_file') ) {
1306
1307                       my $filename = $upload->filename;
1308                       my $target   = "/tmp/upload/$filename";
1309
1310                       unless ( $upload->link_to($target) || $upload->copy_to($target) ) {
1311                           die( "Failed to copy '$filename' to '$target': $!" );
1312                       }
1313                   }
1314               }
1315
1316               $c->stash->{template} = 'file_upload.html';
1317           }
1318
1319       Multiple file upload with Catalyst
1320
1321       Code for uploading multiple files from one form needs a few changes:
1322
1323       The form should have this basic structure:
1324
1325           <form action="/upload" method="post" enctype="multipart/form-data">
1326             <input type="hidden" name="form_submit" value="yes">
1327             <input type="file" name="file1" size="50"><br>
1328             <input type="file" name="file2" size="50"><br>
1329             <input type="file" name="file3" size="50"><br>
1330             <input type="submit" value="Send">
1331           </form>
1332
1333       And in the controller:
1334
1335           sub upload : Local {
1336               my ($self, $c) = @_;
1337
1338               if ( $c->request->parameters->{form_submit} eq 'yes' ) {
1339
1340                   for my $field ( $c->req->upload ) {
1341
1342                       my $upload   = $c->req->upload($field);
1343                       my $filename = $upload->filename;
1344                       my $target   = "/tmp/upload/$filename";
1345
1346                       unless ( $upload->link_to($target) || $upload->copy_to($target) ) {
1347                           die( "Failed to copy '$filename' to '$target': $!" );
1348                       }
1349                   }
1350               }
1351
1352               $c->stash->{template} = 'file_upload.html';
1353           }
1354
1355       "for my $field ($c->req-"upload)> loops automatically over all file
1356       input fields and gets input names. After that is basic file saving
1357       code, just like in single file upload.
1358
1359       Notice: "die"ing might not be what you want to do, when an error
1360       occurs, but it works as an example. A better idea would be to store
1361       error $! in "$c->stash->{error}" and show a custom error template
1362       displaying this message.
1363
1364       For more information about uploads and usable methods look at
1365       Catalyst::Request::Upload and Catalyst::Request.
1366
1367   Forwarding with arguments
1368       Sometimes you want to pass along arguments when forwarding to another
1369       action. As of version 5.30, arguments can be passed in the call to
1370       "forward"; in earlier versions, you can manually set the arguments in
1371       the Catalyst Request object:
1372
1373         # version 5.30 and later:
1374         $c->forward('/wherever', [qw/arg1 arg2 arg3/]);
1375
1376         # pre-5.30
1377         $c->req->args([qw/arg1 arg2 arg3/]);
1378         $c->forward('/wherever');
1379
1380       (See the Catalyst::Manual::Intro Flow_Control section for more
1381       information on passing arguments via "forward".)
1382
1383   Chained dispatch using base classes, and inner packages.
1384         package MyApp::Controller::Base;
1385         use base qw/Catalyst::Controller/;
1386
1387         sub key1 : Chained('/')
1388
1389   Extending RenderView (formerly DefaultEnd)
1390       The recommended approach for an "end" action is to use
1391       Catalyst::Action::RenderView (taking the place of
1392       Catalyst::Plugin::DefaultEnd), which does what you usually need.
1393       However there are times when you need to add a bit to it, but don't
1394       want to write your own "end" action.
1395
1396       You can extend it like this:
1397
1398       To add something to an "end" action that is called before rendering
1399       (this is likely to be what you want), simply place it in the "end"
1400       method:
1401
1402           sub end : ActionClass('RenderView') {
1403             my ( $self, $c ) = @_;
1404             # do stuff here; the RenderView action is called afterwards
1405           }
1406
1407       To add things to an "end" action that are called after rendering, you
1408       can set it up like this:
1409
1410           sub render : ActionClass('RenderView') { }
1411
1412           sub end : Private {
1413             my ( $self, $c ) = @_;
1414             $c->forward('render');
1415             # do stuff here
1416           }
1417
1418   Serving static content
1419       Serving static content in Catalyst used to be somewhat tricky; the use
1420       of Catalyst::Plugin::Static::Simple makes everything much easier.  This
1421       plugin will automatically serve your static content during development,
1422       but allows you to easily switch to Apache (or other server) in a
1423       production environment.
1424
1425       Introduction to Static::Simple
1426
1427       Static::Simple is a plugin that will help to serve static content for
1428       your application. By default, it will serve most types of files,
1429       excluding some standard Template Toolkit extensions, out of your root
1430       file directory. All files are served by path, so if images/me.jpg is
1431       requested, then root/images/me.jpg is found and served.
1432
1433       Usage
1434
1435       Using the plugin is as simple as setting your use line in MyApp.pm to
1436       include:
1437
1438        use Catalyst qw/Static::Simple/;
1439
1440       and already files will be served.
1441
1442       Configuring
1443
1444       Static content is best served from a single directory within your root
1445       directory. Having many different directories such as "root/css" and
1446       "root/images" requires more code to manage, because you must separately
1447       identify each static directory--if you decide to add a "root/js"
1448       directory, you'll need to change your code to account for it. In
1449       contrast, keeping all static directories as subdirectories of a main
1450       "root/static" directory makes things much easier to manage. Here's an
1451       example of a typical root directory structure:
1452
1453           root/
1454           root/content.tt
1455           root/controller/stuff.tt
1456           root/header.tt
1457           root/static/
1458           root/static/css/main.css
1459           root/static/images/logo.jpg
1460           root/static/js/code.js
1461
1462       All static content lives under "root/static", with everything else
1463       being Template Toolkit files.
1464
1465       Include Path
1466           You may of course want to change the default locations, and make
1467           Static::Simple look somewhere else, this is as easy as:
1468
1469            MyApp->config(
1470               static => {
1471                   include_path => [
1472                       MyApp->path_to('/'),
1473                       '/path/to/my/files',
1474                   ],
1475               },
1476             );
1477
1478           When you override include_path, it will not automatically append
1479           the normal root path, so you need to add it yourself if you still
1480           want it. These will be searched in order given, and the first
1481           matching file served.
1482
1483       Static directories
1484           If you want to force some directories to be only static, you can
1485           set them using paths relative to the root dir, or regular
1486           expressions:
1487
1488            MyApp->config(
1489               static => {
1490                   dirs => [
1491                       'static',
1492                       qr/^(images|css)/,
1493                   ],
1494               },
1495             );
1496
1497       File extensions
1498           By default, the following extensions are not served (that is, they
1499           will be processed by Catalyst): tmpl, tt, tt2, html, xhtml. This
1500           list can be replaced easily:
1501
1502            MyApp->config(
1503                   static => {
1504                       ignore_extensions => [
1505                           qw/tmpl tt tt2 html xhtml/
1506                       ],
1507                   },
1508             );
1509
1510       Ignoring directories
1511           Entire directories can be ignored. If used with include_path,
1512           directories relative to the include_path dirs will also be ignored:
1513
1514             MyApp->config( static => {
1515                   ignore_dirs => [ qw/tmpl css/ ],
1516             });
1517
1518       More information
1519
1520       <http://search.cpan.org/dist/Catalyst-Plugin-Static-Simple/>
1521
1522       Serving manually with the Static plugin with HTTP::Daemon
1523       (myapp_server.pl)
1524
1525       In some situations you might want to control things more directly,
1526       using Catalyst::Plugin::Static.
1527
1528       In your main application class (MyApp.pm), load the plugin:
1529
1530           use Catalyst qw/-Debug FormValidator Static OtherPlugin/;
1531
1532       You will also need to make sure your end method does not forward static
1533       content to the view, perhaps like this:
1534
1535           sub end : Private {
1536               my ( $self, $c ) = @_;
1537
1538               $c->forward( 'MyApp::View::TT' )
1539                 unless ( $c->res->body || !$c->stash->{template} );
1540           }
1541
1542       This code will only forward to the view if a template has been
1543       previously defined by a controller and if there is not already data in
1544       "$c->res->body".
1545
1546       Next, create a controller to handle requests for the /static path. Use
1547       the Helper to save time. This command will create a stub controller as
1548       "lib/MyApp/Controller/Static.pm".
1549
1550           $ script/myapp_create.pl controller Static
1551
1552       Edit the file and add the following methods:
1553
1554           # serve all files under /static as static files
1555           sub default : Path('/static') {
1556               my ( $self, $c ) = @_;
1557
1558               # Optional, allow the browser to cache the content
1559               $c->res->headers->header( 'Cache-Control' => 'max-age=86400' );
1560
1561               $c->serve_static; # from Catalyst::Plugin::Static
1562           }
1563
1564           # also handle requests for /favicon.ico
1565           sub favicon : Path('/favicon.ico') {
1566               my ( $self, $c ) = @_;
1567
1568               $c->serve_static;
1569           }
1570
1571       You can also define a different icon for the browser to use instead of
1572       favicon.ico by using this in your HTML header:
1573
1574           <link rel="icon" href="/static/myapp.ico" type="image/x-icon" />
1575
1576       Common problems with the Static plugin
1577
1578       The Static plugin makes use of the "shared-mime-info" package to
1579       automatically determine MIME types. This package is notoriously
1580       difficult to install, especially on win32 and OS X. For OS X the
1581       easiest path might be to install Fink, then use "apt-get install
1582       shared-mime-info". Restart the server, and everything should be fine.
1583
1584       Make sure you are using the latest version (>= 0.16) for best results.
1585       If you are having errors serving CSS files, or if they get served as
1586       text/plain instead of text/css, you may have an outdated shared-mime-
1587       info version. You may also wish to simply use the following code in
1588       your Static controller:
1589
1590           if ($c->req->path =~ /css$/i) {
1591               $c->serve_static( "text/css" );
1592           } else {
1593               $c->serve_static;
1594           }
1595
1596       Serving Static Files with Apache
1597
1598       When using Apache, you can bypass Catalyst and any Static
1599       plugins/controllers controller by intercepting requests for the
1600       "root/static" path at the server level. All that is required is to
1601       define a DocumentRoot and add a separate Location block for your static
1602       content. Here is a complete config for this application under mod_perl
1603       1.x:
1604
1605           <Perl>
1606               use lib qw(/var/www/MyApp/lib);
1607           </Perl>
1608           PerlModule MyApp
1609
1610           <VirtualHost *>
1611               ServerName myapp.example.com
1612               DocumentRoot /var/www/MyApp/root
1613               <Location />
1614                   SetHandler perl-script
1615                   PerlHandler MyApp
1616               </Location>
1617               <LocationMatch "/(static|favicon.ico)">
1618                   SetHandler default-handler
1619               </LocationMatch>
1620           </VirtualHost>
1621
1622       And here's a simpler example that'll get you started:
1623
1624           Alias /static/ "/my/static/files/"
1625           <Location "/static">
1626               SetHandler none
1627           </Location>
1628
1629   Caching
1630       Catalyst makes it easy to employ several different types of caching to
1631       speed up your applications.
1632
1633       Cache Plugins
1634
1635       There are three wrapper plugins around common CPAN cache modules:
1636       Cache::FastMmap, Cache::FileCache, and Cache::Memcached.  These can be
1637       used to cache the result of slow operations.
1638
1639       The Catalyst Advent Calendar uses the FileCache plugin to cache the
1640       rendered XHTML version of the source POD document.  This is an ideal
1641       application for a cache because the source document changes
1642       infrequently but may be viewed many times.
1643
1644           use Catalyst qw/Cache::FileCache/;
1645
1646           ...
1647
1648           use File::stat;
1649           sub render_pod : Local {
1650               my ( self, $c ) = @_;
1651
1652               # the cache is keyed on the filename and the modification time
1653               # to check for updates to the file.
1654               my $file  = $c->path_to( 'root', '2005', '11.pod' );
1655               my $mtime = ( stat $file )->mtime;
1656
1657               my $cached_pod = $c->cache->get("$file $mtime");
1658               if ( !$cached_pod ) {
1659                   $cached_pod = do_slow_pod_rendering();
1660                   # cache the result for 12 hours
1661                   $c->cache->set( "$file $mtime", $cached_pod, '12h' );
1662               }
1663               $c->stash->{pod} = $cached_pod;
1664           }
1665
1666       We could actually cache the result forever, but using a value such as
1667       12 hours allows old entries to be automatically expired when they are
1668       no longer needed.
1669
1670       Page Caching
1671
1672       Another method of caching is to cache the entire HTML page.  While this
1673       is traditionally handled by a frontend proxy server like Squid, the
1674       Catalyst PageCache plugin makes it trivial to cache the entire output
1675       from frequently-used or slow actions.
1676
1677       Many sites have a busy content-filled front page that might look
1678       something like this.  It probably takes a while to process, and will do
1679       the exact same thing for every single user who views the page.
1680
1681           sub front_page : Path('/') {
1682               my ( $self, $c ) = @_;
1683
1684               $c->forward( 'get_news_articles' );
1685               $c->forward( 'build_lots_of_boxes' );
1686               $c->forward( 'more_slow_stuff' );
1687
1688               $c->stash->{template} = 'index.tt';
1689           }
1690
1691       We can add the PageCache plugin to speed things up.
1692
1693           use Catalyst qw/Cache::FileCache PageCache/;
1694
1695           sub front_page : Path ('/') {
1696               my ( $self, $c ) = @_;
1697
1698               $c->cache_page( 300 );
1699
1700               # same processing as above
1701           }
1702
1703       Now the entire output of the front page, from <html> to </html>, will
1704       be cached for 5 minutes.  After 5 minutes, the next request will
1705       rebuild the page and it will be re-cached.
1706
1707       Note that the page cache is keyed on the page URI plus all parameters,
1708       so requests for / and /?foo=bar will result in different cache items.
1709       Also, only GET requests will be cached by the plugin.
1710
1711       You can even get that frontend Squid proxy to help out by enabling HTTP
1712       headers for the cached page.
1713
1714           MyApp->config(
1715               page_cache => {
1716                   set_http_headers => 1,
1717               },
1718           );
1719
1720       This would now set the following headers so proxies and browsers may
1721       cache the content themselves.
1722
1723           Cache-Control: max-age=($expire_time - time)
1724           Expires: $expire_time
1725           Last-Modified: $cache_created_time
1726
1727       Template Caching
1728
1729       Template Toolkit provides support for caching compiled versions of your
1730       templates.  To enable this in Catalyst, use the following
1731       configuration.  TT will cache compiled templates keyed on the file
1732       mtime, so changes will still be automatically detected.
1733
1734           package MyApp::View::TT;
1735
1736           use strict;
1737           use warnings;
1738           use base 'Catalyst::View::TT';
1739
1740           __PACKAGE__->config(
1741               COMPILE_DIR => '/tmp/template_cache',
1742           );
1743
1744           1;
1745
1746       More Info
1747
1748       See the documentation for each cache plugin for more details and other
1749       available configuration options.
1750
1751       Catalyst::Plugin::Cache::FastMmap Catalyst::Plugin::Cache::FileCache
1752       Catalyst::Plugin::Cache::Memcached Catalyst::Plugin::PageCache
1753       <http://search.cpan.org/dist/Template-Toolkit/lib/Template/Manual/Config.pod#Caching_and_Compiling_Options>
1754

Testing

1756       Testing is an integral part of the web application development process.
1757       Tests make multi developer teams easier to coordinate, and they help
1758       ensure that there are no nasty surprises after upgrades or alterations.
1759
1760   Testing
1761       Catalyst provides a convenient way of testing your application during
1762       development and before deployment in a real environment.
1763
1764       "Catalyst::Test" makes it possible to run the same tests both locally
1765       (without an external daemon) and against a remote server via HTTP.
1766
1767       Tests
1768
1769       Let's examine a skeleton application's "t/" directory:
1770
1771           mundus:~/MyApp chansen$ ls -l t/
1772           total 24
1773           -rw-r--r--  1 chansen  chansen   95 18 Dec 20:50 01app.t
1774           -rw-r--r--  1 chansen  chansen  190 18 Dec 20:50 02pod.t
1775           -rw-r--r--  1 chansen  chansen  213 18 Dec 20:50 03podcoverage.t
1776
1777       "01app.t"
1778           Verifies that the application loads, compiles, and returns a
1779           successful response.
1780
1781       "02pod.t"
1782           Verifies that all POD is free from errors. Only executed if the
1783           "TEST_POD" environment variable is true.
1784
1785       "03podcoverage.t"
1786           Verifies that all methods/functions have POD coverage. Only
1787           executed if the "TEST_POD" environment variable is true.
1788
1789       Creating tests
1790
1791           mundus:~/MyApp chansen$ cat t/01app.t | perl -ne 'printf( "%2d  %s", $., $_ )'
1792           1  use Test::More tests => 2;
1793           2  BEGIN { use_ok( Catalyst::Test, 'MyApp' ) }
1794           3
1795           4  ok( request('/')->is_success );
1796
1797       The first line declares how many tests we are going to run, in this
1798       case two. The second line tests and loads our application in test mode.
1799       The fourth line verifies that our application returns a successful
1800       response.
1801
1802       "Catalyst::Test" exports two functions, "request" and "get". Each can
1803       take three different arguments:
1804
1805       A string which is a relative or absolute URI.
1806               request('/my/path');
1807               request('http://www.host.com/my/path');
1808
1809       An instance of "URI".
1810               request( URI->new('http://www.host.com/my/path') );
1811
1812       An instance of "HTTP::Request".
1813               request( HTTP::Request->new( GET => 'http://www.host.com/my/path') );
1814
1815       "request" returns an instance of "HTTP::Response" and "get" returns the
1816       content (body) of the response.
1817
1818       Running tests locally
1819
1820           mundus:~/MyApp chansen$ CATALYST_DEBUG=0 TEST_POD=1 prove --lib lib/ t/
1821           t/01app............ok
1822           t/02pod............ok
1823           t/03podcoverage....ok
1824           All tests successful.
1825           Files=3, Tests=4,  2 wallclock secs ( 1.60 cusr +  0.36 csys =  1.96 CPU)
1826
1827       "CATALYST_DEBUG=0" ensures that debugging is off; if it's enabled you
1828       will see debug logs between tests.
1829
1830       "TEST_POD=1" enables POD checking and coverage.
1831
1832       "prove" A command-line tool that makes it easy to run tests. You can
1833       find out more about it from the links below.
1834
1835       Running tests remotely
1836
1837           mundus:~/MyApp chansen$ CATALYST_SERVER=http://localhost:3000/ prove --lib lib/ t/01app.t
1838           t/01app....ok
1839           All tests successful.
1840           Files=1, Tests=2,  0 wallclock secs ( 0.40 cusr +  0.01 csys =  0.41 CPU)
1841
1842       "CATALYST_SERVER=http://localhost:3000/" is the absolute deployment URI
1843       of your application. In "CGI" or "FastCGI" it should be the host and
1844       path to the script.
1845
1846       "Test::WWW::Mechanize" and Catalyst
1847
1848       Be sure to check out "Test::WWW::Mechanize::Catalyst". It makes it easy
1849       to test HTML, forms and links. A short example of usage:
1850
1851           use Test::More tests => 6;
1852           BEGIN { use_ok( Test::WWW::Mechanize::Catalyst, 'MyApp' ) }
1853
1854           my $mech = Test::WWW::Mechanize::Catalyst->new;
1855           $mech->get_ok("http://localhost/", 'Got index page');
1856           $mech->title_like( qr/^MyApp on Catalyst/, 'Got right index title' );
1857           ok( $mech->find_link( text_regex => qr/^Wiki/i ), 'Found link to Wiki' );
1858           ok( $mech->find_link( text_regex => qr/^Mailing-List/i ), 'Found link to Mailing-List' );
1859           ok( $mech->find_link( text_regex => qr/^IRC channel/i ), 'Found link to IRC channel' );
1860
1861       Further Reading
1862
1863       Catalyst::Test
1864           Catalyst::Test
1865
1866       Test::WWW::Mechanize::Catalyst
1867           <http://search.cpan.org/dist/Test-WWW-Mechanize-Catalyst/lib/Test/WWW/Mechanize/Catalyst.pm>
1868
1869       Test::WWW::Mechanize
1870           <http://search.cpan.org/dist/Test-WWW-Mechanize/Mechanize.pm>
1871
1872       WWW::Mechanize
1873           <http://search.cpan.org/dist/WWW-Mechanize/lib/WWW/Mechanize.pm>
1874
1875       LWP::UserAgent
1876           <http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm>
1877
1878       HTML::Form
1879           <http://search.cpan.org/dist/libwww-perl/lib/HTML/Form.pm>
1880
1881       HTTP::Message
1882           <http://search.cpan.org/dist/libwww-perl/lib/HTTP/Message.pm>
1883
1884       HTTP::Request
1885           <http://search.cpan.org/dist/libwww-perl/lib/HTTP/Request.pm>
1886
1887       HTTP::Request::Common
1888           <http://search.cpan.org/dist/libwww-perl/lib/HTTP/Request/Common.pm>
1889
1890       HTTP::Response
1891           <http://search.cpan.org/dist/libwww-perl/lib/HTTP/Response.pm>
1892
1893       HTTP::Status
1894           <http://search.cpan.org/dist/libwww-perl/lib/HTTP/Status.pm>
1895
1896       URI <http://search.cpan.org/dist/URI/URI.pm>
1897
1898       Test::More
1899           <http://search.cpan.org/dist/Test-Simple/lib/Test/More.pm>
1900
1901       Test::Pod
1902           <http://search.cpan.org/dist/Test-Pod/Pod.pm>
1903
1904       Test::Pod::Coverage
1905           <http://search.cpan.org/dist/Test-Pod-Coverage/Coverage.pm>
1906
1907       prove (Test::Harness)
1908           <http://search.cpan.org/dist/Test-Harness/bin/prove>
1909
1910       More Information
1911
1912       <http://search.cpan.org/perldoc?Catalyst::Plugin::Authorization::Roles>
1913       <http://search.cpan.org/perldoc?Catalyst::Plugin::Authorization::ACL>
1914

AUTHORS

1916       Catalyst Contributors, see Catalyst.pm
1917
1919       This library is free software. You can redistribute it and/or modify it
1920       under the same terms as Perl itself.
1921
1922
1923
1924perl v5.28.1                      2014-12-13     Catalyst::Manual::Cookbook(3)
Impressum