Almost there, will finish adding the rest of the components tomorrow. All plugins...
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Tutorial.pod
CommitLineData
83cea649 1=head1 NAME
2
3Catalyst::Manual::Tutorial - Getting started with Catalyst
4
5=head1 DESCRIPTION
6
7This document aims to get you up and running with Catalyst.
8
83cea649 9=head2 Installation
10
61b1e958 11The first step is to install Catalyst, and the simplest way to do this
12is to install the Catalyst bundle from CPAN:
83cea649 13
d538823f 14 $ perl -MCPAN -e 'install Task::Catalyst'
83cea649 15
61b1e958 16This will retrieve Catalyst and a number of useful extensions and
17install them for you.
83cea649 18
19
20=head2 Setting up your application
21
61b1e958 22Catalyst includes a helper script, C<catalyst.pl>, that will set up a
23skeleton application for you:
83cea649 24
387e4c50 25 $ catalyst MyApp
26
27 created "MyApp"
28 created "MyApp/script"
29 created "MyApp/lib"
30 created "MyApp/root"
31 created "MyApp/root/static"
32 created "MyApp/root/static/images"
33 created "MyApp/t"
34 created "MyApp/t/Model"
35 created "MyApp/t/View"
36 created "MyApp/t/Controller"
37 created "MyApp/lib/MyApp"
38 created "MyApp/lib/MyApp/Model"
39 created "MyApp/lib/MyApp/View"
40 created "MyApp/lib/MyApp/Controller"
41 created "MyApp/lib/MyApp.pm"
42 created "MyApp/Build.PL"
43 created "MyApp/Makefile.PL"
44 created "MyApp/README"
45 created "MyApp/Changes"
46 created "MyApp/t/01app.t"
47 created "MyApp/t/02pod.t"
48 created "MyApp/t/03podcoverage.t"
49 created "MyApp/root/static/images/catalyst_logo.png"
50 created "MyApp/root/static/images/btn_120x50_built.png"
51 created "MyApp/root/static/images/btn_120x50_built_shadow.png"
52 created "MyApp/root/static/images/btn_120x50_powered.png"
53 created "MyApp/root/static/images/btn_120x50_powered_shadow.png"
54 created "MyApp/root/static/images/btn_88x31_built.png"
55 created "MyApp/root/static/images/btn_88x31_built_shadow.png"
56 created "MyApp/root/static/images/btn_88x31_powered.png"
57 created "MyApp/root/static/images/btn_88x31_powered_shadow.png"
58 created "MyApp/root/favicon.ico"
59 created "MyApp/script/myapp_cgi.pl"
60 created "MyApp/script/myapp_fastcgi.pl"
61 created "MyApp/script/myapp_server.pl"
62 created "MyApp/script/myapp_test.pl"
63 created "MyApp/script/myapp_create.pl"
83cea649 64
61b1e958 65This creates the directory structure shown, populated with skeleton
66files.
83cea649 67
83cea649 68=head2 Testing out the sample application
69
70You can test out your new application by running the server script that
07e73f82 71Catalyst provides:
83cea649 72
387e4c50 73 $ cd MyApp
74 $ script/myapp_server.pl
b33ed88c 75
b460ad78 76 [...] [catalyst] [debug] Debug messages enabled
387e4c50 77 [...] [catalyst] [debug] Loaded plugins:
78 .------------------------------------------------------------------------------.
79 | Catalyst::Plugin::Static::Simple |
80 '------------------------------------------------------------------------------'
b33ed88c 81 [...] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
61b1e958 82 [...] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
387e4c50 83 [...] [catalyst] [debug] Found home "/home/users/me/MyApp"
84 [...] [catalyst] [debug] Loaded Private actions:
85 .--------------------------------------+---------------------------------------.
86 | Private | Class |
87 +--------------------------------------+---------------------------------------+
88 | /default | MyApp |
89 '--------------------------------------+---------------------------------------'
90
91 [...] [catalyst] [info] MyApp powered by Catalyst 5.5
92 You can connect to your server at http://localhost:3000
b33ed88c 93
94(Note that each line logged by Catalyst begins with a timestamp, which has
61b1e958 95been replaced here with "C<...>" so that the text fits onto the lines.)
b460ad78 96
61b1e958 97The server is now waiting for you to make requests of it. Try using
98telnet to manually make a simple GET request of the server (when
99telnet responds with "Escape character is '^]'.", type "GET / HTTP/1.0"
100and hit return twice):
83cea649 101
102 $ telnet localhost 3000
103 Trying 127.0.0.1...
104 Connected to localhost.
105 Escape character is '^]'.
106 GET / HTTP/1.0
107
387e4c50 108 HTTP/1.0 200 OK
109 Date: Mon, 07 Nov 2005 14:57:39 GMT
110 Content-Length: 5525
111 Content-Type: text/html; charset=utf-8
83cea649 112 Status: 200
387e4c50 113 X-Catalyst: 5.5
83cea649 114
387e4c50 115 [...]
83cea649 116 Connection closed by foreign host.
117 $
118
387e4c50 119You can see the full welcome message by visting
120http://localhost:3000/ with your browser.
121
83cea649 122More trace messages will appear in the original terminal window:
123
387e4c50 124 [...] [catalyst] [debug] **********************************
125 [...] [catalyst] [debug] * Request 1 (0.063/s) [2148]
126 [...] [catalyst] [debug] **********************************
127 [...] [catalyst] [debug] Arguments are ""
61b1e958 128 [...] [catalyst] [debug] "GET" request for "" from localhost
387e4c50 129 [...] [catalyst] [info] Request took 0.046883s (21.330/s)
130 .------------------------------------------------------------------+-----------.
131 | Action | Time |
132 +------------------------------------------------------------------+-----------+
133 | /default | 0.000000s |
134 '------------------------------------------------------------------+-----------'
83cea649 135
136The server will continue running until you interrupt it.
137
138The application can also be tested from the command line using the generated
387e4c50 139helper script, C<script/myapp_test.pl>.
83cea649 140
8d47005f 141=head2 Getting started
83cea649 142
8d47005f 143So you picked Catalyst. Good choice. I assume you've installed it as
144well. For this tutorial you will also need the following modules:
83cea649 145
8d47005f 146L<Catalyst::Plugin::Session>
83cea649 147
8d47005f 148L<Catalyst::Plugin::Session::Store::File>
83cea649 149
8d47005f 150L<Catalyst::Plugin::Session::State::Cookie>
83cea649 151
8d47005f 152L<Catalyst::Plugin::Authentication>
83cea649 153
8d47005f 154L<Catalyst::Plugin::Authorization::Roles>
83cea649 155
8d47005f 156L<DBD::SQLite>
83cea649 157
8d47005f 158...
159
160To get started all you need to do is type:
161
162B<catalyst.pl tutorial>
163
164This should create a directory called F<tutorial> and fill it with the
165default (standard) Catalyst installation. Change to this directory
166because we will be running all further commands from inside the
167F<tutorial> directory.
168
169If you now run the built-in mini-server with
170B<script/tutorial_server.pl>, it will show some standard debug messages
171in the console screen (more about those in a minute), and then inform
172you that you can now connect to the test server on port 3000. Point your
173browser at localhost:3000 to see the built-in catalyst welcome screen.
174
175The other important thing catalyst.pl did was create your root
176controller. This file is a standard perl module like all the other
177controllers that you might add to your application. It lives in the
178F<lib/> directory, and will have the same name as you supplied to the
179command above, in our case it is F<tutorial.pm>. Alongside this file is
180a directory of the same name, which is the top level namespace for the
181entire application. Thus every other module we create will be
182"tutorial::something";
183
184The root controller is used to load plugins, to configure the
185application and its plugins, and for generic private actions. We will
186explain more about those later.
187
188=head2 Debugging
189
190The simplest way to debug your Catalyst application is to run it using
191the built-in mini-server as described in L</Getting Started>.
192
193If you want to output any debugging information to the console, then
194call C<< $context->log->debug() >>, passing it a string to output. For
195data structures, use Data::Dumper and call C<<
196$context->log->debug(Dumper($structure)) >>
197
198=head2 Model/View/Controller
199
200The recommended method for code organization in a Catalyst application
201is known as the "Model View Controller" design pattern (also referred to
202"MVC"). The point of the MVC pattern is to divorce the dependencies of
203parts of the application from each other, and give them standard
204interfaces. Following this theory of organization should give your code
205all the benefits of modularity. The main benefits are interchangability
206of parts and reusable code.
207
208Thus you could replace your file data storage with a database or your
209oracle database with a mysql database and not have to change any of your
210controlling or view logic. Or you could later decide to output
211information from your application as RSS instead of HTML just by adding
212a new view module.
213
214=head3 Model
215
216Models deal with the storage of data. For a complex website, you may
217need multiple varied data sources, each will have it's own model class
218that provides an abstracted interface to it. In this tutorial we are
219going to be using a simple database.
220
221=head3 View
222
223Views are used to display information to the user. In a web framework,
224it is generally used to output HTML to the browser. As mentioned
225previously, views can also be used to output RSS or any other kind of
226data format. One easy way to do this with Catalyst is to use a
227templating system such as Template Toolkit. If outputting HTML is all
228you are going to do, then you will probably only need one view.
229
230=head3 Controller
231
232A controller deals with reacting to user choices, and thus controls what
233the application does. Since this is a web framework, Catalyst
234controllers are frequently used to react directly to URLs requested by
235the user. This tutorial will describe the simplest way of using
236controllers, where each path or part of a path is assigned its own
237action (or subroutine). More complex controlling mechanisms will be
238mentioned briefly, and can be read about in detail in the manual.
239
240
241=head2 Controlling
242
243Now lets write our first bit of application code. First, we would like
244our application to greet our users. We'll assume for now that our users
245will be sent to the I<users/greet> URL. To create a controller that
246serves the I<users> namespace, we run the following command in our
247F<tutorial> directory:
248
249B<script/tutorial_create.pl controller Users>
250
251This will create a Users.pm in F<lib/tutorial/Controller>. Open this
252file in an editor and take a look. You will notice there is some
253commented out code which we will ignore for now. To make something
254happen when our URL is visited, we will write a "greet" action which
255looks like this:
256
257 sub greet : Local
258 {
259 my ($self, $context) = @_;
260
261 my $name = $context->req->params->{name};
262 $context->log->debug("Got name: $name\n");
263
264 if(!$name)
265 {
266 $context->stash->{message} = 'Please fill in a name!';
61b1e958 267 }
8d47005f 268 else
269 {
270 $context->stash->{message} = "Hello $name!";
271 }
272 $context->stash->{template} = 'greet.tt';
273 }
274
275Whew! So, what does all this do? Lets take it one step at a time.
276The subroutine declaration gives the action a name. To the right of the
277name there is an attribute type that looks like this: " : Local". That
278defines which URIs will translate to this action. "Local", matches
279exactly one URI: /users/greet. The URI matched by "Local" is composed
280from the namespace minus the tutorial::controller portion, that is
281common to all controllers, and the action name itself. Because it is a
282URI, we use forward slashes instead of double colons. So, in summary,
283when a user requests http://localhost:3000/users/greet" the "greet"
284action defined above in the users controller will be executed.
285
286The second line retrieves the parameters Catalyst gives us when it calls
287our method. The first is the instance of our Users class, and the second
288is commonly called the context. The context is the magical object
289containing any information you need from catalyst, or want to send to
290it. You will see it used frequently in Catalyst applications, and a list
291of all its methods is available in the L<Catalyst> POD.
292
293On the third line we use the ->params method of the $context request
294object to retrieve one of the query parameters, just like in L<CGI>.
295
296On the fourth, we make a debug output of this object on the server console.
297(NB where does ->debug go if we're running under CGI or mod_perl?)
298(NB what is $self good for under CGI/mod_perl/anything?)
299
300Next, we check if the name field contains anything (or is "true"), if it
301isnt, we assign an error message to a "message" field in the stash. The
302stash is yet another method of the context object, it allows us to pass
303data on to other methods we call later, most usefully the View modules.
304
305If the username did contain a value, then we just set our message to
306greet the user by name.
307
308Finally, we set the special "template" variable in the stash to the name
309of the template we want our view to use to display this page.
310(NB doing the param name checking this way will also complain when we
311visit the form for the first time, check for presence of params at all?)
312
313=head2 Viewing
314
315Ok, so reacting and checking the users data is all fine, but how do we
316actually display the page/form in the first place, and our results? As
317previously mentioned, we'll use Template Toolkit for our viewing. To
318create out TT based view, just run the following command:
319
320B<script/tutorial_create.pl view TToolkit TT>
321
322Notice that this time we not only gave it the type of module we wanted
323to create (a view), and a name, but also a third argument, "TT". This is
324a Catalyst helper module, which will make a standard template toolkit
325module for you. And that's all you need to do there.
326
327To use the view, the easiest way is to set up a standard "end" action.
328This a private action which will not be matched to a path like our
329"greet" action, but instead will be called after all other processing is
330done. Only one end action will be called, if there is one in a
331controller, it will be prefered over one in the application module, and
332so on.
333
334Since we're writing a simple application, just add an end action like
335this to F<tutorial.pm>:
336
337 sub end : Private
338 {
339 my ($self, $context) = @_;
340 $context->forward('tutorial::View::TToolkit');
341 }
342
343The first line declares the end sub, and marks it as a Private action.
344(The second and last attribute type we'll be using). The second line
345collects our standard parameters as shown in the controller's greet action.
346
347The third line directs Catalyst to pass processing on to our TToolkit
348view. The forward method, when just passed a class name, calls process
349on that classs. The standard TT view's process method renders the
350template named in the templare variable in the stash, using all the
351other variables in the stash as values to fill it in.
352
353NB: This is such a common way to end you processing that there is a
354plugin which does it for you: L<Catalyst::Plugin::DefaultEnd>.
355
356Template Toolkit also has access to the entire context object via "c",
357for example, using [% c.config.name %] in our template will output
358"tutorial", our project name.
359
360All that remains is to create a simple template called "greet.tt",
361containing a form with a text field called "name", and place it in the
362F<root> directory. By default, templates are searched for here, but we
363can change that, which brings us to..
364
365(NB Can we ask catalyst which paths exist to provide a dynamic list of
366them? (eg greet, age etc .. regexed paths??)
367
368=head2 Configuring
369
370As previously mentioned, the configuration of modules, plugins and so on
371is done in the main application file. This is especially true for bits
372which need to be done before an instance of them is created, for example
373Template Toolkit.
374
375The TT View looks for its templates in the F<root> directory by default.
376Since this is also the directory that static files go in, we'd rather
377have a separate F<templates> directory. To do this, change the config
378call in F<tutorial.pm> like this:
379
380 __PACKAGE__->config( name => 'tutorial',
381 'View::TToolkit' => {
382 'INCLUDE_PATH' => __PACKAGE__->path_to('templates')
383 }
384 );
385
386And move the F<greet.tt> file from F<root> to the F<templates> directory
387(after creating it).
388
389Now we can run our application again by killing (ctrl-c) and restarting
390B<script/tutorial_server.pl>. Try connecting to
391I<localhost:3000/users/greet> with a browser and see what happens. What
392happens if you try to visit I<localhost:3000/users> ?
393
394=head2 Users and Authenticating
395
396One of the many reasons to write dynamic websites instead of just using static
397HTML, is to allow us to produce different content for different users, as well
398 as just restricting access to pages (which we could do with just Apaches
399htpasswd system).
400
401In this tutorial, we will just be using basic authentication, when writing
402a real application, you'll want to use a database or other secure store to
403contain your user data.
404
405To add authentication, all we need to do is add the
406L<Catalyst::Plugin::Authentication> module to our main application file. Then
407we need to pick a storage method (one of the
408L<Catalyst::Plugin::Authentication::Store> modules), and a method of verifying
409the users credentials (one of the
410L<Catalyst::Plugin::Authentication::Credential> modules), so just edit
411F<tutorial.pm> to look like this:
412
413 use Catalyst qw/-Debug Static::Simple Authentication
414 Authentication::Store::Minimal
415 Authentication::Credential::Password/;
416
417To configure, add some users to the config call, for example:
418
419 authentication => { 'users' =>
420 { 'fred' =>
421 { 'password' => 'fred1234',
422 }
423 }
424 }
425
426Generally, setting up configuration data for plugins is done based on the
427type of plugin. Check the documentation of the plugin for exact details. The
428details of this one are in L<Catalyst::Plugin::Authentication::Store::Minimal>.
429
430Since our user data is in the config, we can update it at runtime, and thus
431add users dynamically. (Of course, to keep them permanently we'll need to
432export our data to disk and read it back into the config on startup)
433
434To allow creation of new users we'll add a create action to our Users
435controller.
436
437 sub create : Local
438 {
439 my ($self, $context) = @_;
440 my ($username, $passwd1, $passwd2) = map { $context->req->param($_)}
441 ('username', 'password', 'passwordverify');
442
443 if($username && $passwd1 && $passwd2)
444 {
445 if($context->config->{authentication}{users}{$username})
446 {
447 $context->stash->{message} = 'Sorry that user already exists';
448 $context->stash->{username} = $username;
449 }
450 elsif($passwd1 eq $passwd2)
451 {
452 $context->config->({%{$context->config},
453 ($username => { password => $passwd1}});
454 $context->stash->{message} = 'User created!';
455 }
456 else
457 {
458 $context->stash->{username} = $username;
459 $context->stash->{message} = 'Passwords don't match!';
460 }
461 }
462 $context->stash->{template} = 'usercreate.tt';
463 }
464
465All this is doing is checking that all the appropriate fields are filled,
466the password fields contain the same data, and then adding the user to the
467config hash. All the checks produce a message which can be displayed to
468the user via the View.
469
470So our that users can login, we need a login page:
471
472 sub login : Local
473 {
474 my ($self, $context) = @_;
475 $context->stash->{template} = 'userlogin.tt';
476 if(!$context->login())
477 {
478 $context->stash->{message} = 'Login failed.';
61b1e958 479 }
8d47005f 480 }
481
482Verrrry simple. Since Credential::Password's "login" call extracts the
483username/password data from the query itself (assuming we use a standard
484name for our form fields), we don't have to do anything but call it.
485
486To keep the user logged in, all we need to do is add the Session modules to
487our collection, and the Auth modules will automatically use them;
488
489 use Catalyst qw/-Debug Static::Simple Authentication
490 Authentication::Store::Minimal
491 Authentication::Credential::Password
492 Session Session::Store::File Session::State::Cookie/;
493
494Magic!
495
496=head2 Authorising
497
498Authentication is about verifying users, Authorisation is about allowing
499them to do things. Catalyst currently has two Authorisation modules,
500Roles and ACL. The Roles module allows you to define groups which you
501can assign your users to, and then allow access to areas of your website
502to the groups. The ACL module lets you do more fine grained
503access/restriction by allowing of denying access however you like. (It
504also supports Roles as done by the roles module.)
505
506Adding Roles via the Minimal store we are already using is quite simple,
507we just add a roles key to each user, defining the names of the roles
508they belong to.
509
510 authentication => { 'users' =>
511 { 'fred' =>
512 { 'password' => 'fred1234',
513 'roles' => ['admin']
514 }
515 }
516 }
517
518We need an interface for our admins to administer the roles, i.e. assign
519the users to groups. To restrict access to certain actions, we just need
520to call C<< $context->check_user_roles() >> in each action. So we can
521make a restricted I<localhost:3000/users/groups> page like this:
522
523 sub groups : Local
524 {
525 my ($self, $context) = @_;
526 if($context->check_user_roles('admin'))
527 {
528 # Now we can do things only an admin will see
529 if(my $params = $context->req->params)
530 {
531 my $users = $context->config->{authentication}{users};
532 foreach my $u (keys %$params)
533 {
534 $users->{$u}{roles} = $params->{$u} if($users->{$u});
535 }
536 $context->stash->{message} = 'Updated user roles!';
537 }
538 else
539 {
540 $context->stash->{users} = $context->config->{authentication};
541 }
542 $context->stash->{template} = 'usersgroups.tt';
61b1e958 543 }
8d47005f 544 else
545 {
546 $context->stash->{message} = 'Admins Only!';
547 $context->stash->{template} = 'error.tt';
548 }
549 }
550
551What we are doing here is checking whether the logged in user (used by
552default in the check_user_roles method), is a member of the admin group.
553If it is, then we display the usergroups template, and update the users
554hash as required. Otherwise, we just show the user an error page.
555
556And that's all there is to it.
557
558=head2 Data Storage (Modelling)
559
560Whether we want our users to be able to contribute to our website, or just
561create it from changeable data, we need to store the data somewhere. Generally
562this is done using a database, models can also be other data sources, for
563example another website, or RSS feeds.
564
565If you have or want a database, there are still choices to be made, there are
566several modules about for accessing databases via OO. The best known are
567probably L<Class::DBI> and L<DBIx::Class>. Catalyst supports making models
568using either of these.
569
570For a simple example, we will allow our users to store their favourite
571greeting in our database. Create a table called "greetings" in a database,
572that contains a "user" field and a "greeting" field. The simplest way to
573create a model of your database is to use these helper modules, for example
574with L<DBIx::Class>:
575
576B<script/tutorial_create.pl model UserData DBIC dbi:SQLite:/path/to/mydb.db>
577
578This will cause the DBIx::Class Loader to inspect your database, and create a
579module in the Model::UserData namespace for each table in your database.
580
581Now we need a form for our users to enter/edit their personal greetings in,
582we'll make a I<localhost:3000/users/editgreeting> page:
583
584 sub editgreeting : Local
585 {
586 my ($self, $context) = @_;
587 if($context->req->params->{greeting})
588 {
589 if(!$context->user_exists)
590 {
591 $context->stash->{message} = "You're not logged in!";
592 }
593 else
594 {
595 my $grtable = $context->model('UserData::Greetings');
596 my $record = $grtable->find_or_create(user => $context->user->id);
597 $record->greeting($context->req->params->{greeting};
598 $record->update;
599 $context->stash->{message} = 'Greeting updated';
600 }
601 }
602 $context->stash->{template} = 'usersgreeting.tt';
603 }
83cea649 604
8d47005f 605Using C<< $context->user_exists >> from the Authentication plugin, this checks
606whether the user is logged in already. If they are, if they are, and they have
607entered a new greeting, we use DBIx::Class' C<find_or_create> to fetch or
608create a new record in the greetings table for the user. Once we have the
609record, we change the value of the greeting field, and call C<update> to store
610the new value in the database.
eff5f524 611
8d47005f 612=head2 Engines (Apache and FastCGI)
83cea649 613
8d47005f 614Now that we have the basics together, we can try running our application on a
615"real" server instead of just using the test server that catalyst comes
616with. L<Catalyst::Engine> is the module used to implement various types of
617servers to run it on. The currect popular ones are Apache and FastCGI. To
618force the use of a particular engine we can use the -Engine flag to Catalyst:
b460ad78 619
8d47005f 620 use Catalyst qw/-Engine=Apache/;
b460ad78 621
8d47005f 622or
b460ad78 623
8d47005f 624 use Catalyst qw/-Engine=FastCGI/;
b460ad78 625
8d47005f 626=head3 Apache
b460ad78 627
8d47005f 628Apache also needs configuring, we need to tell it to load your
629application. You can either use Catalyst for your entire website, or
630subsections. Use the Location directive to choose a path to run your
631application under:
b460ad78 632
8d47005f 633 <Location />
634 SetHandler perl-script
635 PerlResponseHandler MyApp
636 </Location>
b460ad78 637
8d47005f 638You will need to install the perl modules of your application into one of
639perls library directories, as listed by B<perl -V>, so that Apache can find
640them. Alternatively you can use the C<PerlSwitches> directive to tell Apache
641where to look:
b460ad78 642
8d47005f 643 PerlSwitches -I/path/to/MyApp/
b460ad78 644
8d47005f 645These instructions are for using Apache2 and mod_perl 2.0. If you are using
646mod_perl 1.3 or 1.99, please refer to either L<Catalyst::Engine::Apache::MP13>
647or L<Catalyst::Engine::Apache2::MP19> for slightly different ways to do it.
b460ad78 648
8d47005f 649If you wish to ensure that Apache pre-loads your application, use the
650PerlModule directive. This means that there will be less of a delay when your
651application is accessed.
b460ad78 652
8d47005f 653 PerlModule MyApp
b460ad78 654
8d47005f 655=head3 FastCGI
b460ad78 656
8d47005f 657These instructions apply to the use of C<mod_fastcgi> under Apache (either 1 or 2 series).
b460ad78 658
8d47005f 659There are 3 ways to attach a program to a URL with C<mod_fastcgi>; we'll examine all of them, and explain how to avoid having the C<myapp_fastcgi.pl> substring in the user-visible URLs.
b460ad78 660
8d47005f 661In all of these examples, we assume that the C<DocumentRoot> is C</var>, that our app is called C<MyApp> and is kept in C</usr>, that you want the users to access the app either from the root of the server-uri-space, or from C</theapp>. We also assume that the general FastCGI settings (C<FastCgiIpcDir>, loading the module) are already correct (they don't depend on Catalyst or your application layout).
83cea649 662
8d47005f 663=head4 static application
664
665In this setup, you tell C<mod_fastcgi> that a particular I<file> is to be run as a FastCGI handler. Put this somewhere in Apache's configuration:
666
667 FastCgiServer /usr/apps/MyApp/script/myapp_fastcgi.pl
668 Alias / /usr/apps/MyApp/script/myapp_fastcgi.pl/
669
670If you want your app under C</theapp>, change the C<Alias> line to:
671
672 Alias /theapp /usr/apps/MyApp/script/myapp_fastcgi.pl
673
674Note the detail of the trailing C</ >: this is a general rule af the C<Alias> directive, both sides must end with C</ >, or both must not; you can't have one with C</ > and the other without, or strange things happen.
675
676=head4 dynamic application
677
678In this setup, you tell C<mod_fastcgi> that certain files are to be treated as FastCGI handlers, in the same way you have to tell C<mod_cgi>. Put this in the configuration:
679
680 FastCgiConfig -autoUpdate
681
682 <Directory /usr/apps/MyApp/script>
683 Options +ExecCGI
684 <Files *_fastcgi.pl>
685 SetHandles fastcgi-script
686 </Files>
687 </Directory>
83cea649 688
8d47005f 689 Alias / /usr/apps/MyApp/script/myapp_fastcgi.pl/
b460ad78 690
8d47005f 691Again, if you want your app under C</theapp>, change the C<Alias> line to:
b460ad78 692
8d47005f 693 Alias /theapp /usr/apps/MyApp/script/myapp_fastcgi.pl
b460ad78 694
8d47005f 695=head4 external server
b460ad78 696
8d47005f 697In this setup, the application is started separately from Apache, and communicates via a socket with C<mod_fastcgi>. This can be useful if you need to have a particular environment for your application (maybe different between applications), or you want to run them on different machines, or under different users for security reasons.
b460ad78 698
8d47005f 699If you want to use a UNIX socket (on the filesystem), put this in Apache's configuration:
b460ad78 700
8d47005f 701 FastCgiExternalServer /tmp/somewhere -socket /tmp/myapp-socket
702 Alias / /tmp/somewhere/
b460ad78 703
8d47005f 704Note that C</tmp> should I<not> exist: it's just a name to connect the two parts.
b460ad78 705
8d47005f 706Again, if you want your app under C</theapp>, change the C<Alias> line to:
b460ad78 707
8d47005f 708 Alias /theapp /tmp/somewhere
709
710Then start your Catalyst application:
711
712 $ cd /usr/apps/MyApp
713 $ ./script/myapp_fastcgi -l /tmp/myapp-socket
714
715If you want to use a TCP socket, simply change the C</tmp> to a C<host:port> pair, both in Apache's configuration and on the command line of your application.
716
717=head2 Upgrading
718
719Upgrading your application to newer Catalyst versions is quite simple. After
720installing the new Catalyst package, just run:
721
722B<catalyst.pl -scripts>
723
724One level above your application directory. This will update the scripts
725directory only, and leave the rest of your app alone, If you wish to make use
726of other parts of Catalyst that have been updated, leave off the B<-scripts>
727argument, this will cause .new files to appear, for each module that has
728either been updated, or is different to the original because you have changed
729it. To find out what these changes are, type:
730
731B<diff MyApp/lib/MyApp/View/TT.pm MyApp/lib/MyApp/View/TT.pm.new>
732
733for each of the changed files. (This is a Unix command, Windows users will
734need to find some equivalent). Copy any changes you need into your original
735file, then remove the .new files. (This makes life less complicated when the
736next upgrade comes around.)
737
738=head1 AUTHOR
739
740Jess Robinson, C<jrobinson@cpan.org>
741Andrew Ford, C<A.Ford@ford-mason.co.uk>
742Marcus Ramberg, C<mramberg@cpan.org>
b460ad78 743
744Please send comments, corrections and suggestions for improvements to
8d47005f 745jrobinson@cpan.org
746
747=head1 TODO
748
749Add template examples.
750
751Many other things..
b460ad78 752
83cea649 753=head1 COPYRIGHT
754
61b1e958 755This program is free software, you can redistribute it and/or modify
756it under the same terms as Perl itself.