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