rollback to use Catalyst qw/@plugins/
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Cookbook.pod
1 =head1 NAME
2
3 Catalyst::Manual::Cookbook - Cooking with Catalyst
4
5 =head1 DESCRIPTION
6
7 Yummy code like your mum used to bake!
8
9 =head1 RECIPES
10
11 =head1 Basics
12
13 These recipes cover some basic stuff that is worth knowing for
14 catalyst developers.
15
16 =head2 Delivering a Custom Error Page
17
18 By default, Catalyst will display its own error page whenever it
19 encounters an error in your application. When running under C<-Debug>
20 mode, the error page is a useful screen including the error message
21 and L<Data::Dump> output of the relevant parts of the C<$c> context
22 object.  When not in C<-Debug>, users see a simple "Please come back
23 later" screen.
24
25 To use a custom error page, use a special C<end> method to
26 short-circuit the error processing. The following is an example; you
27 might want to adjust it further depending on the needs of your
28 application (for example, any calls to C<fillform> will probably need
29 to go into this C<end> method; see L<Catalyst::Plugin::FillInForm>).
30
31     sub end : Private {
32         my ( $self, $c ) = @_;
33
34         if ( scalar @{ $c->error } ) {
35             $c->stash->{errors}   = $c->error;
36             $c->stash->{template} = 'errors.tt';
37             $c->forward('MyApp::View::TT');
38             $c->error(0);
39         }
40
41         return 1 if $c->response->status =~ /^3\d\d$/;
42         return 1 if $c->response->body;
43
44         unless ( $c->response->content_type ) {
45             $c->response->content_type('text/html; charset=utf-8');
46         }
47
48         $c->forward('MyApp::View::TT');
49     }
50
51 You can manually set errors in your code to trigger this page by calling
52
53     $c->error( 'You broke me!' );
54
55 =head2 Disable statistics
56
57 Just add this line to your application class if you don't want those
58 nifty statistics in your debug messages.
59
60     sub Catalyst::Log::info { }
61
62 =head2 Enable debug status in the environment
63
64 Normally you enable the debugging info by adding the C<-Debug> flag to
65 your C<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 C<CATALYST_DEBUG> or
68 C<E<lt>MYAPPE<gt>_DEBUG> to a true value.
69
70 =head2 Sessions
71
72 When you have your users identified, you will want to somehow remember
73 that fact, to save them from having to identify themselves for every
74 single page. One way to do this is to send the username and password
75 parameters in every single page, but that's ugly, and won't work for
76 static pages.
77
78 Sessions are a method of saving data related to some transaction, and
79 giving the whole collection a single ID. This ID is then given to the
80 user to return to us on every page they visit while logged in. The
81 usual way to do this is using a browser cookie.
82
83 Catalyst uses two types of plugins to represent sessions:
84
85 =head3 State
86
87 A State module is used to keep track of the state of the session
88 between the users browser, and your application.
89
90 A common example is the Cookie state module, which sends the browser a
91 cookie containing the session ID. It will use default value for the
92 cookie name and domain, so will "just work" when used.
93
94 =head3 Store
95
96 A Store module is used to hold all the data relating to your session,
97 for example the users ID, or the items for their shopping cart. You
98 can store data in memory (FastMmap), in a file (File) or in a database
99 (DBI).
100
101 =head3 Authentication magic
102
103 If you have included the session modules in your application, the
104 Authentication modules will automagically use your session to save and
105 retrieve the user data for you.
106
107 =head3 Using a session
108
109 Once the session modules are loaded, the session is available as C<<
110 $c->session >>, and can be writen to and read from as a simple hash
111 reference.
112
113 =head3 EXAMPLE
114
115   use parent qw/Catalyst/;
116   use Catalyst  qw/
117                          Session
118                          Session::Store::FastMmap
119                          Session::State::Cookie
120                    /;
121
122
123   ## Write data into the session
124
125   sub add_item : Local {
126      my ( $self, $c ) = @_;
127
128      my $item_id = $c->req->param("item");
129
130      push @{ $c->session->{items} }, $item_id;
131
132   }
133
134   ## A page later we retrieve the data from the session:
135
136   sub get_items : Local {
137      my ( $self, $c ) = @_;
138
139      $c->stash->{items_to_display} = $c->session->{items};
140
141   }
142
143
144 =head3 More information
145
146 L<http://search.cpan.org/dist/Catalyst-Plugin-Session>
147
148 L<http://search.cpan.org/dist/Catalyst-Plugin-Session-State-Cookie>
149
150 L<http://search.cpan.org/dist/Catalyst-Plugin-Session-State-URI>
151
152 L<http://search.cpan.org/dist/Catalyst-Plugin-Session-Store-FastMmap>
153
154 L<http://search.cpan.org/dist/Catalyst-Plugin-Session-Store-File>
155
156 L<http://search.cpan.org/dist/Catalyst-Plugin-Session-Store-DBI>
157
158 =head2 Configure your application
159
160 You configure your application with the C<config> method in your
161 application class. This can be hard-coded, or brought in from a
162 separate configuration file.
163
164 =head3 Using Config::General
165
166 L<Config::General|Config::General> is a method for creating flexible
167 and readable configuration files. It's a great way to keep your
168 Catalyst application configuration in one easy-to-understand location.
169
170 Now create C<myapp.conf> in your application home:
171
172   name     MyApp
173
174   # session; perldoc Catalyst::Plugin::Session::FastMmap
175   <Session>
176     expires 3600
177     rewrite 0
178     storage /tmp/myapp.session
179   </Session>
180
181   # emails; perldoc Catalyst::Plugin::Email
182   # this passes options as an array :(
183   Mail SMTP
184   Mail localhost
185
186 This is equivalent to:
187
188   # configure base package
189   __PACKAGE__->config( name => MyApp );
190   # configure authentication
191   __PACKAGE__->config->{authentication} = {
192     user_class => 'MyApp::Model::MyDB::Customer',
193     ...
194   };
195   # configure sessions
196   __PACKAGE__->config->{session} = {
197     expires => 3600,
198     ...
199   };
200   # configure email sending
201   __PACKAGE__->config->{email} = [qw/SMTP localhost/];
202
203 See also L<Config::General|Config::General>.
204
205 =head1 Skipping your VCS's directories
206
207 Catalyst uses Module::Pluggable to load Models, Views and Controllers.
208 Module::Pluggable will scan through all directories and load modules
209 it finds.  Sometimes you might want to skip some of these directories,
210 for example when your version control system makes a subdirectory with
211 meta-information in every version-controlled directory.  While
212 Catalyst skips subversion and CVS directories already, there are other
213 source control systems.  Here is the configuration you need to add
214 their directories to the list to skip.
215
216 You can make catalyst skip these directories using the Catalyst config:
217
218   # Configure the application
219   __PACKAGE__->config(
220       name => 'MyApp',
221       setup_components => { except => qr/SCCS/ },
222   );
223
224 See the Module::Pluggable manual page for more information on B<except>
225 and other options.
226
227 =head1 Users and Access Control
228
229 Most multiuser, and some single user web applications require that
230 users identify themselves, and the application is often required to
231 define those roles.  The recipes below describe some ways of doing
232 this.
233
234 =head2 Authentication (logging in)
235
236 This is extensively covered in other documentation; see in particular
237 L<Catalyst::Plugin::Authentication> and the Authentication chapter
238 of the Tutorial at L<Catalyst::Manual::Tutorial::Authorization>.
239
240 =head2 Pass-through login (and other actions)
241
242 An easy way of having assorted actions that occur during the processing
243 of a request that are orthogonal to its actual purpose - logins, silent
244 commands etc. Provide actions for these, but when they're required for
245 something else fill e.g. a form variable __login and have a sub begin
246 like so:
247
248     sub begin : Private {
249       my ($self, $c) = @_;
250       foreach my $action (qw/login docommand foo bar whatever/) {
251         if ($c->req->params->{"__${action}"}) {
252           $c->forward($action);
253         }
254       }
255     }
256
257
258 =head2 Role-based Authorization
259
260 For more advanced access control, you may want to consider using role-based
261 authorization. This means you can assign different roles to each user, e.g.
262 "user", "admin", etc.
263
264 The C<login> and C<logout> methods and view template are exactly the same as
265 in the previous example.
266
267 The L<Catalyst::Plugin::Authorization::Roles> plugin is required when
268 implementing roles:
269
270  use parent qw/Catalyst/;
271  use Catalyst qw/
272      Authentication
273      Authentication::Credential::Password
274      Authentication::Store::Htpasswd
275      Authorization::Roles/;
276
277 Roles are implemented automatically when using
278 L<Catalyst::Authentication::Store::Htpasswd>:
279
280   # no additional role configuration required
281   __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile";
282
283 Or can be set up manually when using L<Catalyst::Authentication::Store::DBIC>:
284
285   # Authorization using a many-to-many role relationship
286   __PACKAGE__->config->{authorization}{dbic} = {
287     'role_class'           => 'My::Model::DBIC::Role',
288     'role_field'           => 'name',
289     'user_role_user_field' => 'user',
290
291     # DBIx::Class only (omit if using Class::DBI)
292     'role_rel'             => 'user_role',
293
294     # Class::DBI only, (omit if using DBIx::Class)
295     'user_role_class'      => 'My::Model::CDBI::UserRole'
296     'user_role_role_field' => 'role',
297   };
298
299 To restrict access to any action, you can use the C<check_user_roles> method:
300
301   sub restricted : Local {
302      my ( $self, $c ) = @_;
303
304      $c->detach("unauthorized")
305        unless $c->check_user_roles( "admin" );
306
307      # do something restricted here
308   }
309
310 You can also use the C<assert_user_roles> method. This just gives an
311 error if the current user does not have one of the required roles:
312
313   sub also_restricted : Global {
314     my ( $self, $c ) = @_;
315     $c->assert_user_roles( qw/ user admin / );
316   }
317   
318 =head2 Authentication/Authorization
319
320 This is done in several steps:
321
322 =over 4
323
324 =item Verification
325
326 Getting the user to identify themselves, by giving you some piece of
327 information known only to you and the user. Then you can assume that
328 the user is who they say they are. This is called B<credential
329 verification>.
330
331 =item Authorization
332
333 Making sure the user only accesses functions you want them to
334 access. This is done by checking the verified users data against your
335 internal list of groups, or allowed persons for the current page.
336
337 =back
338
339 =head3 Modules
340
341 The Catalyst Authentication system is made up of many interacting
342 modules, to give you the most flexibility possible.
343
344 =head4 Credential verifiers
345
346 A Credential module tables the user input, and passes it to a Store,
347 or some other system, for verification. Typically, a user object is
348 created by either this module or the Store and made accessible by a
349 C<< $c->user >> call.
350
351 Examples:
352
353  Password - Simple username/password checking.
354  HTTPD    - Checks using basic HTTP auth.
355  TypeKey  - Check using the typekey system.
356
357 =head3 Storage backends
358
359 A Storage backend contains the actual data representing the users. It
360 is queried by the credential verifiers. Updating the store is not done
361 within this system, you will need to do it yourself.
362
363 Examples:
364
365  DBIC     - Storage using a database.
366  Minimal  - Storage using a simple hash (for testing).
367
368 =head3 User objects
369
370 A User object is created by either the storage backend or the
371 credential verifier, and filled with the retrieved user information.
372
373 Examples:
374
375  Hash     - A simple hash of keys and values.
376
377 =head3 ACL authorization
378
379 ACL stands for Access Control List. The ACL plugin allows you to
380 regulate access on a path by path basis, by listing which users, or
381 roles, have access to which paths.
382
383 =head3 Roles authorization
384
385 Authorization by roles is for assigning users to groups, which can
386 then be assigned to ACLs, or just checked when needed.
387
388 =head3 Logging in
389
390 When you have chosen your modules, all you need to do is call the C<<
391 $c->login >> method. If called with no parameters, it will try to find
392 suitable parameters, such as B<username> and B<password>, or you can
393 pass it these values.
394
395 =head3 Checking roles
396
397 Role checking is done by using the C<< $c->check_user_roles >> method,
398 this will check using the currently logged in user (via C<< $c->user
399 >>). You pass it the name of a role to check, and it returns true if
400 the user is a member.
401
402 =head3 EXAMPLE
403
404  use parent qw/Catalyst/;
405  use Catalyst qw/Authentication
406                  Authentication::Credential::Password
407                  Authentication::Store::Htpasswd
408                  Authorization::Roles/;
409
410  __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile";
411
412   sub login : Local {
413      my ($self, $c) = @_;
414
415      if (    my $user = $c->req->param("user")
416          and my $password = $c->req->param("password") )
417      {
418          if ( $c->login( $user, $password ) ) {
419               $c->res->body( "hello " . $c->user->name );
420          } else {
421             # login incorrect
422          }
423      }
424      else {
425          # invalid form input
426      }
427   }
428
429   sub restricted : Local {
430      my ( $self, $c ) = @_;
431
432      $c->detach("unauthorized")
433        unless $c->check_user_roles( "admin" );
434
435      # do something restricted here
436   }
437
438 =head3 Using authentication in a testing environment
439
440 Ideally, to write tests for authentication/authorization code one
441 would first set up a test database with known data, then use
442 L<Test::WWW::Mechanize::Catalyst> to simulate a user logging
443 in. Unfortunately the former can be rather awkward, which is why it's
444 a good thing that the authentication framework is so flexible.
445
446 Instead of using a test database, one can simply change the
447 authentication store to something a bit easier to deal with in a
448 testing environment. Additionally, this has the advantage of not
449 modifying one's database, which can be problematic if one forgets to
450 use the testing instead of production database.
451
452 e.g.,
453
454   use Catalyst::Plugin::Authentication::Store::Minimal::Backend;
455
456   # Sets up the user `test_user' with password `test_pass'
457   MyApp->default_auth_store(
458     Catalyst::Plugin::Authentication::Store::Minimal::Backend->new({
459       test_user => { password => 'test_pass' },
460     })
461   );
462
463 Now, your test code can call C<$c->login('test_user', 'test_pass')> and
464 successfully login, without messing with the database at all.
465
466 =head3 More information
467
468 L<http://search.cpan.org/perldoc?Catalyst::Plugin::Authentication> has a longer explanation.
469
470 =head2 Authorization
471
472 =head3 Introduction
473
474 Authorization is the step that comes after
475 authentication. Authentication establishes that the user agent is
476 really representing the user we think it's representing, and then
477 authorization determines what this user is allowed to do.
478
479 =head3 Role Based Access Control
480
481 Under role based access control each user is allowed to perform any
482 number of roles. For example, at a zoo no one but specially trained
483 personnel can enter the moose cage (Mynd you, møøse bites kan be
484 pretty nasti!). For example:
485
486     package Zoo::Controller::MooseCage;
487
488     sub feed_moose : Local {
489         my ( $self, $c ) = @_;
490
491         $c->model( "Moose" )->eat( $c->req->param("food") );
492     }
493
494 With this action, anyone can just come into the moose cage and feed
495 the moose, which is a very dangerous thing. We need to restrict this
496 action, so that only a qualified moose feeder can perform that action.
497
498 The Authorization::Roles plugin let's us perform role based access
499 control checks. Let's load it:
500
501     use parent qw/Catalyst/;
502     use Catalyst qw/
503                     Authentication # yadda yadda
504                     Authorization::Roles
505                   /;
506
507 And now our action should look like this:
508
509     sub feed_moose : Local {
510         my ( $self, $c ) = @_;
511
512         if ( $c->check_roles( "moose_feeder" ) ) {
513             $c->model( "Moose" )->eat( $c->req->param("food") );
514         } else {
515             $c->stash->{error} = "unauthorized";
516         }
517     }
518
519 This checks C<< $c->user >>, and only if the user has B<all> the roles
520 in the list, a true value is returned.
521
522 C<check_roles> has a sister method, C<assert_roles>, which throws an
523 exception if any roles are missing.
524
525 Some roles that might actually make sense in, say, a forum application:
526
527 =over 4
528
529 =item *
530
531 administrator
532
533 =item *
534
535 moderator
536
537 =back
538
539 each with a distinct task (system administration versus content
540 administration).
541
542 =head3 Access Control Lists
543
544 Checking for roles all the time can be tedious and error prone.
545
546 The Authorization::ACL plugin let's us declare where we'd like checks
547 to be done automatically for us.
548
549 For example, we may want to completely block out anyone who isn't a
550 C<moose_feeder> from the entire C<MooseCage> controller:
551
552     Zoo->deny_access_unless( "/moose_cage", [qw/moose_feeder/] );
553
554 The role list behaves in the same way as C<check_roles>. However, the
555 ACL plugin isn't limited to just interacting with the Roles plugin. We
556 can use a code reference instead. For example, to allow either moose
557 trainers or moose feeders into the moose cage, we can create a more
558 complex check:
559
560     Zoo->deny_access_unless( "/moose_cage", sub {
561         my $c = shift;
562         $c->check_roles( "moose_trainer" ) || $c->check_roles( "moose_feeder" );
563     });
564
565 The more specific a role, the earlier it will be checked. Let's say
566 moose feeders are now restricted to only the C<feed_moose> action,
567 while moose trainers get access everywhere:
568
569     Zoo->deny_access_unless( "/moose_cage", [qw/moose_trainer/] );
570     Zoo->allow_access_if( "/moose_cage/feed_moose", [qw/moose_feeder/]);
571
572 When the C<feed_moose> action is accessed the second check will be
573 made. If the user is a C<moose_feeder>, then access will be
574 immediately granted. Otherwise, the next rule in line will be tested -
575 the one checking for a C<moose_trainer>.  If this rule is not
576 satisfied, access will be immediately denied.
577
578 Rules applied to the same path will be checked in the order they were
579 added.
580
581 Lastly, handling access denial events is done by creating an
582 C<access_denied> private action:
583
584     sub access_denied : Private {
585         my ( $self, $c, $action ) = @_;
586     }
587
588 This action works much like auto, in that it is inherited across
589 namespaces (not like object oriented code). This means that the
590 C<access_denied> action which is B<nearest> to the action which was
591 blocked will be triggered.
592
593 If this action does not exist, an error will be thrown, which you can
594 clean up in your C<end> private action instead.
595
596 Also, it's important to note that if you restrict access to "/" then
597 C<end>, C<default>, etc will also be restricted.
598
599    MyApp->acl_allow_root_internals;
600
601 will create rules that permit access to C<end>, C<begin>, and C<auto> in the
602 root of your app (but not in any other controller).
603
604 =head1 Models
605
606 Models are where application data belongs.  Catalyst is exteremely
607 flexible with the kind of models that it can use.  The recipes here
608 are just the start.
609
610 =head2 Using existing DBIC (etc.) classes with Catalyst
611
612 Many people have existing Model classes that they would like to use
613 with Catalyst (or, conversely, they want to write Catalyst models that
614 can be used outside of Catalyst, e.g.  in a cron job). It's trivial to
615 write a simple component in Catalyst that slurps in an outside Model:
616
617     package MyApp::Model::DB;
618     use base qw/Catalyst::Model::DBIC::Schema/;
619     __PACKAGE__->config(
620         schema_class => 'Some::DBIC::Schema',
621         connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}];
622     );
623     1;
624
625 and that's it! Now C<Some::DBIC::Schema> is part of your
626 Cat app as C<MyApp::Model::DB>.
627
628 =head2 DBIx::Class as a Catalyst Model
629
630 See L<Catalyst::Model::DBIC::Schema>.
631
632 =head2 Create accessors to preload static data once per server instance
633
634 When you have data that you want to load just once from the model at
635 server load instead of for each request, use mk_group_accessors to
636 create accessors and tie them to resultsets in your package that
637 inherits from DBIx::Class::Schema
638
639     package My::Schema;
640     use base qw/DBIx::Class::Schema/;
641     __PACKAGE__->register_class('RESULTSOURCEMONIKER',
642                                 'My::Schema::RESULTSOURCE');
643     __PACKAGE__->mk_group_accessors('simple' =>
644                                 qw(ACCESSORNAME1 ACCESSORNAME2 ACCESSORNAMEn));
645
646     sub connection {
647         my ($self, @rest) = @_;
648         $self->next::method(@rest);
649         # $self is now a live My::Schema object, complete with DB connection 
650
651         $self->ACCESSORNAME1([ $self->resultset('RESULTSOURCEMONIKER')->all ]);
652         $self->ACCESSORNAME2([ $self->resultset('RESULTSOURCEMONIKER')->search({ COLUMN => { '<' => '30' } })->all ]);
653         $self->ACCESSORNAMEn([ $self->resultset('RESULTSOURCEMONIKER')->find(1) ]);
654     }
655
656     1;
657
658 and now in the controller, you can now access any of these without a
659 per-request fetch:
660
661     $c->stash->{something} = $c->model('My::Schema')->schema->ACCESSORNAMEn;
662
663
664 =head2 XMLRPC
665
666 Unlike SOAP, XMLRPC is a very simple (and imo elegant) web-services
667 protocol, exchanging small XML messages like these:
668
669 Request:
670
671     POST /api HTTP/1.1
672     TE: deflate,gzip;q=0.3
673     Connection: TE, close
674     Accept: text/xml
675     Accept: multipart/*
676     Host: 127.0.0.1:3000
677     User-Agent: SOAP::Lite/Perl/0.60
678     Content-Length: 192
679     Content-Type: text/xml
680
681     <?xml version="1.0" encoding="UTF-8"?>
682     <methodCall>
683         <methodName>add</methodName>
684         <params>
685             <param><value><int>1</int></value></param>
686             <param><value><int>2</int></value></param>
687         </params>
688     </methodCall>
689
690 Response:
691
692     Connection: close
693     Date: Tue, 20 Dec 2005 07:45:55 GMT
694     Content-Length: 133
695     Content-Type: text/xml
696     Status: 200
697     X-Catalyst: 5.70
698
699     <?xml version="1.0" encoding="us-ascii"?>
700     <methodResponse>
701         <params>
702             <param><value><int>3</int></value></param>
703         </params>
704     </methodResponse>
705
706 Now follow these few steps to implement the application:
707
708 1. Install Catalyst (5.61 or later), Catalyst::Plugin::XMLRPC (0.06 or
709 later) and SOAP::Lite (for XMLRPCsh.pl).
710
711 2. Create an application framework:
712
713     % catalyst.pl MyApp
714     ...
715     % cd MyApp
716
717 3. Add the XMLRPC plugin to MyApp.pm
718
719     use Catalyst qw/-Debug Static::Simple XMLRPC/;
720
721 4. Add an API controller
722
723     % ./script/myapp_create.pl controller API
724
725 5. Add a XMLRPC redispatch method and an add method with Remote
726 attribute to lib/MyApp/Controller/API.pm
727
728     sub default :Path {
729         my ( $self, $c ) = @_;
730         $c->xmlrpc;
731     }
732
733     sub add : Remote {
734         my ( $self, $c, $a, $b ) = @_;
735         return $a + $b;
736     }
737
738 The default action is the entry point for each XMLRPC request. It will
739 redispatch every request to methods with Remote attribute in the same
740 class.
741
742 The C<add> method is not a traditional action; it has no private or
743 public path. Only the XMLRPC dispatcher knows it exists.
744
745 6. That's it! You have built your first web service. Let's test it with
746 XMLRPCsh.pl (part of SOAP::Lite):
747
748     % ./script/myapp_server.pl
749     ...
750     % XMLRPCsh.pl http://127.0.0.1:3000/api
751     Usage: method[(parameters)]
752     > add( 1, 2 )
753     --- XMLRPC RESULT ---
754     '3'
755
756 =head3 Tip
757
758 Your return data type is usually auto-detected, but you can easily
759 enforce a specific one.
760
761     sub add : Remote {
762         my ( $self, $c, $a, $b ) = @_;
763         return RPC::XML::int->new( $a + $b );
764     }
765     
766
767
768 =head1 Views
769
770 Views pertain to the display of your application.  As with models,
771 catalyst is uncommonly flexible.  The recipes below are just a start.
772
773 =head2 Catalyst::View::TT
774
775 One of the first things you probably want to do when starting a new
776 Catalyst application is set up your View. Catalyst doesn't care how you
777 display your data; you can choose to generate HTML, PDF files, or plain
778 text if you wanted.
779
780 Most Catalyst applications use a template system to generate their HTML,
781 and though there are several template systems available, Template
782 Toolkit is probably the most popular.
783
784 Once again, the Catalyst developers have done all the hard work, and
785 made things easy for the rest of us. Catalyst::View::TT provides the
786 interface to Template Toolkit, and provides Helpers which let us set it
787 up that much more easily.
788
789 =head3 Creating your View
790
791 Catalyst::View::TT provides two different helpers for us to use: TT and
792 TTSite.
793
794 =head4 TT
795
796 Create a basic Template Toolkit View using the provided helper script:
797
798     script/myapp_create.pl view TT TT
799
800 This will create lib/MyApp/View/MyView.pm, which is going to be pretty
801 empty to start. However, it sets everything up that you need to get
802 started. You can now define which template you want and forward to your
803 view. For instance:
804
805     sub hello : Local {
806         my ( $self, $c ) = @_;
807
808         $c->stash->{template} = 'hello.tt';
809
810         $c->forward( $c->view('TT') );
811     }
812
813 In practice you wouldn't do the forwarding manually, but would
814 use L<Catalyst::Action::RenderView>.
815
816 =head4 TTSite
817
818 Although the TT helper does create a functional, working view, you may
819 find yourself having to create the same template files and changing the
820 same options every time you create a new application. The TTSite helper
821 saves us even more time by creating the basic templates and setting some
822 common options for us.
823
824 Once again, you can use the helper script:
825
826     script/myapp_create.pl view TT TTSite
827
828 This time, the helper sets several options for us in the generated View.
829
830     __PACKAGE__->config({
831         CATALYST_VAR => 'Catalyst',
832         INCLUDE_PATH => [
833             MyApp->path_to( 'root', 'src' ),
834             MyApp->path_to( 'root', 'lib' )
835         ],
836         PRE_PROCESS  => 'config/main',
837         WRAPPER      => 'site/wrapper',
838         ERROR        => 'error.tt2',
839         TIMER        => 0
840     });
841
842 =over
843
844 =item 
845
846 INCLUDE_PATH defines the directories that Template Toolkit should search
847 for the template files.
848
849 =item
850
851 PRE_PROCESS is used to process configuration options which are common to
852 every template file.
853
854 =item
855
856 WRAPPER is a file which is processed with each template, usually used to
857 easily provide a common header and footer for every page.
858
859 =back
860
861 In addition to setting these options, the TTSite helper also created the
862 template and config files for us! In the 'root' directory, you'll notice
863 two new directories: src and lib.
864
865 Several configuration files in root/lib/config are called by PRE_PROCESS.
866
867 The files in root/lib/site are the site-wide templates, called by
868 WRAPPER, and display the html framework, control the layout, and provide
869 the templates for the header and footer of your page. Using the template
870 organization provided makes it much easier to standardize pages and make
871 changes when they are (inevitably) needed.
872
873 The template files that you will create for your application will go
874 into root/src, and you don't need to worry about putting the the <html>
875 or <head> sections; just put in the content. The WRAPPER will the rest
876 of the page around your template for you.
877
878
879 =head3 $c->stash
880
881 Of course, having the template system include the header and footer for
882 you isn't all that we want our templates to do. We need to be able to
883 put data into our templates, and have it appear where and how we want
884 it, right? That's where the stash comes in.
885
886 In our controllers, we can add data to the stash, and then access it
887 from the template. For instance:
888
889     sub hello : Local {
890         my ( $self, $c ) = @_;
891
892         $c->stash->{name} = 'Adam';
893
894         $c->stash->{template} = 'hello.tt';
895
896         $c->forward( $c->view('TT') );
897     }
898
899 Then, in hello.tt:
900
901     <strong>Hello, [% name %]!</strong>
902
903 When you view this page, it will display "Hello, Adam!"
904
905 All of the information in your stash is available, by its name/key, in
906 your templates. And your data don't have to be plain, old, boring
907 scalars. You can pass array references and hash references, too.
908
909 In your controller:
910
911     sub hello : Local {
912         my ( $self, $c ) = @_;
913
914         $c->stash->{names} = [ 'Adam', 'Dave', 'John' ];
915
916         $c->stash->{template} = 'hello.tt';
917
918         $c->forward( $c->view('TT') );
919     }
920
921 In hello.tt:
922
923     [% FOREACH name IN names %]
924         <strong>Hello, [% name %]!</strong><br />
925     [% END %]
926
927 This allowed us to loop through each item in the arrayref, and display a
928 line for each name that we have.
929
930 This is the most basic usage, but Template Toolkit is quite powerful,
931 and allows you to truly keep your presentation logic separate from the
932 rest of your application.
933
934 =head3 $c->uri_for()
935
936 One of my favorite things about Catalyst is the ability to move an
937 application around without having to worry that everything is going to
938 break. One of the areas that used to be a problem was with the http
939 links in your template files. For example, suppose you have an
940 application installed at http://www.domain.com/Calendar. The links point
941 to "/Calendar", "/Calendar/2005", "/Calendar/2005/10", etc.  If you move
942 the application to be at http://www.mydomain.com/Tools/Calendar, then
943 all of those links will suddenly break.
944
945 That's where $c->uri_for() comes in. This function will merge its
946 parameters with either the base location for the app, or its current
947 namespace. Let's take a look at a couple of examples.
948
949 In your template, you can use the following:
950
951     <a href="[% c.uri_for('/login') %]">Login Here</a>
952
953 Although the parameter starts with a forward slash, this is relative
954 to the application root, not the webserver root. This is important to
955 remember. So, if your application is installed at
956 http://www.domain.com/Calendar, then the link would be
957 http://www.mydomain.com/Calendar/Login. If you move your application
958 to a different domain or path, then that link will still be correct.
959
960 Likewise,
961
962     <a href="[% c.uri_for('2005','10', '24') %]">October, 24 2005</a>
963
964 The first parameter does NOT have a forward slash, and so it will be
965 relative to the current namespace. If the application is installed at
966 http://www.domain.com/Calendar. and if the template is called from
967 MyApp::Controller::Display, then the link would become
968 http://www.domain.com/Calendar/Display/2005/10/24.
969
970 If you want to link to a parent uri of your current namespace you can
971 prefix the arguments with multiple '../':
972
973     <a href="[% c.uri_for('../../view', stashed_object.id) %]">User view</a>
974
975 Once again, this allows you to move your application around without
976 having to worry about broken links. But there's something else, as
977 well. Since the links are generated by uri_for, you can use the same
978 template file by several different controllers, and each controller
979 will get the links that its supposed to. Since we believe in Don't
980 Repeat Yourself, this is particularly helpful if you have common
981 elements in your site that you want to keep in one file.
982
983 Further Reading:
984
985 L<http://search.cpan.org/perldoc?Catalyst>
986
987 L<http://search.cpan.org/perldoc?Catalyst%3A%3AView%3A%3ATT>
988
989 L<http://search.cpan.org/perldoc?Template>
990
991 =head2 Adding RSS feeds 
992
993 Adding RSS feeds to your Catalyst applications is simple. We'll see two
994 different aproaches here, but the basic premise is that you forward to
995 the normal view action first to get the objects, then handle the output
996 differently.
997
998 =head3 Using TT templates
999
1000 This is the aproach used in Agave (L<http://dev.rawmode.org/>).
1001
1002     sub rss : Local {
1003         my ($self,$c) = @_;
1004         $c->forward('view');
1005         $c->stash->{template}='rss.tt';
1006     }
1007
1008 Then you need a template. Here's the one from Agave: 
1009
1010     <?xml version="1.0" encoding="UTF-8"?>
1011     <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
1012       <channel>
1013         <title>[ [% blog.name || c.config.name || "Agave" %] ] RSS Feed</title>
1014         <link>[% base %]</link>
1015         <description>Recent posts</description>
1016         <language>en-us</language>
1017         <ttl>40</ttl>
1018      [% WHILE (post = posts.next) %]
1019       <item>
1020         <title>[% post.title %]</title>
1021         <description>[% post.formatted_teaser|html%]</description>    
1022         <pubDate>[% post.pub_date %]</pubDate>
1023         <guid>[% post.full_uri %]</guid>
1024         <link>[% post.full_uri %]</link>
1025         <dc:creator>[% post.author.screenname %]</dc:creator>
1026       </item>
1027     [% END %]
1028       </channel>
1029     </rss> 
1030
1031 =head3 Using XML::Feed
1032
1033 A more robust solution is to use XML::Feed, as was done in the Catalyst
1034 Advent Calendar. Assuming we have a C<view> action that populates
1035 'entries' with some DBIx::Class iterator, the code would look something
1036 like this:
1037
1038     sub rss : Local {
1039         my ($self,$c) = @_;
1040         $c->forward('view'); # get the entries
1041
1042         my $feed = XML::Feed->new('RSS');
1043         $feed->title( $c->config->{name} . ' RSS Feed' );
1044         $feed->link( $c->req->base ); # link to the site.
1045         $feed->description('Catalyst advent calendar'); Some description
1046
1047         # Process the entries
1048         while( my $entry = $c->stash->{entries}->next ) {
1049             my $feed_entry = XML::Feed::Entry->new('RSS');
1050             $feed_entry->title($entry->title);
1051             $feed_entry->link( $c->uri_for($entry->link) );
1052             $feed_entry->issued( DateTime->from_epoch(epoch => $entry->created) );
1053             $feed->add_entry($feed_entry);
1054         }
1055         $c->res->body( $feed->as_xml );
1056    }
1057
1058 A little more code in the controller, but with this approach you're
1059 pretty sure to get something that validates. 
1060
1061 Note that for both of the above aproaches, you'll need to set the
1062 content type like this:
1063
1064     $c->res->content_type('application/rss+xml');
1065
1066 =head3 Final words
1067
1068 You could generalize the second variant easily by replacing 'RSS' with a
1069 variable, so you can generate Atom feeds with the same code.
1070
1071 Now, go ahead and make RSS feeds for all your stuff. The world *needs*
1072 updates on your goldfish!
1073
1074 =head2 Forcing the browser to download content
1075
1076 Sometimes you need your application to send content for download. For
1077 example, you can generate a comma-separated values (CSV) file for your
1078 users to download and import into their spreadsheet program.
1079
1080 Let's say you have an C<Orders> controller which generates a CSV file
1081 in the C<export> action (i.e., C<http://localhost:3000/orders/export>):
1082
1083     sub export : Local Args(0) {
1084         my ( $self, $c ) = @_;
1085
1086         # In a real application, you'd generate this from the database
1087         my $csv = "1,5.99\n2,29.99\n3,3.99\n";
1088
1089         $c->res->content_type('text/comma-separated-values');
1090         $c->res->body($csv);
1091     }
1092
1093 Normally the browser uses the last part of the URI to generate a
1094 filename for data it cannot display. In this case your browser would
1095 likely ask you to save a file named C<export>.
1096
1097 Luckily you can have the browser download the content with a specific
1098 filename by setting the C<Content-Disposition> header:
1099
1100     my $filename = 'Important Orders.csv';
1101     $c->res->header('Content-Disposition', qq[attachment; filename="$filename"]);
1102
1103 Note the use of quotes around the filename; this ensures that any
1104 spaces in the filename are handled by the browser.
1105
1106 Put this right before calling C<< $c->res->body >> and your browser
1107 will download a file named C<Important Orders.csv> instead of
1108 C<export>.
1109
1110 You can also use this to have the browser download content which it
1111 normally displays, such as JPEG images or even HTML. Just be sure to
1112 set the appropriate content type and disposition.
1113
1114
1115 =head1 Controllers
1116
1117 Controllers are the main point of communication between the web server
1118 and your application.  Here we explore some aspects of how they work.
1119
1120 =head2 Extending RenderView (formerly DefaultEnd)
1121
1122 The recommended approach for an C<end> action is to use
1123 L<Catalyst::Action::RenderView> (taking the place of
1124 L<Catalyst::Plugin::DefaultEnd>), which does what you usually need.
1125 However there are times when you need to add a bit to it, but don't want
1126 to write your own C<end> action.
1127
1128 You can extend it like this:
1129
1130 To add something to an C<end> action that is called before rendering
1131 (this is likely to be what you want), simply place it in the C<end>
1132 method:
1133
1134     sub end : ActionClass('RenderView') {
1135       my ( $self, $c ) = @_;
1136       # do stuff here; the RenderView action is called afterwards
1137     }
1138
1139 To add things to an C<end> action that are called I<after> rendering,
1140 you can set it up like this:
1141
1142     sub render : ActionClass('RenderView') { }
1143
1144     sub end : Private { 
1145       my ( $self, $c ) = @_;
1146       $c->forward('render');
1147       # do stuff here
1148     }
1149   
1150 =head2 Action Types
1151
1152 =head3 Introduction
1153
1154 A Catalyst application is driven by one or more Controller
1155 modules. There are a number of ways that Catalyst can decide which of
1156 the methods in your controller modules it should call. Controller
1157 methods are also called actions, because they determine how your
1158 catalyst application should (re-)act to any given URL. When the
1159 application is started up, catalyst looks at all your actions, and
1160 decides which URLs they map to.
1161
1162 =head3 Type attributes
1163
1164 Each action is a normal method in your controller, except that it has an
1165 L<attribute|http://search.cpan.org/~nwclark/perl-5.8.7/lib/attributes.pm>
1166 attached. These can be one of several types.
1167
1168 Assume our Controller module starts with the following package declaration:
1169
1170  package MyApp::Controller::Buckets;
1171
1172 and we are running our application on localhost, port 3000 (the test
1173 server default).
1174
1175 =over 4
1176
1177 =item Path
1178
1179 A Path attribute also takes an argument, this can be either a relative
1180 or an absolute path. A relative path will be relative to the
1181 controller namespace, an absolute path will represent an exact
1182 matching URL.
1183
1184  sub my_handles : Path('handles') { .. }
1185
1186 becomes
1187
1188  http://localhost:3000/buckets/handles
1189
1190 and
1191
1192  sub my_handles : Path('/handles') { .. }
1193
1194 becomes 
1195
1196  http://localhost:3000/handles
1197
1198 =item Local
1199
1200 When using a Local attribute, no parameters are needed, instead, the
1201 name of the action is matched in the URL. The namespaces created by
1202 the name of the controller package is always part of the URL.
1203
1204  sub my_handles : Local { .. }
1205
1206 becomes
1207
1208  http://localhost:3000/buckets/my_handles
1209
1210 =item Global
1211
1212 A Global attribute is similar to a Local attribute, except that the
1213 namespace of the controller is ignored, and matching starts at root.
1214
1215  sub my_handles : Global { .. }
1216
1217 becomes
1218
1219  http://localhost:3000/my_handles
1220
1221 =item Regex
1222
1223 By now you should have figured that a Regex attribute is just what it
1224 sounds like. This one takes a regular expression, and matches starting
1225 from root. These differ from the rest as they can match multiple URLs.
1226
1227  sub my_handles : Regex('^handles') { .. }
1228
1229 matches
1230
1231  http://localhost:3000/handles
1232
1233 and 
1234
1235  http://localhost:3000/handles_and_other_parts
1236
1237 etc.
1238
1239 =item LocalRegex
1240
1241 A LocalRegex is similar to a Regex, except it only matches below the current
1242 controller namespace.
1243
1244  sub my_handles : LocalRegex(^handles') { .. }
1245
1246 matches
1247
1248  http://localhost:3000/buckets/handles
1249
1250 and
1251
1252  http://localhost:3000/buckets/handles_and_other_parts
1253
1254 etc.
1255
1256 =item Private
1257
1258 Last but not least, there is the Private attribute, which allows you
1259 to create your own internal actions, which can be forwarded to, but
1260 won't be matched as URLs.
1261
1262  sub my_handles : Private { .. }
1263
1264 becomes nothing at all..
1265
1266 Catalyst also predefines some special Private actions, which you can
1267 override, these are:
1268
1269 =over 4
1270
1271 =item default
1272
1273 The default action will be called, if no other matching action is
1274 found. If you don't have one of these in your namespace, or any sub
1275 part of your namespace, you'll get an error page instead. If you want
1276 to find out where it was the user was trying to go, you can look in
1277 the request object using C<< $c->req->path >>.
1278
1279  sub default :Path { .. }
1280
1281 works for all unknown URLs, in this controller namespace, or every one
1282 if put directly into MyApp.pm.
1283
1284 =item index 
1285
1286 The index action is called when someone tries to visit the exact
1287 namespace of your controller. If index, default and matching Path
1288 actions are defined, then index will be used instead of default and
1289 Path.
1290
1291  sub index :Path :Args(0) { .. }
1292
1293 becomes
1294
1295  http://localhost:3000/buckets
1296
1297 =item begin
1298
1299 The begin action is called at the beginning of every request involving
1300 this namespace directly, before other matching actions are called. It
1301 can be used to set up variables/data for this particular part of your
1302 app. A single begin action is called, its always the one most relevant
1303 to the current namespace.
1304
1305  sub begin : Private { .. }
1306
1307 is called once when 
1308
1309  http://localhost:3000/bucket/(anything)?
1310
1311 is visited.
1312
1313 =item end
1314
1315 Like begin, this action is always called for the namespace it is in,
1316 after every other action has finished. It is commonly used to forward
1317 processing to the View component. A single end action is called, its
1318 always the one most relevant to the current namespace.
1319
1320
1321  sub end : Private { .. }
1322
1323 is called once after any actions when
1324
1325  http://localhost:3000/bucket/(anything)?
1326
1327 is visited.
1328
1329 =item auto
1330
1331 Lastly, the auto action is magic in that B<every> auto action in the
1332 chain of paths up to and including the ending namespace, will be
1333 called. (In contrast, only one of the begin/end/default actions will
1334 be called, the relevant one).
1335
1336  package MyApp.pm;
1337  sub auto : Private { .. }
1338
1339 and 
1340
1341  sub auto : Private { .. }
1342
1343 will both be called when visiting 
1344
1345  http://localhost:3000/bucket/(anything)?
1346
1347 =back
1348
1349 =back
1350
1351 =head3 A word of warning
1352
1353 Due to possible namespace conflicts with Plugins, it is advised to
1354 only put the pre-defined Private actions in your main MyApp.pm file,
1355 all others should go in a Controller module.
1356
1357 =head3 More Information
1358
1359 L<http://search.cpan.org/author/SRI/Catalyst-5.61/lib/Catalyst/Manual/Intro.pod>
1360
1361 L<http://dev.catalyst.perl.org/wiki/FlowChart>
1362
1363 =head2 Component-based Subrequests
1364
1365 See L<Catalyst::Plugin::SubRequest>.
1366
1367 =head2 File uploads
1368
1369 =head3 Single file upload with Catalyst
1370
1371 To implement uploads in Catalyst, you need to have a HTML form similar to
1372 this:
1373
1374     <form action="/upload" method="post" enctype="multipart/form-data">
1375       <input type="hidden" name="form_submit" value="yes">
1376       <input type="file" name="my_file">
1377       <input type="submit" value="Send">
1378     </form>
1379
1380 It's very important not to forget C<enctype="multipart/form-data"> in
1381 the form.
1382
1383 Catalyst Controller module 'upload' action:
1384
1385     sub upload : Global {
1386         my ($self, $c) = @_;
1387
1388         if ( $c->request->parameters->{form_submit} eq 'yes' ) {
1389
1390             if ( my $upload = $c->request->upload('my_file') ) {
1391
1392                 my $filename = $upload->filename;
1393                 my $target   = "/tmp/upload/$filename";
1394
1395                 unless ( $upload->link_to($target) || $upload->copy_to($target) ) {
1396                     die( "Failed to copy '$filename' to '$target': $!" );
1397                 }
1398             }
1399         }
1400
1401         $c->stash->{template} = 'file_upload.html';
1402     }
1403
1404 =head3 Multiple file upload with Catalyst
1405
1406 Code for uploading multiple files from one form needs a few changes:
1407
1408 The form should have this basic structure:
1409
1410     <form action="/upload" method="post" enctype="multipart/form-data">
1411       <input type="hidden" name="form_submit" value="yes">
1412       <input type="file" name="file1" size="50"><br>
1413       <input type="file" name="file2" size="50"><br>
1414       <input type="file" name="file3" size="50"><br>
1415       <input type="submit" value="Send">
1416     </form>
1417
1418 And in the controller:
1419
1420     sub upload : Local {
1421         my ($self, $c) = @_;
1422
1423         if ( $c->request->parameters->{form_submit} eq 'yes' ) {
1424
1425             for my $field ( $c->req->upload ) {
1426
1427                 my $upload   = $c->req->upload($field);
1428                 my $filename = $upload->filename;
1429                 my $target   = "/tmp/upload/$filename";
1430
1431                 unless ( $upload->link_to($target) || $upload->copy_to($target) ) {
1432                     die( "Failed to copy '$filename' to '$target': $!" );
1433                 }
1434             }
1435         }
1436
1437         $c->stash->{template} = 'file_upload.html';
1438     }
1439
1440 C<for my $field ($c-E<gt>req->upload)> loops automatically over all file
1441 input fields and gets input names. After that is basic file saving code,
1442 just like in single file upload.
1443
1444 Notice: C<die>ing might not be what you want to do, when an error
1445 occurs, but it works as an example. A better idea would be to store
1446 error C<$!> in $c->stash->{error} and show a custom error template
1447 displaying this message.
1448
1449 For more information about uploads and usable methods look at
1450 L<Catalyst::Request::Upload> and L<Catalyst::Request>.
1451
1452 =head2 Forwarding with arguments
1453
1454 Sometimes you want to pass along arguments when forwarding to another
1455 action. As of version 5.30, arguments can be passed in the call to
1456 C<forward>; in earlier versions, you can manually set the arguments in
1457 the Catalyst Request object:
1458
1459   # version 5.30 and later:
1460   $c->forward('/wherever', [qw/arg1 arg2 arg3/]);
1461
1462   # pre-5.30
1463   $c->req->args([qw/arg1 arg2 arg3/]);
1464   $c->forward('/wherever');
1465
1466 (See the L<Catalyst::Manual::Intro> Flow_Control section for more 
1467 information on passing arguments via C<forward>.)
1468
1469
1470 =head1 Deployment
1471
1472 The recipes below describe aspects of the deployment process,
1473 including web server engines and tips to improve application efficiency.
1474
1475 =head2 mod_perl Deployment
1476
1477 mod_perl is the best solution for many applications, but we'll list some pros
1478 and cons so you can decide for yourself.  The other production deployment
1479 option is FastCGI, for which see below.
1480
1481 =head3 Pros
1482
1483 =head4 Speed
1484
1485 mod_perl is very fast and your app will benefit from being loaded in memory
1486 within each Apache process.
1487
1488 =head4 Shared memory for multiple apps
1489
1490 If you need to run several Catalyst apps on the same server, mod_perl will
1491 share the memory for common modules.
1492
1493 =head3 Cons
1494
1495 =head4 Memory usage
1496
1497 Since your application is fully loaded in memory, every Apache process will
1498 be rather large.  This means a large Apache process will be tied up while
1499 serving static files, large files, or dealing with slow clients.  For this
1500 reason, it is best to run a two-tiered web architecture with a lightweight
1501 frontend server passing dynamic requests to a large backend mod_perl
1502 server.
1503
1504 =head4 Reloading
1505
1506 Any changes made to the core code of your app require a full Apache restart.
1507 Catalyst does not support Apache::Reload or StatINC.  This is another good
1508 reason to run a frontend web server where you can set up an
1509 C<ErrorDocument 502> page to report that your app is down for maintenance.
1510
1511 =head4 Cannot run multiple versions of the same app
1512
1513 It is not possible to run two different versions of the same application in
1514 the same Apache instance because the namespaces will collide.
1515
1516 =head4 Setup
1517
1518 Now that we have that out of the way, let's talk about setting up mod_perl
1519 to run a Catalyst app.
1520
1521 =head4 1. Install Catalyst::Engine::Apache
1522
1523 You should install the latest versions of both Catalyst and 
1524 Catalyst::Engine::Apache.  The Apache engines were separated from the
1525 Catalyst core in version 5.50 to allow for updates to the engine without
1526 requiring a new Catalyst release.
1527
1528 =head4 2. Install Apache with mod_perl
1529
1530 Both Apache 1.3 and Apache 2 are supported, although Apache 2 is highly
1531 recommended.  With Apache 2, make sure you are using the prefork MPM and not
1532 the worker MPM.  The reason for this is that many Perl modules are not
1533 thread-safe and may have problems running within the threaded worker
1534 environment.  Catalyst is thread-safe however, so if you know what you're
1535 doing, you may be able to run using worker.
1536
1537 In Debian, the following commands should get you going.
1538
1539     apt-get install apache2-mpm-prefork
1540     apt-get install libapache2-mod-perl2
1541
1542 =head4 3. Configure your application
1543
1544 Every Catalyst application will automagically become a mod_perl handler
1545 when run within mod_perl.  This makes the configuration extremely easy.
1546 Here is a basic Apache 2 configuration.
1547
1548     PerlSwitches -I/var/www/MyApp/lib
1549     PerlModule MyApp
1550     
1551     <Location />
1552         SetHandler          modperl
1553         PerlResponseHandler MyApp
1554     </Location>
1555
1556 The most important line here is C<PerlModule MyApp>.  This causes mod_perl
1557 to preload your entire application into shared memory, including all of your
1558 controller, model, and view classes and configuration.  If you have -Debug
1559 mode enabled, you will see the startup output scroll by when you first
1560 start Apache.
1561
1562 For an example Apache 1.3 configuration, please see the documentation for
1563 L<Catalyst::Engine::Apache::MP13>.
1564
1565 =head3 Test It
1566
1567 That's it, your app is now a full-fledged mod_perl application!  Try it out
1568 by going to http://your.server.com/.
1569
1570 =head3 Other Options
1571
1572 =head4 Non-root location
1573
1574 You may not always want to run your app at the root of your server or virtual
1575 host.  In this case, it's a simple change to run at any non-root location
1576 of your choice.
1577
1578     <Location /myapp>
1579         SetHandler          modperl
1580         PerlResponseHandler MyApp
1581     </Location>
1582     
1583 When running this way, it is best to make use of the C<uri_for> method in
1584 Catalyst for constructing correct links.
1585
1586 =head4 Static file handling
1587
1588 Static files can be served directly by Apache for a performance boost.
1589
1590     DocumentRoot /var/www/MyApp/root
1591     <Location /static>
1592         SetHandler default-handler
1593     </Location>
1594     
1595 This will let all files within root/static be handled directly by Apache.  In
1596 a two-tiered setup, the frontend server should handle static files.
1597 The configuration to do this on the frontend will vary.
1598
1599 The same is accomplished in lighttpd with the following snippet:
1600
1601    $HTTP["url"] !~ "^/(?:img/|static/|css/|favicon.ico$)" {
1602          fastcgi.server = (
1603              "" => (
1604                  "MyApp" => (
1605                      "socket"       => "/tmp/myapp.socket",
1606                      "check-local"  => "disable",
1607                  )
1608              )
1609          )
1610     }
1611
1612 Which serves everything in the img, static, css directories
1613 statically, as well as the favicon file.
1614
1615 Note the path of the application needs to be stated explicitly in the
1616 web server configuration for both these recipes.
1617
1618 =head2 Catalyst on shared hosting
1619
1620 So, you want to put your Catalyst app out there for the whole world to
1621 see, but you don't want to break the bank. There is an answer - if you
1622 can get shared hosting with FastCGI and a shell, you can install your
1623 Catalyst app in a local directory on your shared host. First, run
1624
1625     perl -MCPAN -e shell
1626
1627 and go through the standard CPAN configuration process. Then exit out
1628 without installing anything. Next, open your .bashrc and add
1629
1630     export PATH=$HOME/local/bin:$HOME/local/script:$PATH
1631     perlversion=`perl -v | grep 'built for' | awk '{print $4}' | sed -e 's/v//;'`
1632     export PERL5LIB=$HOME/local/share/perl/$perlversion:$HOME/local/lib/perl/$perlversion:$HOME/local/lib:$PERL5LIB
1633
1634 and log out, then back in again (or run C<". .bashrc"> if you
1635 prefer). Finally, edit C<.cpan/CPAN/MyConfig.pm> and add
1636
1637     'make_install_arg' => qq[SITEPREFIX=$ENV{HOME}/local],
1638     'makepl_arg' => qq[INSTALLDIRS=site install_base=$ENV{HOME}/local],
1639
1640 Now you can install the modules you need using CPAN as normal; they
1641 will be installed into your local directory, and perl will pick them
1642 up. Finally, change directory into the root of your virtual host and
1643 symlink your application's script directory in:
1644
1645     cd path/to/mydomain.com
1646     ln -s ~/lib/MyApp/script script
1647
1648 And add the following lines to your .htaccess file (assuming the server
1649 is setup to handle .pl as fcgi - you may need to rename the script to
1650 myapp_fastcgi.fcgi and/or use a SetHandler directive):
1651
1652   RewriteEngine On
1653   RewriteCond %{REQUEST_URI} !^/?script/myapp_fastcgi.pl
1654   RewriteRule ^(.*)$ script/myapp_fastcgi.pl/$1 [PT,L]
1655
1656 Now C<http://mydomain.com/> should now Just Work. Congratulations, now
1657 you can tell your friends about your new website (or in our case, tell
1658 the client it's time to pay the invoice :) )
1659
1660 =head2 FastCGI Deployment
1661
1662 FastCGI is a high-performance extension to CGI. It is suitable
1663 for production environments.
1664
1665 =head3 Pros
1666
1667 =head4 Speed
1668
1669 FastCGI performs equally as well as mod_perl.  Don't let the 'CGI' fool you;
1670 your app runs as multiple persistent processes ready to receive connections
1671 from the web server.
1672
1673 =head4 App Server
1674
1675 When using external FastCGI servers, your application runs as a standalone
1676 application server.  It may be restarted independently from the web server.
1677 This allows for a more robust environment and faster reload times when
1678 pushing new app changes.  The frontend server can even be configured to
1679 display a friendly "down for maintenance" page while the application is
1680 restarting.
1681
1682 =head4 Load-balancing
1683
1684 You can launch your application on multiple backend servers and allow the
1685 frontend web server to load-balance between all of them.  And of course, if
1686 one goes down, your app continues to run fine.
1687
1688 =head4 Multiple versions of the same app
1689
1690 Each FastCGI application is a separate process, so you can run different
1691 versions of the same app on a single server.
1692
1693 =head4 Can run with threaded Apache
1694
1695 Since your app is not running inside of Apache, the faster mpm_worker module
1696 can be used without worrying about the thread safety of your application.
1697
1698 =head3 Cons
1699
1700 =head4 More complex environment
1701
1702 With FastCGI, there are more things to monitor and more processes running
1703 than when using mod_perl.
1704
1705 =head3 Setup
1706
1707 =head4 1. Install Apache with mod_fastcgi
1708
1709 mod_fastcgi for Apache is a third party module, and can be found at
1710 L<http://www.fastcgi.com/>.  It is also packaged in many distributions,
1711 for example, libapache2-mod-fastcgi in Debian.
1712
1713 =head4 2. Configure your application
1714
1715     # Serve static content directly
1716     DocumentRoot  /var/www/MyApp/root
1717     Alias /static /var/www/MyApp/root/static
1718
1719     FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -processes 3
1720     Alias /myapp/ /var/www/MyApp/script/myapp_fastcgi.pl/
1721     
1722     # Or, run at the root
1723     Alias / /var/www/MyApp/script/myapp_fastcgi.pl/
1724     
1725 The above commands will launch 3 app processes and make the app available at
1726 /myapp/
1727
1728 =head3 Standalone server mode
1729
1730 While not as easy as the previous method, running your app as an external
1731 server gives you much more flexibility.
1732
1733 First, launch your app as a standalone server listening on a socket.
1734
1735     script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5 -p /tmp/myapp.pid -d
1736     
1737 You can also listen on a TCP port if your web server is not on the same
1738 machine.
1739
1740     script/myapp_fastcgi.pl -l :8080 -n 5 -p /tmp/myapp.pid -d
1741     
1742 You will probably want to write an init script to handle starting/stopping
1743 of the app using the pid file.
1744
1745 Now, we simply configure Apache to connect to the running server.
1746
1747     # 502 is a Bad Gateway error, and will occur if the backend server is down
1748     # This allows us to display a friendly static page that says "down for
1749     # maintenance"
1750     Alias /_errors /var/www/MyApp/root/error-pages
1751     ErrorDocument 502 /_errors/502.html
1752
1753     FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
1754     Alias /myapp/ /tmp/myapp.fcgi/
1755     
1756     # Or, run at the root
1757     Alias / /tmp/myapp.fcgi/
1758     
1759 =head3 More Info
1760
1761 L<Catalyst::Engine::FastCGI>.
1762
1763 =head2 Development server deployment
1764
1765 The development server is a mini web server written in perl.  If you
1766 expect a low number of hits or you don't need mod_perl/FastCGI speed,
1767 you could use the development server as the application server with a
1768 lightweight proxy web server at the front.  However, consider using
1769 L<Catalyst::Engine::HTTP::Prefork> for this kind of deployment instead, since
1770 it can better handle multiple concurrent requests without forking, or can
1771 prefork a set number of servers for improved performance.
1772
1773 =head3 Pros
1774
1775 As this is an application server setup, the pros are the same as
1776 FastCGI (with the exception of speed).
1777 It is also:
1778
1779 =head4 Simple
1780
1781 The development server is what you create your code on, so if it works
1782 here, it should work in production!
1783
1784 =head3 Cons
1785
1786 =head4 Speed
1787
1788 Not as fast as mod_perl or FastCGI. Needs to fork for each request
1789 that comes in - make sure static files are served by the web server to
1790 save forking.
1791
1792 =head3 Setup
1793
1794 =head4 Start up the development server
1795
1796    script/myapp_server.pl -p 8080 -k  -f -pidfile=/tmp/myapp.pid
1797
1798 You will probably want to write an init script to handle stop/starting
1799 the app using the pid file.
1800
1801 =head4 Configuring Apache
1802
1803 Make sure mod_proxy is enabled and add:
1804
1805     # Serve static content directly
1806     DocumentRoot /var/www/MyApp/root
1807     Alias /static /var/www/MyApp/root/static
1808
1809     ProxyRequests Off
1810     <Proxy *>
1811         Order deny,allow
1812         Allow from all
1813     </Proxy>
1814
1815     # Need to specifically stop these paths from being passed to proxy
1816     ProxyPass /static !
1817     ProxyPass /favicon.ico !
1818
1819     ProxyPass / http://localhost:8080/
1820     ProxyPassReverse / http://localhost:8080/
1821
1822     # This is optional if you'd like to show a custom error page 
1823     # if the proxy is not available
1824     ErrorDocument 502 /static/error_pages/http502.html
1825
1826 You can wrap the above within a VirtualHost container if you want
1827 different apps served on the same host.
1828
1829 =head2 Quick deployment: Building PAR Packages
1830
1831 You have an application running on your development box, but then you
1832 have to quickly move it to another one for
1833 demonstration/deployment/testing...
1834
1835 PAR packages can save you from a lot of trouble here. They are usual Zip
1836 files that contain a blib tree; you can even include all prereqs and a
1837 perl interpreter by setting a few flags!
1838
1839 =head3 Follow these few points to try it out!
1840
1841 1. Install Catalyst and PAR 0.89 (or later)
1842
1843     % perl -MCPAN -e 'install Catalyst'
1844     ...
1845     % perl -MCPAN -e 'install PAR'
1846     ...
1847
1848 2. Create a application
1849
1850     % catalyst.pl MyApp
1851     ...
1852     % cd MyApp
1853
1854 Recent versions of Catalyst (5.62 and up) include
1855 L<Module::Install::Catalyst>, which simplifies the process greatly.  From the shell in your application directory:
1856
1857     % perl Makefile.PL
1858     % make catalyst_par
1859
1860 Congratulations! Your package "myapp.par" is ready, the following
1861 steps are just optional.
1862
1863 3. Test your PAR package with "parl" (no typo)
1864
1865     % parl myapp.par
1866     Usage:
1867         [parl] myapp[.par] [script] [arguments]
1868
1869       Examples:
1870         parl myapp.par myapp_server.pl -r
1871         myapp myapp_cgi.pl
1872
1873       Available scripts:
1874         myapp_cgi.pl
1875         myapp_create.pl
1876         myapp_fastcgi.pl
1877         myapp_server.pl
1878         myapp_test.pl
1879
1880     % parl myapp.par myapp_server.pl
1881     You can connect to your server at http://localhost:3000
1882
1883 Yes, this nifty little starter application gets automatically included.
1884 You can also use "catalyst_par_script('myapp_server.pl')" to set a
1885 default script to execute.
1886
1887 6. Want to create a binary that includes the Perl interpreter?
1888
1889     % pp -o myapp myapp.par
1890     % ./myapp myapp_server.pl
1891     You can connect to your server at http://localhost:3000
1892
1893 =head2 Serving static content
1894
1895 Serving static content in Catalyst used to be somewhat tricky; the use
1896 of L<Catalyst::Plugin::Static::Simple> makes everything much easier.
1897 This plugin will automatically serve your static content during development,
1898 but allows you to easily switch to Apache (or other server) in a
1899 production environment.
1900
1901 =head3 Introduction to Static::Simple
1902
1903 Static::Simple is a plugin that will help to serve static content for your
1904 application. By default, it will serve most types of files, excluding some
1905 standard Template Toolkit extensions, out of your B<root> file directory. All
1906 files are served by path, so if B<images/me.jpg> is requested, then
1907 B<root/images/me.jpg> is found and served.
1908
1909 =head3 Usage
1910
1911 Using the plugin is as simple as setting your use line in MyApp.pm to include:
1912
1913  use Catalyst qw/Static::Simple/;
1914
1915 and already files will be served.
1916
1917 =head3 Configuring
1918
1919 Static content is best served from a single directory within your root
1920 directory. Having many different directories such as C<root/css> and
1921 C<root/images> requires more code to manage, because you must separately
1922 identify each static directory--if you decide to add a C<root/js>
1923 directory, you'll need to change your code to account for it. In
1924 contrast, keeping all static directories as subdirectories of a main
1925 C<root/static> directory makes things much easier to manage. Here's an
1926 example of a typical root directory structure:
1927
1928     root/
1929     root/content.tt
1930     root/controller/stuff.tt
1931     root/header.tt
1932     root/static/
1933     root/static/css/main.css
1934     root/static/images/logo.jpg
1935     root/static/js/code.js
1936
1937
1938 All static content lives under C<root/static>, with everything else being
1939 Template Toolkit files.
1940
1941 =over 4
1942
1943 =item Include Path
1944
1945 You may of course want to change the default locations, and make
1946 Static::Simple look somewhere else, this is as easy as:
1947
1948  MyApp->config->{static}->{include_path} = [
1949   MyApp->config->{root},
1950   '/path/to/my/files' 
1951  ];
1952
1953 When you override include_path, it will not automatically append the
1954 normal root path, so you need to add it yourself if you still want
1955 it. These will be searched in order given, and the first matching file
1956 served.
1957
1958 =item Static directories
1959
1960 If you want to force some directories to be only static, you can set
1961 them using paths relative to the root dir, or regular expressions:
1962
1963  MyApp->config->{static}->{dirs} = [
1964    'static',
1965    qr/^(images|css)/,
1966  ];
1967
1968 =item File extensions
1969
1970 By default, the following extensions are not served (that is, they will
1971 be processed by Catalyst): B<tmpl, tt, tt2, html, xhtml>. This list can
1972 be replaced easily:
1973
1974  MyApp->config->{static}->{ignore_extensions} = [
1975     qw/tmpl tt tt2 html xhtml/ 
1976  ];
1977
1978 =item Ignoring directories
1979
1980 Entire directories can be ignored. If used with include_path,
1981 directories relative to the include_path dirs will also be ignored:
1982
1983  MyApp->config->{static}->{ignore_dirs} = [ qw/tmpl css/ ];
1984
1985 =back
1986
1987 =head3 More information
1988
1989 L<http://search.cpan.org/dist/Catalyst-Plugin-Static-Simple/>
1990
1991 =head3 Serving manually with the Static plugin with HTTP::Daemon (myapp_server.pl)
1992
1993 In some situations you might want to control things more directly,
1994 using L<Catalyst::Plugin::Static>.
1995
1996 In your main application class (MyApp.pm), load the plugin:
1997
1998     use Catalyst qw/-Debug FormValidator Static OtherPlugin/;
1999
2000 You will also need to make sure your end method does I<not> forward
2001 static content to the view, perhaps like this:
2002
2003     sub end : Private {
2004         my ( $self, $c ) = @_;
2005
2006         $c->forward( 'MyApp::View::TT' ) 
2007           unless ( $c->res->body || !$c->stash->{template} );
2008     }
2009
2010 This code will only forward to the view if a template has been
2011 previously defined by a controller and if there is not already data in
2012 C<$c-E<gt>res-E<gt>body>.
2013
2014 Next, create a controller to handle requests for the /static path. Use
2015 the Helper to save time. This command will create a stub controller as
2016 C<lib/MyApp/Controller/Static.pm>.
2017
2018     $ script/myapp_create.pl controller Static
2019
2020 Edit the file and add the following methods:
2021
2022     # serve all files under /static as static files
2023     sub default : Path('/static') {
2024         my ( $self, $c ) = @_;
2025
2026         # Optional, allow the browser to cache the content
2027         $c->res->headers->header( 'Cache-Control' => 'max-age=86400' );
2028
2029         $c->serve_static; # from Catalyst::Plugin::Static
2030     }
2031
2032     # also handle requests for /favicon.ico
2033     sub favicon : Path('/favicon.ico') {
2034         my ( $self, $c ) = @_;
2035
2036         $c->serve_static;
2037     }
2038
2039 You can also define a different icon for the browser to use instead of
2040 favicon.ico by using this in your HTML header:
2041
2042     <link rel="icon" href="/static/myapp.ico" type="image/x-icon" />
2043
2044 =head3 Common problems with the Static plugin
2045
2046 The Static plugin makes use of the C<shared-mime-info> package to
2047 automatically determine MIME types. This package is notoriously
2048 difficult to install, especially on win32 and OS X. For OS X the easiest
2049 path might be to install Fink, then use C<apt-get install
2050 shared-mime-info>. Restart the server, and everything should be fine.
2051
2052 Make sure you are using the latest version (>= 0.16) for best
2053 results. If you are having errors serving CSS files, or if they get
2054 served as text/plain instead of text/css, you may have an outdated
2055 shared-mime-info version. You may also wish to simply use the following
2056 code in your Static controller:
2057
2058     if ($c->req->path =~ /css$/i) {
2059         $c->serve_static( "text/css" );
2060     } else {
2061         $c->serve_static;
2062     }
2063
2064 =head3 Serving Static Files with Apache
2065
2066 When using Apache, you can bypass Catalyst and any Static
2067 plugins/controllers controller by intercepting requests for the
2068 C<root/static> path at the server level. All that is required is to
2069 define a DocumentRoot and add a separate Location block for your static
2070 content. Here is a complete config for this application under mod_perl
2071 1.x:
2072
2073     <Perl>
2074         use lib qw(/var/www/MyApp/lib);
2075     </Perl>
2076     PerlModule MyApp
2077
2078     <VirtualHost *>
2079         ServerName myapp.example.com
2080         DocumentRoot /var/www/MyApp/root
2081         <Location />
2082             SetHandler perl-script
2083             PerlHandler MyApp
2084         </Location>
2085         <LocationMatch "/(static|favicon.ico)">
2086             SetHandler default-handler
2087         </LocationMatch>
2088     </VirtualHost>
2089
2090 And here's a simpler example that'll get you started:
2091
2092     Alias /static/ "/my/static/files/"
2093     <Location "/static">
2094         SetHandler none
2095     </Location>
2096
2097 =head2 Caching
2098
2099 Catalyst makes it easy to employ several different types of caching to
2100 speed up your applications.
2101
2102 =head3 Cache Plugins
2103
2104 There are three wrapper plugins around common CPAN cache modules:
2105 Cache::FastMmap, Cache::FileCache, and Cache::Memcached.  These can be
2106 used to cache the result of slow operations.
2107
2108 The Catalyst Advent Calendar uses the FileCache plugin to cache the
2109 rendered XHTML version of the source POD document.  This is an ideal
2110 application for a cache because the source document changes
2111 infrequently but may be viewed many times.
2112
2113     use Catalyst qw/Cache::FileCache/;
2114     
2115     ...
2116     
2117     use File::stat;
2118     sub render_pod : Local {
2119         my ( self, $c ) = @_;
2120         
2121         # the cache is keyed on the filename and the modification time
2122         # to check for updates to the file.
2123         my $file  = $c->path_to( 'root', '2005', '11.pod' );
2124         my $mtime = ( stat $file )->mtime;
2125         
2126         my $cached_pod = $c->cache->get("$file $mtime");
2127         if ( !$cached_pod ) {
2128             $cached_pod = do_slow_pod_rendering();
2129             # cache the result for 12 hours
2130             $c->cache->set( "$file $mtime", $cached_pod, '12h' );
2131         }
2132         $c->stash->{pod} = $cached_pod;
2133     }
2134     
2135 We could actually cache the result forever, but using a value such as 12 hours
2136 allows old entries to be automatically expired when they are no longer needed.
2137
2138 =head3 Page Caching
2139
2140 Another method of caching is to cache the entire HTML page.  While this is
2141 traditionally handled by a front-end proxy server like Squid, the Catalyst
2142 PageCache plugin makes it trivial to cache the entire output from
2143 frequently-used or slow actions.
2144
2145 Many sites have a busy content-filled front page that might look something
2146 like this.  It probably takes a while to process, and will do the exact same
2147 thing for every single user who views the page.
2148
2149     sub front_page : Path('/') {
2150         my ( $self, $c ) = @_;
2151         
2152         $c->forward( 'get_news_articles' );
2153         $c->forward( 'build_lots_of_boxes' );
2154         $c->forward( 'more_slow_stuff' );
2155         
2156         $c->stash->{template} = 'index.tt';
2157     }
2158
2159 We can add the PageCache plugin to speed things up.
2160
2161     use Catalyst qw/Cache::FileCache PageCache/;
2162     
2163     sub front_page : Path ('/') {
2164         my ( $self, $c ) = @_;
2165         
2166         $c->cache_page( 300 );
2167         
2168         # same processing as above
2169     }
2170     
2171 Now the entire output of the front page, from <html> to </html>, will be
2172 cached for 5 minutes.  After 5 minutes, the next request will rebuild the
2173 page and it will be re-cached.
2174
2175 Note that the page cache is keyed on the page URI plus all parameters, so
2176 requests for / and /?foo=bar will result in different cache items.  Also,
2177 only GET requests will be cached by the plugin.
2178
2179 You can even get that front-end Squid proxy to help out by enabling HTTP
2180 headers for the cached page.
2181
2182     MyApp->config->{page_cache}->{set_http_headers} = 1;
2183     
2184 This would now set the following headers so proxies and browsers may cache
2185 the content themselves.
2186
2187     Cache-Control: max-age=($expire_time - time)
2188     Expires: $expire_time
2189     Last-Modified: $cache_created_time
2190     
2191 =head3 Template Caching
2192
2193 Template Toolkit provides support for caching compiled versions of your
2194 templates.  To enable this in Catalyst, use the following configuration.
2195 TT will cache compiled templates keyed on the file mtime, so changes will
2196 still be automatically detected.
2197
2198     package MyApp::View::TT;
2199     
2200     use strict;
2201     use warnings;
2202     use base 'Catalyst::View::TT';
2203     
2204     __PACKAGE__->config(
2205         COMPILE_DIR => '/tmp/template_cache',
2206     );
2207     
2208     1;
2209     
2210 =head3 More Info
2211
2212 See the documentation for each cache plugin for more details and other
2213 available configuration options.
2214
2215 L<Catalyst::Plugin::Cache::FastMmap>
2216 L<Catalyst::Plugin::Cache::FileCache>
2217 L<Catalyst::Plugin::Cache::Memcached>
2218 L<Catalyst::Plugin::PageCache>
2219 L<http://search.cpan.org/dist/Template-Toolkit/lib/Template/Manual/Config.pod#Caching_and_Compiling_Options>
2220
2221 =head1 Testing
2222
2223 Testing is an integral part of the web application development
2224 process.  Tests make multi developer teams easier to coordinate, and
2225 they help ensure that there are no nasty surprises after upgrades or
2226 alterations.
2227
2228 =head2 Testing
2229
2230 Catalyst provides a convenient way of testing your application during 
2231 development and before deployment in a real environment.
2232
2233 C<Catalyst::Test> makes it possible to run the same tests both locally 
2234 (without an external daemon) and against a remote server via HTTP.
2235
2236 =head3 Tests
2237
2238 Let's examine a skeleton application's C<t/> directory:
2239
2240     mundus:~/MyApp chansen$ ls -l t/
2241     total 24
2242     -rw-r--r--  1 chansen  chansen   95 18 Dec 20:50 01app.t
2243     -rw-r--r--  1 chansen  chansen  190 18 Dec 20:50 02pod.t
2244     -rw-r--r--  1 chansen  chansen  213 18 Dec 20:50 03podcoverage.t
2245
2246 =over 4
2247
2248 =item C<01app.t>
2249
2250 Verifies that the application loads, compiles, and returns a successful
2251 response.
2252
2253 =item C<02pod.t>
2254
2255 Verifies that all POD is free from errors. Only executed if the C<TEST_POD> 
2256 environment variable is true.
2257
2258 =item C<03podcoverage.t>
2259
2260 Verifies that all methods/functions have POD coverage. Only executed if the
2261 C<TEST_POD> environment variable is true.
2262
2263 =back
2264
2265 =head3 Creating tests
2266
2267     mundus:~/MyApp chansen$ cat t/01app.t | perl -ne 'printf( "%2d  %s", $., $_ )'
2268     1  use Test::More tests => 2;
2269     2  use_ok( Catalyst::Test, 'MyApp' );
2270     3
2271     4  ok( request('/')->is_success );
2272
2273 The first line declares how many tests we are going to run, in this case
2274 two. The second line tests and loads our application in test mode. The
2275 fourth line verifies that our application returns a successful response.
2276
2277 C<Catalyst::Test> exports two functions, C<request> and C<get>. Each can
2278 take three different arguments:
2279
2280 =over 4
2281
2282 =item A string which is a relative or absolute URI.
2283
2284     request('/my/path');
2285     request('http://www.host.com/my/path');
2286
2287 =item An instance of C<URI>.
2288
2289     request( URI->new('http://www.host.com/my/path') );
2290
2291 =item An instance of C<HTTP::Request>.
2292
2293     request( HTTP::Request->new( GET => 'http://www.host.com/my/path') );
2294
2295 =back
2296
2297 C<request> returns an instance of C<HTTP::Response> and C<get> returns the 
2298 content (body) of the response.
2299
2300 =head3 Running tests locally
2301
2302     mundus:~/MyApp chansen$ CATALYST_DEBUG=0 TEST_POD=1 prove --lib lib/ t/
2303     t/01app............ok                                                        
2304     t/02pod............ok                                                        
2305     t/03podcoverage....ok                                                        
2306     All tests successful.
2307     Files=3, Tests=4,  2 wallclock secs ( 1.60 cusr +  0.36 csys =  1.96 CPU)
2308  
2309 C<CATALYST_DEBUG=0> ensures that debugging is off; if it's enabled you
2310 will see debug logs between tests.
2311
2312 C<TEST_POD=1> enables POD checking and coverage.
2313
2314 C<prove> A command-line tool that makes it easy to run tests. You can
2315 find out more about it from the links below.
2316
2317 =head3 Running tests remotely
2318
2319     mundus:~/MyApp chansen$ CATALYST_SERVER=http://localhost:3000/ prove --lib lib/ t/01app.t
2320     t/01app....ok                                                                
2321     All tests successful.
2322     Files=1, Tests=2,  0 wallclock secs ( 0.40 cusr +  0.01 csys =  0.41 CPU)
2323
2324 C<CATALYST_SERVER=http://localhost:3000/> is the absolute deployment URI of 
2325 your application. In C<CGI> or C<FastCGI> it should be the host and path 
2326 to the script.
2327
2328 =head3 C<Test::WWW::Mechanize> and Catalyst
2329
2330 Be sure to check out C<Test::WWW::Mechanize::Catalyst>. It makes it easy to
2331 test HTML, forms and links. A short example of usage:
2332
2333     use Test::More tests => 6;
2334     use_ok( Test::WWW::Mechanize::Catalyst, 'MyApp' );
2335
2336     my $mech = Test::WWW::Mechanize::Catalyst->new;
2337     $mech->get_ok("http://localhost/", 'Got index page');
2338     $mech->title_like( qr/^MyApp on Catalyst/, 'Got right index title' );
2339     ok( $mech->find_link( text_regex => qr/^Wiki/i ), 'Found link to Wiki' );
2340     ok( $mech->find_link( text_regex => qr/^Mailing-List/i ), 'Found link to Mailing-List' );
2341     ok( $mech->find_link( text_regex => qr/^IRC channel/i ), 'Found link to IRC channel' );
2342
2343 =head3 Further Reading
2344
2345 =over 4
2346
2347 =item Catalyst::Test
2348
2349 L<http://search.cpan.org/dist/Catalyst/lib/Catalyst/Test.pm>
2350
2351 =item Test::WWW::Mechanize::Catalyst
2352
2353 L<http://search.cpan.org/dist/Test-WWW-Mechanize-Catalyst/lib/Test/WWW/Mechanize/Catalyst.pm>
2354
2355 =item Test::WWW::Mechanize
2356
2357 L<http://search.cpan.org/dist/Test-WWW-Mechanize/Mechanize.pm>
2358
2359 =item WWW::Mechanize
2360
2361 L<http://search.cpan.org/dist/WWW-Mechanize/lib/WWW/Mechanize.pm>
2362
2363 =item LWP::UserAgent
2364
2365 L<http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm>
2366
2367 =item HTML::Form
2368
2369 L<http://search.cpan.org/dist/libwww-perl/lib/HTML/Form.pm>
2370
2371 =item HTTP::Message
2372
2373 L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Message.pm>
2374
2375 =item HTTP::Request
2376
2377 L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Request.pm>
2378
2379 =item HTTP::Request::Common
2380
2381 L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Request/Common.pm>
2382
2383 =item HTTP::Response
2384
2385 L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Response.pm>
2386
2387 =item HTTP::Status
2388
2389 L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Status.pm>
2390
2391 =item URI
2392
2393 L<http://search.cpan.org/dist/URI/URI.pm>
2394
2395 =item Test::More
2396
2397 L<http://search.cpan.org/dist/Test-Simple/lib/Test/More.pm>
2398
2399 =item Test::Pod
2400
2401 L<http://search.cpan.org/dist/Test-Pod/Pod.pm>
2402
2403 =item Test::Pod::Coverage
2404
2405 L<http://search.cpan.org/dist/Test-Pod-Coverage/Coverage.pm>
2406
2407 =item prove (Test::Harness)
2408
2409 L<http://search.cpan.org/dist/Test-Harness/bin/prove>
2410
2411 =back
2412
2413 =head3 More Information
2414
2415 L<http://search.cpan.org/perldoc?Catalyst::Plugin::Authorization::Roles>
2416 L<http://search.cpan.org/perldoc?Catalyst::Plugin::Authorization::ACL>
2417
2418 =head1 AUTHORS
2419
2420 Sebastian Riedel C<sri@oook.de>
2421
2422 Danijel Milicevic C<me@danijel.de>
2423
2424 Viljo Marrandi C<vilts@yahoo.com>  
2425
2426 Marcus Ramberg C<mramberg@cpan.org>
2427
2428 Jesse Sheidlower C<jester@panix.com>
2429
2430 Andy Grundman C<andy@hybridized.org> 
2431
2432 Chisel Wright C<pause@herlpacker.co.uk>
2433
2434 Will Hawes C<info@whawes.co.uk>
2435
2436 Gavin Henry C<ghenry@perl.me.uk>
2437
2438 Kieren Diment C<kd@totaldatasolution.com>
2439
2440 =head1 COPYRIGHT
2441
2442 This document is free, you can redistribute it and/or modify it
2443 under the same terms as Perl itself.
2444