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