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           ## A page later we retrieve the data from the session:
141
142           sub get_items : Local {
143               my ( $self, $c ) = @_;
144
145               $c->stash->{items_to_display} = $c->session->{items};
146           }
147
148       More information
149
150       Catalyst::Plugin::Session
151
152       Catalyst::Plugin::Session::State::Cookie
153
154       Catalyst::Plugin::Session::State::URI
155
156       Catalyst::Plugin::Session::Store::FastMmap
157
158       Catalyst::Plugin::Session::Store::File
159
160       Catalyst::Plugin::Session::Store::DBI
161
162   Configure your application
163       You configure your application with the "config" method in your
164       application class. This can be hard-coded, or brought in from a
165       separate configuration file.
166
167       Using Config::General
168
169       Config::General is a method for creating flexible and readable
170       configuration files. It's a great way to keep your Catalyst application
171       configuration in one easy-to-understand location.
172
173       Now create myapp.conf in your application home:
174
175         name     MyApp
176
177         # session; perldoc Catalyst::Plugin::Session::FastMmap
178         <Session>
179           expires 3600
180           rewrite 0
181           storage /tmp/myapp.session
182         </Session>
183
184         # emails; perldoc Catalyst::Plugin::Email
185         # this passes options as an array :(
186         Mail SMTP
187         Mail localhost
188
189       This is equivalent to:
190
191         # configure base package
192         __PACKAGE__->config( name => MyApp );
193         # configure authentication
194         __PACKAGE__->config(
195               'Plugin::Authentication' => {
196                   user_class => 'MyApp::Model::MyDB::Customer',
197                   ...
198               },
199         _;
200         # configure sessions
201         __PACKAGE__->config(
202           session => {
203               expires => 3600,
204               ...
205           },
206         );
207         # configure email sending
208         __PACKAGE__->config( email => [qw/SMTP localhost/] );
209
210       Catalyst explains precedence of multiple sources for configuration
211       values, how to access the values in your components, and many 'base'
212       config variables used internally.
213
214       See also Config::General.
215

Skipping your VCS's directories

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

Users and Access Control

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

Models

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

Views

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

Controllers

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

Testing

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

AUTHORS

1900       Catalyst Contributors, see Catalyst.pm
1901
1903       This library is free software. You can redistribute it and/or modify it
1904       under the same terms as Perl itself.
1905
1906
1907
1908perl v5.34.0                      2022-01-20     Catalyst::Manual::Cookbook(3)
Impressum