s/hope/hopes
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
1 package Catalyst;
2
3 use strict;
4 use base 'Catalyst::Base';
5 use bytes;
6 use UNIVERSAL::require;
7 use Catalyst::Exception;
8 use Catalyst::Log;
9 use Catalyst::Request;
10 use Catalyst::Request::Upload;
11 use Catalyst::Response;
12 use Catalyst::Utils;
13 use NEXT;
14 use Text::ASCIITable;
15 use Path::Class;
16 use Time::HiRes qw/gettimeofday tv_interval/;
17 use URI;
18 use Scalar::Util qw/weaken/;
19
20 __PACKAGE__->mk_accessors(
21     qw/counter depth request response state action namespace/
22 );
23
24 # Laziness++
25 *comp = \&component;
26 *req  = \&request;
27 *res  = \&response;
28
29 # For backwards compatibility
30 *finalize_output = \&finalize_body;
31
32 # For statistics
33 our $COUNT     = 1;
34 our $START     = time;
35 our $RECURSION = 1000;
36 our $DETACH    = "catalyst_detach\n";
37
38 require Module::Pluggable::Fast;
39
40 # Helper script generation
41 our $CATALYST_SCRIPT_GEN = 8;
42
43 __PACKAGE__->mk_classdata($_)
44   for qw/components arguments dispatcher engine log/;
45
46 our $VERSION = '5.49_01';
47
48 sub version { return $Catalyst::VERSION }
49
50 sub import {
51     my ( $class, @arguments ) = @_;
52
53     # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
54     # callers @ISA.
55     return unless $class eq 'Catalyst';
56
57     my $caller = caller(0);
58
59     unless ( $caller->isa('Catalyst') ) {
60         no strict 'refs';
61         push @{"$caller\::ISA"}, $class;
62     }
63
64     $caller->arguments( [@arguments] );
65     $caller->setup_home;
66 }
67
68 =head1 NAME
69
70 Catalyst - The Elegant MVC Web Application Framework
71
72 =head1 SYNOPSIS
73
74     # use the helper to start a new application
75     catalyst.pl MyApp
76     cd MyApp
77
78     # add models, views, controllers
79     script/myapp_create.pl model Something
80     script/myapp_create.pl view Stuff
81     script/myapp_create.pl controller Yada
82
83     # built in testserver
84     script/myapp_server.pl
85
86     # command line interface
87     script/myapp_test.pl /yada
88
89
90     use Catalyst;
91
92     use Catalyst qw/My::Module My::OtherModule/;
93
94     use Catalyst '-Debug';
95
96     use Catalyst qw/-Debug -Engine=CGI/;
97
98     sub default : Private { $_[1]->res->output('Hello') } );
99
100     sub index : Path('/index.html') {
101         my ( $self, $c ) = @_;
102         $c->res->output('Hello');
103         $c->forward('foo');
104     }
105
106     sub product : Regex('^product[_]*(\d*).html$') {
107         my ( $self, $c ) = @_;
108         $c->stash->{template} = 'product.tt';
109         $c->stash->{product} = $c->req->snippets->[0];
110     }
111
112 See also L<Catalyst::Manual::Intro>
113
114 =head1 DESCRIPTION
115
116 The key concept of Catalyst is DRY (Don't Repeat Yourself).
117
118 See L<Catalyst::Manual> for more documentation.
119
120 Catalyst plugins can be loaded by naming them as arguments to the "use Catalyst" statement.
121 Omit the C<Catalyst::Plugin::> prefix from the plugin name,
122 so C<Catalyst::Plugin::My::Module> becomes C<My::Module>.
123
124     use Catalyst 'My::Module';
125
126 Special flags like -Debug and -Engine can also be specified as arguments when
127 Catalyst is loaded:
128
129     use Catalyst qw/-Debug My::Module/;
130
131 The position of plugins and flags in the chain is important, because they are
132 loaded in exactly the order that they appear.
133
134 The following flags are supported:
135
136 =over 4
137
138 =item -Debug
139
140 enables debug output, i.e.:
141
142     use Catalyst '-Debug';
143
144 this is equivalent to:
145
146     use Catalyst;
147     sub debug { 1 }
148
149 =item -Dispatcher
150
151 Force Catalyst to use a specific dispatcher.
152
153 =item -Engine
154
155 Force Catalyst to use a specific engine.
156 Omit the C<Catalyst::Engine::> prefix of the engine name, i.e.:
157
158     use Catalyst '-Engine=CGI';
159
160 =item -Home
161
162 Force Catalyst to use a specific home directory.
163
164 =item -Log
165
166 Specify log level.
167
168 =back
169
170 =head1 METHODS
171
172 =over 4
173
174 =item $c->action
175
176 Accessor for the current action
177
178 =item $c->comp($name)
179
180 =item $c->component($name)
181
182 Get a component object by name.
183
184     $c->comp('MyApp::Model::MyModel')->do_stuff;
185
186 =cut
187
188 sub component {
189     my $c = shift;
190
191     if (@_) {
192
193         my $name = shift;
194
195         my $appclass = ref $c || $c;
196
197         my @names = (
198             $name, "${appclass}::${name}",
199             map { "${appclass}::${_}::${name}" } qw/M V C/
200         );
201
202         foreach my $try (@names) {
203
204             if ( exists $c->components->{$try} ) {
205
206                 return $c->components->{$try};
207             }
208         }
209
210         foreach my $component ( keys %{ $c->components } ) {
211
212             return $c->components->{$component} if $component =~ /$name/i;
213         }
214
215     }
216
217     return sort keys %{ $c->components };
218 }
219
220 =item config
221
222 Returns a hashref containing your applications settings.
223
224 =item debug
225
226 Overload to enable debug messages.
227
228 =cut
229
230 sub debug { 0 }
231
232 =item $c->detach( $command [, \@arguments ] )
233
234 Like C<forward> but doesn't return.
235
236 =cut
237
238 sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
239
240 =item $c->dispatcher
241
242 Contains the dispatcher instance.
243 Stringifies to class.
244
245 =item $c->forward( $command [, \@arguments ] )
246
247 Forward processing to a private action or a method from a class.
248 If you define a class without method it will default to process().
249 also takes an optional arrayref containing arguments to be passed
250 to the new function. $c->req->args will be reset upon returning 
251 from the function.
252
253     $c->forward('/foo');
254     $c->forward('index');
255     $c->forward(qw/MyApp::Model::CDBI::Foo do_stuff/);
256     $c->forward('MyApp::View::TT');
257
258 =cut
259
260 sub forward { my $c = shift; $c->dispatcher->forward( $c, @_ ) }
261
262 =item $c->namespace
263
264 Accessor to the namespace of the current action
265
266 =item $c->path_to(@path)
267
268 Merges C<@path> with $c->config->{home} and returns a L<Path::Class> object.
269
270 For example:
271
272     $c->path_to( 'db', 'sqlite.db' );
273
274 =cut
275
276 sub path_to {
277     my ( $c, @path ) = @_;
278     my $path = dir( $c->config->{home}, @path );
279     if ( -d $path ) { return $path }
280     else { return file( $c->config->{home}, @path ) }
281 }
282
283 =item $c->setup
284
285 Setup.
286
287     $c->setup;
288
289 =cut
290
291 sub setup {
292     my ( $class, @arguments ) = @_;
293
294     unless ( $class->isa('Catalyst') ) {
295
296         Catalyst::Exception->throw(
297             message => qq/'$class' does not inherit from Catalyst/ );
298     }
299
300     if ( $class->arguments ) {
301         @arguments = ( @arguments, @{ $class->arguments } );
302     }
303
304     # Process options
305     my $flags = {};
306
307     foreach (@arguments) {
308
309         if (/^-Debug$/) {
310             $flags->{log} =
311               ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
312         }
313         elsif (/^-(\w+)=?(.*)$/) {
314             $flags->{ lc $1 } = $2;
315         }
316         else {
317             push @{ $flags->{plugins} }, $_;
318         }
319     }
320
321     $class->setup_log( delete $flags->{log} );
322     $class->setup_plugins( delete $flags->{plugins} );
323     $class->setup_dispatcher( delete $flags->{dispatcher} );
324     $class->setup_engine( delete $flags->{engine} );
325     $class->setup_home( delete $flags->{home} );
326
327     for my $flag ( sort keys %{$flags} ) {
328
329         if ( my $code = $class->can( 'setup_' . $flag ) ) {
330             &$code( $class, delete $flags->{$flag} );
331         }
332         else {
333             $class->log->warn(qq/Unknown flag "$flag"/);
334         }
335     }
336
337     $class->log->warn( "You are running an old helper script! "
338           . "Please update your scripts by regenerating the "
339           . "application and copying over the new scripts." )
340       if ( $ENV{CATALYST_SCRIPT_GEN}
341         && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::CATALYST_SCRIPT_GEN ) );
342
343     if ( $class->debug ) {
344
345         my @plugins = ();
346
347         {
348             no strict 'refs';
349             @plugins = grep { /^Catalyst::Plugin/ } @{"$class\::ISA"};
350         }
351
352         if (@plugins) {
353             my $t = Text::ASCIITable->new;
354             $t->setOptions( 'hide_HeadRow',  1 );
355             $t->setOptions( 'hide_HeadLine', 1 );
356             $t->setCols('Class');
357             $t->setColWidth( 'Class', 75, 1 );
358             $t->addRow($_) for @plugins;
359             $class->log->debug( "Loaded plugins:\n" . $t->draw );
360         }
361
362         my $dispatcher = $class->dispatcher;
363         my $engine     = $class->engine;
364         my $home       = $class->config->{home};
365
366         $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
367         $class->log->debug(qq/Loaded engine "$engine"/);
368
369         $home
370           ? ( -d $home )
371           ? $class->log->debug(qq/Found home "$home"/)
372           : $class->log->debug(qq/Home "$home" doesn't exist/)
373           : $class->log->debug(q/Couldn't find home/);
374     }
375
376     # Call plugins setup
377     {
378         no warnings qw/redefine/;
379         local *setup = sub { };
380         $class->setup;
381     }
382
383     # Initialize our data structure
384     $class->components( {} );
385
386     $class->setup_components;
387
388     if ( $class->debug ) {
389         my $t = Text::ASCIITable->new;
390         $t->setOptions( 'hide_HeadRow',  1 );
391         $t->setOptions( 'hide_HeadLine', 1 );
392         $t->setCols('Class');
393         $t->setColWidth( 'Class', 75, 1 );
394         $t->addRow($_) for sort keys %{ $class->components };
395         $class->log->debug( "Loaded components:\n" . $t->draw )
396           if ( @{ $t->{tbl_rows} } );
397     }
398
399     # Add our self to components, since we are also a component
400     $class->components->{$class} = $class;
401
402     $class->setup_actions;
403
404     if ( $class->debug ) {
405         my $name = $class->config->{name} || 'Application';
406         $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
407     }
408     $class->log->_flush() if $class->log->can('_flush');
409 }
410
411 =item $c->uri_for($path,[@args])
412
413 Merges path with $c->request->base for absolute uri's and with
414 $c->request->match for relative uri's, then returns a normalized
415 L<URI> object. If any args are passed, they are added at the end
416 of the path.
417
418 =cut
419
420 sub uri_for {
421     my ( $c, $path, @args ) = @_;
422     my $base     = $c->request->base->clone;
423     my $basepath = $base->path;
424     $basepath =~ s/\/$//;
425     $basepath .= '/';
426     my $match = $c->request->match;
427
428     # massage match, empty if absolute path
429     $match =~ s/^\///;
430     $match .= '/' if $match;
431     $match = '' if $path =~ /^\//;
432     $path =~ s/^\///;
433
434     # join args with '/', or a blank string
435     my $args = ( scalar @args ? '/' . join( '/', @args ) : '' );
436     return URI->new_abs( URI->new_abs( "$path$args", "$basepath$match" ),
437         $base )->canonical;
438 }
439
440 =item $c->error
441
442 =item $c->error($error, ...)
443
444 =item $c->error($arrayref)
445
446 Returns an arrayref containing error messages.
447
448     my @error = @{ $c->error };
449
450 Add a new error.
451
452     $c->error('Something bad happened');
453
454 Clean errors.
455
456     $c->error(0);
457
458 =cut
459
460 sub error {
461     my $c = shift;
462     if ( $_[0] ) {
463         my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
464         push @{ $c->{error} }, @$error;
465     }
466     elsif ( defined $_[0] ) { $c->{error} = undef }
467     return $c->{error} || [];
468 }
469
470 =item $c->engine
471
472 Contains the engine instance.
473 Stringifies to the class.
474
475 =item $c->log
476
477 Contains the logging object.  Unless it is already set Catalyst sets this up with a
478 C<Catalyst::Log> object.  To use your own log class:
479
480     $c->log( MyLogger->new );
481     $c->log->info("now logging with my own logger!");
482
483 Your log class should implement the methods described in the C<Catalyst::Log>
484 man page.
485
486 =item $c->plugin( $name, $class, @args )
487
488 Instant plugins for Catalyst.
489 Classdata accessor/mutator will be created, class loaded and instantiated.
490
491     MyApp->plugin( 'prototype', 'HTML::Prototype' );
492
493     $c->prototype->define_javascript_functions;
494
495 =cut
496
497 sub plugin {
498     my ( $class, $name, $plugin, @args ) = @_;
499     $plugin->require;
500
501     if ( my $error = $UNIVERSAL::require::ERROR ) {
502         Catalyst::Exception->throw(
503             message => qq/Couldn't load instant plugin "$plugin", "$error"/ );
504     }
505
506     eval { $plugin->import };
507     $class->mk_classdata($name);
508     my $obj;
509     eval { $obj = $plugin->new(@args) };
510
511     if ($@) {
512         Catalyst::Exception->throw( message =>
513               qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
514     }
515
516     $class->$name($obj);
517     $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
518       if $class->debug;
519 }
520
521 =item $c->request
522
523 =item $c->req
524
525 Returns a C<Catalyst::Request> object.
526
527     my $req = $c->req;
528
529 =item $c->response
530
531 =item $c->res
532
533 Returns a C<Catalyst::Response> object.
534
535     my $res = $c->res;
536
537 =item $c->state
538
539 Contains the return value of the last executed action.
540
541 =item $c->stash
542
543 Returns a hashref containing all your data.
544
545     print $c->stash->{foo};
546
547 Keys may be set in the stash by assigning to the hash reference, or by passing
548 either a single hash reference or a list of key/value pairs as arguments.
549
550 For example:
551
552     $c->stash->{foo} ||= 'yada';
553     $c->stash( { moose => 'majestic', qux => 0 } );
554     $c->stash( bar => 1, gorch => 2 );
555
556 =cut
557
558 sub stash {
559     my $c = shift;
560     if (@_) {
561         my $stash = @_ > 1 ? {@_} : $_[0];
562         while ( my ( $key, $val ) = each %$stash ) {
563             $c->{stash}->{$key} = $val;
564         }
565     }
566     return $c->{stash};
567 }
568
569 =item $c->welcome_message
570
571 Returns the Catalyst welcome HTML page.
572
573 =cut
574
575 sub welcome_message {
576     my $c      = shift;
577     my $name   = $c->config->{name};
578     my $logo   = $c->uri_for('/static/images/catalyst_logo.png');
579     my $prefix = Catalyst::Utils::appprefix( ref $c );
580     return <<"EOF";
581 <html>
582     <head>
583         <title>$name on Catalyst $VERSION</title>
584         <style type="text/css">
585             body {
586                 text-align: center;
587                 padding-left: 50%;
588                 color: #000;
589                 background-color: #eee;
590             }
591             div#content {
592                 width: 640px;
593                 margin-left: -320px;
594                 margin-top: 10px;
595                 margin-bottom: 10px;
596                 text-align: left;
597                 background-color: #ccc;
598                 border: 1px solid #aaa;
599                 -moz-border-radius: 10px;
600             }
601             p, h1, h2 {
602                 margin-left: 20px;
603                 margin-right: 20px;
604                 font-family: verdana, tahoma, sans-serif;
605             }
606             a {
607                 font-family: verdana, tahoma, sans-serif;
608             }
609             :link, :visited {
610                     text-decoration: none;
611                     color: #b00;
612                     border-bottom: 1px dotted #bbb;
613             }
614             :link:hover, :visited:hover {
615                     color: #555;
616             }
617             div#topbar {
618                 margin: 0px;
619             }
620             pre {
621                 margin: 10px;
622                 padding: 8px;
623             }
624             div#answers {
625                 padding: 8px;
626                 margin: 10px;
627                 background-color: #fff;
628                 border: 1px solid #aaa;
629                 -moz-border-radius: 10px;
630             }
631             h1 {
632                 font-size: 0.9em;
633                 font-weight: normal;
634                 text-align: center;
635             }
636             h2 {
637                 font-size: 1.0em;
638             }
639             p {
640                 font-size: 0.9em;
641             }
642             p img {
643                 float: right;
644                 margin-left: 10px;
645             }
646             b#appname {
647                 font-size: 1.6em;
648             }
649         </style>
650     </head>
651     <body>
652         <div id="content">
653             <div id="topbar">
654                 <h1><b id="appname">$name</b> on <a href="http://catalyst.perl.org">Catalyst</a>
655                     $VERSION</h1>
656              </div>
657              <div id="answers">
658                  <p>
659                  <img src="$logo"/>
660                  </p>
661                  <p>Welcome to the wonderful world of Catalyst.
662                     This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
663                     framework will make web development something you had
664                     never expected it to be: Fun, rewarding and quick.</p>
665                  <h2>What to do now?</h2>
666                  <p>That really depends  on what <b>you</b> want to do.
667                     We do, however, provide you with a few starting points.</p>
668                  <p>If you want to jump right into web development with Catalyst
669                     you might want to check out the documentation.</p>
670                  <pre><code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
671 perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual.pod">Catalyst::Manual</a></code></pre>
672                  <h2>What to do next?</h2>
673                  <p>Next it's time to write an actual application. Use the
674                     helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&mode=all">controllers</a>,
675                     <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&mode=all">models</a> and
676                     <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&mode=all">views</a>,
677                     they can save you a lot of work.</p>
678                     <pre><code>script/${prefix}_create.pl -help</code></pre>
679                     <p>Also, be sure to check out the vast and growing
680                     collection of <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3APlugin%3A%3A&mode=all">plugins for Catalyst on CPAN</a>,
681                     you are likely to find what you need there.
682                     </p>
683
684                  <h2>Need help?</h2>
685                  <p>Catalyst has a very active community. Here are the main places to
686                     get in touch with us.</p>
687                  <ul>
688                      <li>
689                          <a href="http://dev.catalyst.perl.org">Wiki</a>
690                      </li>
691                      <li>
692                          <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
693                      </li>
694                      <li>
695                          <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
696                      </li>
697                  </ul>
698                  <h2>In conclusion</h2>
699                  <p>The Catalyst team hopes you will enjoy using Catalyst as much 
700                     as we enjoyed making it. Please contact us if you have ideas
701                     for improvement or other feedback.</p>
702              </div>
703          </div>
704     </body>
705 </html>
706 EOF
707 }
708
709 =back
710
711 =head1 INTERNAL METHODS
712
713 =over 4
714
715 =item $c->benchmark($coderef)
716
717 Takes a coderef with arguments and returns elapsed time as float.
718
719     my ( $elapsed, $status ) = $c->benchmark( sub { return 1 } );
720     $c->log->info( sprintf "Processing took %f seconds", $elapsed );
721
722 =cut
723
724 sub benchmark {
725     my $c       = shift;
726     my $code    = shift;
727     my $time    = [gettimeofday];
728     my @return  = &$code(@_);
729     my $elapsed = tv_interval $time;
730     return wantarray ? ( $elapsed, @return ) : $elapsed;
731 }
732
733 =item $c->components
734
735 Contains the components.
736
737 =item $c->counter
738
739 Returns a hashref containing coderefs and execution counts.
740 (Needed for deep recursion detection) 
741
742 =item $c->depth
743
744 Returns the actual forward depth.
745
746 =item $c->dispatch
747
748 Dispatch request to actions.
749
750 =cut
751
752 sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
753
754 =item $c->execute($class, $coderef)
755
756 Execute a coderef in given class and catch exceptions.
757 Errors are available via $c->error.
758
759 =cut
760
761 sub execute {
762     my ( $c, $class, $code ) = @_;
763     $class = $c->components->{$class} || $class;
764     $c->state(0);
765     my $callsub = ( caller(1) )[3];
766
767     my $action = '';
768     if ( $c->debug ) {
769         $action = "$code";
770         $action = "/$action" unless $action =~ /\-\>/;
771         $c->counter->{"$code"}++;
772
773         if ( $c->counter->{"$code"} > $RECURSION ) {
774             my $error = qq/Deep recursion detected in "$action"/;
775             $c->log->error($error);
776             $c->error($error);
777             $c->state(0);
778             return $c->state;
779         }
780
781         $action = "-> $action" if $callsub =~ /forward$/;
782     }
783     $c->{depth}++;
784     eval {
785         if ( $c->debug )
786         {
787             my ( $elapsed, @state ) =
788               $c->benchmark( $code, $class, $c, @{ $c->req->args } );
789             push @{ $c->{stats} }, [ $action, sprintf( '%fs', $elapsed ) ];
790             $c->state(@state);
791         }
792         else {
793             $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 );
794         }
795     };
796     $c->{depth}--;
797
798     if ( my $error = $@ ) {
799
800         if ( $error eq $DETACH ) { die $DETACH if $c->{depth} > 1 }
801         else {
802             unless ( ref $error ) {
803                 chomp $error;
804                 $error = qq/Caught exception "$error"/;
805             }
806
807             $c->log->error($error);
808             $c->error($error);
809             $c->state(0);
810         }
811     }
812     return $c->state;
813 }
814
815 =item $c->finalize
816
817 Finalize request.
818
819 =cut
820
821 sub finalize {
822     my $c = shift;
823
824     $c->finalize_uploads;
825
826     # Error
827     if ( $#{ $c->error } >= 0 ) {
828         $c->finalize_error;
829     }
830
831     $c->finalize_headers;
832
833     # HEAD request
834     if ( $c->request->method eq 'HEAD' ) {
835         $c->response->body('');
836     }
837
838     $c->finalize_body;
839
840     return $c->response->status;
841 }
842
843 =item $c->finalize_body
844
845 Finalize body.
846
847 =cut
848
849 sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
850
851 =item $c->finalize_cookies
852
853 Finalize cookies.
854
855 =cut
856
857 sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
858
859 =item $c->finalize_error
860
861 Finalize error.
862
863 =cut
864
865 sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
866
867 =item $c->finalize_headers
868
869 Finalize headers.
870
871 =cut
872
873 sub finalize_headers {
874     my $c = shift;
875
876     # Check if we already finalized headers
877     return if $c->response->{_finalized_headers};
878
879     # Handle redirects
880     if ( my $location = $c->response->redirect ) {
881         $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
882         $c->response->header( Location => $location );
883     }
884
885     # Content-Length
886     if ( $c->response->body && !$c->response->content_length ) {
887         $c->response->content_length( bytes::length( $c->response->body ) );
888     }
889
890     # Errors
891     if ( $c->response->status =~ /^(1\d\d|[23]04)$/ ) {
892         $c->response->headers->remove_header("Content-Length");
893         $c->response->body('');
894     }
895
896     $c->finalize_cookies;
897
898     $c->engine->finalize_headers( $c, @_ );
899
900     # Done
901     $c->response->{_finalized_headers} = 1;
902 }
903
904 =item $c->finalize_output
905
906 An alias for finalize_body.
907
908 =item $c->finalize_read
909
910 Finalize the input after reading is complete.
911
912 =cut
913
914 sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
915
916 =item $c->finalize_uploads
917
918 Finalize uploads.  Cleans up any temporary files.
919
920 =cut
921
922 sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
923
924 =item $c->get_action( $action, $namespace, $inherit )
925
926 Get an action in a given namespace.
927
928 =cut
929
930 sub get_action { my $c = shift; $c->dispatcher->get_action( $c, @_ ) }
931
932 =item handle_request( $class, @arguments )
933
934 Handles the request.
935
936 =cut
937
938 sub handle_request {
939     my ( $class, @arguments ) = @_;
940
941     # Always expect worst case!
942     my $status = -1;
943     eval {
944         my @stats = ();
945
946         my $handler = sub {
947             my $c = $class->prepare(@arguments);
948             $c->{stats} = \@stats;
949             $c->dispatch;
950             return $c->finalize;
951         };
952
953         if ( $class->debug ) {
954             my $elapsed;
955             ( $elapsed, $status ) = $class->benchmark($handler);
956             $elapsed = sprintf '%f', $elapsed;
957             my $av = sprintf '%.3f',
958               ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) );
959             my $t = Text::ASCIITable->new;
960             $t->setCols( 'Action', 'Time' );
961             $t->setColWidth( 'Action', 64, 1 );
962             $t->setColWidth( 'Time',   9,  1 );
963
964             for my $stat (@stats) { $t->addRow( $stat->[0], $stat->[1] ) }
965             $class->log->info(
966                 "Request took ${elapsed}s ($av/s)\n" . $t->draw );
967         }
968         else { $status = &$handler }
969
970     };
971
972     if ( my $error = $@ ) {
973         chomp $error;
974         $class->log->error(qq/Caught exception in engine "$error"/);
975     }
976
977     $COUNT++;
978     $class->log->_flush() if $class->log->can('_flush');
979     return $status;
980 }
981
982 =item $c->prepare(@arguments)
983
984 Turns the engine-specific request( Apache, CGI ... )
985 into a Catalyst context .
986
987 =cut
988
989 sub prepare {
990     my ( $class, @arguments ) = @_;
991
992     my $c = bless {
993         counter => {},
994         depth   => 0,
995         request => Catalyst::Request->new(
996             {
997                 arguments        => [],
998                 body_parameters  => {},
999                 cookies          => {},
1000                 headers          => HTTP::Headers->new,
1001                 parameters       => {},
1002                 query_parameters => {},
1003                 secure           => 0,
1004                 snippets         => [],
1005                 uploads          => {}
1006             }
1007         ),
1008         response => Catalyst::Response->new(
1009             {
1010                 body    => '',
1011                 cookies => {},
1012                 headers => HTTP::Headers->new(),
1013                 status  => 200
1014             }
1015         ),
1016         stash => {},
1017         state => 0
1018     }, $class;
1019
1020     # For on-demand data
1021     $c->request->{_context}  = $c;
1022     $c->response->{_context} = $c;
1023     weaken( $c->request->{_context} );
1024     weaken( $c->response->{_context} );
1025
1026     if ( $c->debug ) {
1027         my $secs = time - $START || 1;
1028         my $av = sprintf '%.3f', $COUNT / $secs;
1029         $c->log->debug('**********************************');
1030         $c->log->debug("* Request $COUNT ($av/s) [$$]");
1031         $c->log->debug('**********************************');
1032         $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
1033     }
1034
1035     $c->prepare_request(@arguments);
1036     $c->prepare_connection;
1037     $c->prepare_query_parameters;
1038     $c->prepare_headers;
1039     $c->prepare_cookies;
1040     $c->prepare_path;
1041
1042     # On-demand parsing
1043     $c->prepare_body unless $c->config->{parse_on_demand};
1044
1045     $c->prepare_action;
1046     my $method  = $c->req->method  || '';
1047     my $path    = $c->req->path    || '';
1048     my $address = $c->req->address || '';
1049
1050     $c->log->debug(qq/"$method" request for "$path" from $address/)
1051       if $c->debug;
1052
1053     return $c;
1054 }
1055
1056 =item $c->prepare_action
1057
1058 Prepare action.
1059
1060 =cut
1061
1062 sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1063
1064 =item $c->prepare_body
1065
1066 Prepare message body.
1067
1068 =cut
1069
1070 sub prepare_body {
1071     my $c = shift;
1072
1073     # Do we run for the first time?
1074     return if defined $c->request->{_body};
1075
1076     # Initialize on-demand data
1077     $c->engine->prepare_body( $c, @_ );
1078     $c->prepare_parameters;
1079     $c->prepare_uploads;
1080
1081     if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1082         my $t = Text::ASCIITable->new;
1083         $t->setCols( 'Key', 'Value' );
1084         $t->setColWidth( 'Key',   37, 1 );
1085         $t->setColWidth( 'Value', 36, 1 );
1086         $t->alignCol( 'Value', 'right' );
1087         for my $key ( sort keys %{ $c->req->body_parameters } ) {
1088             my $param = $c->req->body_parameters->{$key};
1089             my $value = defined($param) ? $param : '';
1090             $t->addRow( $key,
1091                 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1092         }
1093         $c->log->debug( "Body Parameters are:\n" . $t->draw );
1094     }
1095 }
1096
1097 =item $c->prepare_body_chunk( $chunk )
1098
1099 Prepare a chunk of data before sending it to HTTP::Body.
1100
1101 =cut
1102
1103 sub prepare_body_chunk {
1104     my $c = shift;
1105     $c->engine->prepare_body_chunk( $c, @_ );
1106 }
1107
1108 =item $c->prepare_body_parameters
1109
1110 Prepare body parameters.
1111
1112 =cut
1113
1114 sub prepare_body_parameters {
1115     my $c = shift;
1116     $c->engine->prepare_body_parameters( $c, @_ );
1117 }
1118
1119 =item $c->prepare_connection
1120
1121 Prepare connection.
1122
1123 =cut
1124
1125 sub prepare_connection {
1126     my $c = shift;
1127     $c->engine->prepare_connection( $c, @_ );
1128 }
1129
1130 =item $c->prepare_cookies
1131
1132 Prepare cookies.
1133
1134 =cut
1135
1136 sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1137
1138 =item $c->prepare_headers
1139
1140 Prepare headers.
1141
1142 =cut
1143
1144 sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1145
1146 =item $c->prepare_parameters
1147
1148 Prepare parameters.
1149
1150 =cut
1151
1152 sub prepare_parameters {
1153     my $c = shift;
1154     $c->prepare_body_parameters;
1155     $c->engine->prepare_parameters( $c, @_ );
1156 }
1157
1158 =item $c->prepare_path
1159
1160 Prepare path and base.
1161
1162 =cut
1163
1164 sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1165
1166 =item $c->prepare_query_parameters
1167
1168 Prepare query parameters.
1169
1170 =cut
1171
1172 sub prepare_query_parameters {
1173     my $c = shift;
1174
1175     $c->engine->prepare_query_parameters( $c, @_ );
1176
1177     if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1178         my $t = Text::ASCIITable->new;
1179         $t->setCols( 'Key', 'Value' );
1180         $t->setColWidth( 'Key',   37, 1 );
1181         $t->setColWidth( 'Value', 36, 1 );
1182         $t->alignCol( 'Value', 'right' );
1183         for my $key ( sort keys %{ $c->req->query_parameters } ) {
1184             my $param = $c->req->query_parameters->{$key};
1185             my $value = defined($param) ? $param : '';
1186             $t->addRow( $key,
1187                 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1188         }
1189         $c->log->debug( "Query Parameters are:\n" . $t->draw );
1190     }
1191 }
1192
1193 =item $c->prepare_read
1194
1195 Prepare the input for reading.
1196
1197 =cut
1198
1199 sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1200
1201 =item $c->prepare_request
1202
1203 Prepare the engine request.
1204
1205 =cut
1206
1207 sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1208
1209 =item $c->prepare_uploads
1210
1211 Prepare uploads.
1212
1213 =cut
1214
1215 sub prepare_uploads {
1216     my $c = shift;
1217
1218     $c->engine->prepare_uploads( $c, @_ );
1219
1220     if ( $c->debug && keys %{ $c->request->uploads } ) {
1221         my $t = Text::ASCIITable->new;
1222         $t->setCols( 'Key', 'Filename', 'Type', 'Size' );
1223         $t->setColWidth( 'Key',      12, 1 );
1224         $t->setColWidth( 'Filename', 28, 1 );
1225         $t->setColWidth( 'Type',     18, 1 );
1226         $t->setColWidth( 'Size',     9,  1 );
1227         $t->alignCol( 'Size', 'left' );
1228         for my $key ( sort keys %{ $c->request->uploads } ) {
1229             my $upload = $c->request->uploads->{$key};
1230             for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
1231                 $t->addRow( $key, $u->filename, $u->type, $u->size );
1232             }
1233         }
1234         $c->log->debug( "File Uploads are:\n" . $t->draw );
1235     }
1236 }
1237
1238 =item $c->prepare_write
1239
1240 Prepare the output for writing.
1241
1242 =cut
1243
1244 sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1245
1246 =item $c->read( [$maxlength] )
1247
1248 Read a chunk of data from the request body.  This method is designed to be
1249 used in a while loop, reading $maxlength bytes on every call.  $maxlength
1250 defaults to the size of the request if not specified.
1251
1252 You have to set MyApp->config->{parse_on_demand} to use this directly.
1253
1254 =cut
1255
1256 sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1257
1258 =item $c->run
1259
1260 Starts the engine.
1261
1262 =cut
1263
1264 sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1265
1266 =item $c->set_action( $action, $code, $namespace, $attrs )
1267
1268 Set an action in a given namespace.
1269
1270 =cut
1271
1272 sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1273
1274 =item $c->setup_actions($component)
1275
1276 Setup actions for a component.
1277
1278 =cut
1279
1280 sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1281
1282 =item $c->setup_components
1283
1284 Setup components.
1285
1286 =cut
1287
1288 sub setup_components {
1289     my $class = shift;
1290
1291     my $callback = sub {
1292         my ( $component, $context ) = @_;
1293
1294         unless ( $component->isa('Catalyst::Base') ) {
1295             return $component;
1296         }
1297
1298         my $suffix = Catalyst::Utils::class2classsuffix($component);
1299         my $config = $class->config->{$suffix} || {};
1300
1301         my $instance;
1302
1303         eval { $instance = $component->new( $context, $config ); };
1304
1305         if ( my $error = $@ ) {
1306
1307             chomp $error;
1308
1309             Catalyst::Exception->throw( message =>
1310                   qq/Couldn't instantiate component "$component", "$error"/ );
1311         }
1312
1313         Catalyst::Exception->throw( message =>
1314 qq/Couldn't instantiate component "$component", "new() didn't return a object"/
1315           )
1316           unless ref $instance;
1317         return $instance;
1318     };
1319
1320     eval {
1321         Module::Pluggable::Fast->import(
1322             name   => '_catalyst_components',
1323             search => [
1324                 "$class\::Controller", "$class\::C",
1325                 "$class\::Model",      "$class\::M",
1326                 "$class\::View",       "$class\::V"
1327             ],
1328             callback => $callback
1329         );
1330     };
1331
1332     if ( my $error = $@ ) {
1333
1334         chomp $error;
1335
1336         Catalyst::Exception->throw(
1337             message => qq/Couldn't load components "$error"/ );
1338     }
1339
1340     for my $component ( $class->_catalyst_components($class) ) {
1341         $class->components->{ ref $component || $component } = $component;
1342     }
1343 }
1344
1345 =item $c->setup_dispatcher
1346
1347 =cut
1348
1349 sub setup_dispatcher {
1350     my ( $class, $dispatcher ) = @_;
1351
1352     if ($dispatcher) {
1353         $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1354     }
1355
1356     if ( $ENV{CATALYST_DISPATCHER} ) {
1357         $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
1358     }
1359
1360     if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
1361         $dispatcher =
1362           'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
1363     }
1364
1365     unless ($dispatcher) {
1366         $dispatcher = 'Catalyst::Dispatcher';
1367     }
1368
1369     $dispatcher->require;
1370
1371     if ($@) {
1372         Catalyst::Exception->throw(
1373             message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
1374     }
1375
1376     # dispatcher instance
1377     $class->dispatcher( $dispatcher->new );
1378 }
1379
1380 =item $c->setup_engine
1381
1382 =cut
1383
1384 sub setup_engine {
1385     my ( $class, $engine ) = @_;
1386
1387     if ($engine) {
1388         $engine = 'Catalyst::Engine::' . $engine;
1389     }
1390
1391     if ( $ENV{CATALYST_ENGINE} ) {
1392         $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
1393     }
1394
1395     if ( $ENV{ uc($class) . '_ENGINE' } ) {
1396         $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
1397     }
1398
1399     if ( !$engine && $ENV{MOD_PERL} ) {
1400
1401         # create the apache method
1402         {
1403             no strict 'refs';
1404             *{"$class\::apache"} = sub { shift->engine->apache };
1405         }
1406
1407         my ( $software, $version ) =
1408           $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
1409
1410         $version =~ s/_//g;
1411         $version =~ s/(\.[^.]+)\./$1/g;
1412
1413         if ( $software eq 'mod_perl' ) {
1414
1415             if ( $version >= 1.99922 ) {
1416                 $engine = 'Catalyst::Engine::Apache2::MP20';
1417             }
1418
1419             elsif ( $version >= 1.9901 ) {
1420                 $engine = 'Catalyst::Engine::Apache2::MP19';
1421             }
1422
1423             elsif ( $version >= 1.24 ) {
1424                 $engine = 'Catalyst::Engine::Apache::MP13';
1425             }
1426
1427             else {
1428                 Catalyst::Exception->throw( message =>
1429                       qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
1430             }
1431
1432             # install the correct mod_perl handler
1433             if ( $version >= 1.9901 ) {
1434                 *handler = sub  : method {
1435                     shift->handle_request(@_);
1436                 };
1437             }
1438             else {
1439                 *handler = sub ($$) { shift->handle_request(@_) };
1440             }
1441
1442         }
1443
1444         elsif ( $software eq 'Zeus-Perl' ) {
1445             $engine = 'Catalyst::Engine::Zeus';
1446         }
1447
1448         else {
1449             Catalyst::Exception->throw(
1450                 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
1451         }
1452     }
1453
1454     unless ($engine) {
1455         $engine = 'Catalyst::Engine::CGI';
1456     }
1457
1458     $engine->require;
1459
1460     if ($@) {
1461         Catalyst::Exception->throw( message =>
1462 qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
1463         );
1464     }
1465
1466     # engine instance
1467     $class->engine( $engine->new );
1468 }
1469
1470 =item $c->setup_home
1471
1472 =cut
1473
1474 sub setup_home {
1475     my ( $class, $home ) = @_;
1476
1477     if ( $ENV{CATALYST_HOME} ) {
1478         $home = $ENV{CATALYST_HOME};
1479     }
1480
1481     if ( $ENV{ uc($class) . '_HOME' } ) {
1482         $home = $ENV{ uc($class) . '_HOME' };
1483     }
1484
1485     unless ($home) {
1486         $home = Catalyst::Utils::home($class);
1487     }
1488
1489     if ($home) {
1490         $class->config->{home} ||= $home;
1491         $class->config->{root} ||= dir($home)->subdir('root');
1492     }
1493 }
1494
1495 =item $c->setup_log
1496
1497 =cut
1498
1499 sub setup_log {
1500     my ( $class, $debug ) = @_;
1501
1502     unless ( $class->log ) {
1503         $class->log( Catalyst::Log->new );
1504     }
1505
1506     if ( $ENV{CATALYST_DEBUG} || $ENV{ uc($class) . '_DEBUG' } || $debug ) {
1507         no strict 'refs';
1508         *{"$class\::debug"} = sub { 1 };
1509         $class->log->debug('Debug messages enabled');
1510     }
1511 }
1512
1513 =item $c->setup_plugins
1514
1515 =cut
1516
1517 sub setup_plugins {
1518     my ( $class, $plugins ) = @_;
1519
1520     $plugins ||= [];
1521     for my $plugin ( reverse @$plugins ) {
1522
1523         $plugin = "Catalyst::Plugin::$plugin";
1524
1525         $plugin->require;
1526
1527         if ($@) {
1528             Catalyst::Exception->throw(
1529                 message => qq/Couldn't load plugin "$plugin", "$@"/ );
1530         }
1531
1532         {
1533             no strict 'refs';
1534             unshift @{"$class\::ISA"}, $plugin;
1535         }
1536     }
1537 }
1538
1539 =item $c->write( $data )
1540
1541 Writes $data to the output stream.  When using this method directly, you will
1542 need to manually set the Content-Length header to the length of your output
1543 data, if known.
1544
1545 =cut
1546
1547 sub write {
1548     my $c = shift;
1549
1550     # Finalize headers if someone manually writes output
1551     $c->finalize_headers;
1552
1553     return $c->engine->write( $c, @_ );
1554 }
1555
1556 =back
1557
1558 =head1 CASE SENSITIVITY
1559
1560 By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> becomes
1561 C</foo/bar>.
1562
1563 But you can activate case sensitivity with a config parameter.
1564
1565     MyApp->config->{case_sensitive} = 1;
1566
1567 So C<MyApp::C::Foo::Bar> becomes C</Foo/Bar>.
1568
1569 =head1 ON-DEMAND PARSER
1570
1571 The request body is usually parsed at the beginning of a request,
1572 but if you want to handle input yourself or speed things up a bit
1573 you can enable on-demand parsing with a config parameter.
1574
1575     MyApp->config->{parse_on_demand} = 1;
1576     
1577 =head1 PROXY SUPPORT
1578
1579 Many production servers operate using the common double-server approach, with
1580 a lightweight frontend web server passing requests to a larger backend
1581 server.  An application running on the backend server must deal with two
1582 problems: the remote user always appears to be '127.0.0.1' and the server's
1583 hostname will appear to be 'localhost' regardless of the virtual host the
1584 user connected through.
1585
1586 Catalyst will automatically detect this situation when you are running both
1587 the frontend and backend servers on the same machine.  The following changes
1588 are made to the request.
1589
1590     $c->req->address is set to the user's real IP address, as read from the
1591     HTTP_X_FORWARDED_FOR header.
1592     
1593     The host value for $c->req->base and $c->req->uri is set to the real host,
1594     as read from the HTTP_X_FORWARDED_HOST header.
1595
1596 Obviously, your web server must support these 2 headers for this to work.
1597
1598 In a more complex server farm environment where you may have your frontend
1599 proxy server(s) on different machines, you will need to set a configuration
1600 option to tell Catalyst to read the proxied data from the headers.
1601
1602     MyApp->config->{using_frontend_proxy} = 1;
1603     
1604 If you do not wish to use the proxy support at all, you may set:
1605
1606     MyApp->config->{ignore_frontend_proxy} = 1;
1607
1608 =head1 THREAD SAFETY
1609
1610 Catalyst has been tested under Apache 2's threading mpm_worker, mpm_winnt,
1611 and the standalone forking HTTP server on Windows.  We believe the Catalyst
1612 core to be thread-safe.
1613
1614 If you plan to operate in a threaded environment, remember that all other
1615 modules you are using must also be thread-safe.  Some modules, most notably
1616 DBD::SQLite, are not thread-safe.
1617
1618 =head1 SUPPORT
1619
1620 IRC:
1621
1622     Join #catalyst on irc.perl.org.
1623
1624 Mailing-Lists:
1625
1626     http://lists.rawmode.org/mailman/listinfo/catalyst
1627     http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1628
1629 Web:
1630
1631     http://catalyst.perl.org
1632
1633 =head1 SEE ALSO
1634
1635 =over 4
1636
1637 =item L<Catalyst::Manual> - The Catalyst Manual
1638
1639 =item L<Catalyst::Engine> - Core Engine
1640
1641 =item L<Catalyst::Log> - The Log Class.
1642
1643 =item L<Catalyst::Request> - The Request Object
1644
1645 =item L<Catalyst::Response> - The Response Object
1646
1647 =item L<Catalyst::Test> - The test suite.
1648
1649 =back
1650
1651 =head1 CREDITS
1652
1653 Andy Grundman
1654
1655 Andy Wardley
1656
1657 Andreas Marienborg
1658
1659 Andrew Bramble
1660
1661 Andrew Ford
1662
1663 Andrew Ruthven
1664
1665 Arthur Bergman
1666
1667 Autrijus Tang
1668
1669 Christian Hansen
1670
1671 Christopher Hicks
1672
1673 Dan Sully
1674
1675 Danijel Milicevic
1676
1677 David Naughton
1678
1679 Gary Ashton Jones
1680
1681 Geoff Richards
1682
1683 Jesse Sheidlower
1684
1685 Jesse Vincent
1686
1687 Jody Belka
1688
1689 Johan Lindstrom
1690
1691 Juan Camacho
1692
1693 Leon Brocard
1694
1695 Marcus Ramberg
1696
1697 Matt S Trout
1698
1699 Robert Sedlacek
1700
1701 Tatsuhiko Miyagawa
1702
1703 Ulf Edvinsson
1704
1705 Yuval Kogman
1706
1707 =head1 AUTHOR
1708
1709 Sebastian Riedel, C<sri@oook.de>
1710
1711 =head1 LICENSE
1712
1713 This library is free software, you can redistribute it and/or modify it under
1714 the same terms as Perl itself.
1715
1716 =cut
1717
1718 1;