Fixed uri_for bug found by drewbie
[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 specifed 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_parameters
908
909 Prepare body parameters.
910
911 =cut
912
913 sub prepare_body_parameters {
914     my $c = shift;
915     $c->engine->prepare_body_parameters( $c, @_ );
916 }
917
918 =item $c->prepare_connection
919
920 Prepare connection.
921
922 =cut
923
924 sub prepare_connection {
925     my $c = shift;
926     $c->engine->prepare_connection( $c, @_ );
927 }
928
929 =item $c->prepare_cookies
930
931 Prepare cookies.
932
933 =cut
934
935 sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
936
937 =item $c->prepare_headers
938
939 Prepare headers.
940
941 =cut
942
943 sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
944
945 =item $c->prepare_parameters
946
947 Prepare parameters.
948
949 =cut
950
951 sub prepare_parameters {
952     my $c = shift;
953     $c->prepare_body_parameters;
954     $c->engine->prepare_parameters( $c, @_ );
955 }
956
957 =item $c->prepare_path
958
959 Prepare path and base.
960
961 =cut
962
963 sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
964
965 =item $c->prepare_query_parameters
966
967 Prepare query parameters.
968
969 =cut
970
971 sub prepare_query_parameters {
972     my $c = shift;
973
974     $c->engine->prepare_query_parameters( $c, @_ );
975
976     if ( $c->debug && keys %{ $c->request->query_parameters } ) {
977         my $t = Text::ASCIITable->new;
978         $t->setCols( 'Key', 'Value' );
979         $t->setColWidth( 'Key',   37, 1 );
980         $t->setColWidth( 'Value', 36, 1 );
981         $t->alignCol( 'Value', 'right' );
982         for my $key ( sort keys %{ $c->req->query_parameters } ) {
983             my $param = $c->req->query_parameters->{$key};
984             my $value = defined($param) ? $param : '';
985             $t->addRow( $key,
986                 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
987         }
988         $c->log->debug( "Query Parameters are:\n" . $t->draw );
989     }
990 }
991
992 =item $c->prepare_read
993
994 Prepare the input for reading.
995
996 =cut
997
998 sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
999
1000 =item $c->prepare_request
1001
1002 Prepare the engine request.
1003
1004 =cut
1005
1006 sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1007
1008 =item $c->prepare_uploads
1009
1010 Prepare uploads.
1011
1012 =cut
1013
1014 sub prepare_uploads {
1015     my $c = shift;
1016
1017     $c->engine->prepare_uploads( $c, @_ );
1018
1019     if ( $c->debug && keys %{ $c->request->uploads } ) {
1020         my $t = Text::ASCIITable->new;
1021         $t->setCols( 'Filename', 'Type', 'Size' );
1022         $t->setColWidth( 'Filename', 37, 1 );
1023         $t->setColWidth( 'Type',     24, 1 );
1024         $t->setColWidth( 'Size',     9,  1 );
1025         $t->alignCol( 'Size', 'left' );
1026         for my $key ( sort keys %{ $c->request->uploads } ) {
1027             my $upload = $c->request->uploads->{$key};
1028             for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
1029                 $t->addRow( $key, $u->type, $u->size );
1030             }
1031         }
1032         $c->log->debug( "File Uploads are:\n" . $t->draw );
1033     }
1034 }
1035
1036 =item $c->prepare_write
1037
1038 Prepare the output for writing.
1039
1040 =cut
1041
1042 sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1043
1044 =item $c->read( [$maxlength] )
1045
1046 Read a chunk of data from the request body.  This method is designed to be
1047 used in a while loop, reading $maxlength bytes on every call.  $maxlength
1048 defaults to the size of the request if not specified.
1049
1050 You have to set MyApp->config->{parse_on_demand} to use this directly.
1051
1052 =cut
1053
1054 sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1055
1056 =item $c->run
1057
1058 Starts the engine.
1059
1060 =cut
1061
1062 sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1063
1064 =item $c->set_action( $action, $code, $namespace, $attrs )
1065
1066 Set an action in a given namespace.
1067
1068 =cut
1069
1070 sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1071
1072 =item $c->setup_actions($component)
1073
1074 Setup actions for a component.
1075
1076 =cut
1077
1078 sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1079
1080 =item $c->setup_components
1081
1082 Setup components.
1083
1084 =cut
1085
1086 sub setup_components {
1087     my $class = shift;
1088
1089     my $callback = sub {
1090         my ( $component, $context ) = @_;
1091
1092         unless ( $component->isa('Catalyst::Base') ) {
1093             return $component;
1094         }
1095
1096         my $suffix = Catalyst::Utils::class2classsuffix($component);
1097         my $config = $class->config->{$suffix} || {};
1098
1099         my $instance;
1100
1101         eval { $instance = $component->new( $context, $config ); };
1102
1103         if ( my $error = $@ ) {
1104
1105             chomp $error;
1106
1107             Catalyst::Exception->throw( message =>
1108                   qq/Couldn't instantiate component "$component", "$error"/ );
1109         }
1110
1111         Catalyst::Exception->throw( message =>
1112 qq/Couldn't instantiate component "$component", "new() didn't return a object"/
1113           )
1114           unless ref $instance;
1115         return $instance;
1116     };
1117
1118     eval {
1119         Module::Pluggable::Fast->import(
1120             name   => '_catalyst_components',
1121             search => [
1122                 "$class\::Controller", "$class\::C",
1123                 "$class\::Model",      "$class\::M",
1124                 "$class\::View",       "$class\::V"
1125             ],
1126             callback => $callback
1127         );
1128     };
1129
1130     if ( my $error = $@ ) {
1131
1132         chomp $error;
1133
1134         Catalyst::Exception->throw(
1135             message => qq/Couldn't load components "$error"/ );
1136     }
1137
1138     for my $component ( $class->_catalyst_components($class) ) {
1139         $class->components->{ ref $component || $component } = $component;
1140     }
1141 }
1142
1143 =item $c->setup_dispatcher
1144
1145 =cut
1146
1147 sub setup_dispatcher {
1148     my ( $class, $dispatcher ) = @_;
1149
1150     if ($dispatcher) {
1151         $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1152     }
1153
1154     if ( $ENV{CATALYST_DISPATCHER} ) {
1155         $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
1156     }
1157
1158     if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
1159         $dispatcher =
1160           'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
1161     }
1162
1163     unless ($dispatcher) {
1164         $dispatcher = 'Catalyst::Dispatcher';
1165     }
1166
1167     $dispatcher->require;
1168
1169     if ($@) {
1170         Catalyst::Exception->throw(
1171             message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
1172     }
1173
1174     # dispatcher instance
1175     $class->dispatcher( $dispatcher->new );
1176 }
1177
1178 =item $c->setup_engine
1179
1180 =cut
1181
1182 sub setup_engine {
1183     my ( $class, $engine ) = @_;
1184
1185     if ($engine) {
1186         $engine = 'Catalyst::Engine::' . $engine;
1187     }
1188
1189     if ( $ENV{CATALYST_ENGINE} ) {
1190         $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
1191     }
1192
1193     if ( $ENV{ uc($class) . '_ENGINE' } ) {
1194         $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
1195     }
1196
1197     if ( !$engine && $ENV{MOD_PERL} ) {
1198
1199         # create the apache method
1200         {
1201             no strict 'refs';
1202             *{"$class\::apache"} = sub { shift->engine->apache };
1203         }
1204
1205         my ( $software, $version ) =
1206           $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
1207
1208         $version =~ s/_//g;
1209         $version =~ s/(\.[^.]+)\./$1/g;
1210
1211         if ( $software eq 'mod_perl' ) {
1212
1213             if ( $version >= 1.99922 ) {
1214                 $engine = 'Catalyst::Engine::Apache2::MP20';
1215             }
1216
1217             elsif ( $version >= 1.9901 ) {
1218                 $engine = 'Catalyst::Engine::Apache2::MP19';
1219             }
1220
1221             elsif ( $version >= 1.24 ) {
1222                 $engine = 'Catalyst::Engine::Apache::MP13';
1223             }
1224
1225             else {
1226                 Catalyst::Exception->throw( message =>
1227                       qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
1228             }
1229
1230             # install the correct mod_perl handler
1231             if ( $version >= 1.9901 ) {
1232                 *handler = sub  : method {
1233                     shift->handle_request(@_);
1234                 };
1235             }
1236             else {
1237                 *handler = sub ($$) { shift->handle_request(@_) };
1238             }
1239
1240         }
1241
1242         elsif ( $software eq 'Zeus-Perl' ) {
1243             $engine = 'Catalyst::Engine::Zeus';
1244         }
1245
1246         else {
1247             Catalyst::Exception->throw(
1248                 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
1249         }
1250     }
1251
1252     unless ($engine) {
1253         $engine = 'Catalyst::Engine::CGI';
1254     }
1255
1256     $engine->require;
1257
1258     if ($@) {
1259         Catalyst::Exception->throw( message =>
1260 qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
1261         );
1262     }
1263
1264     # engine instance
1265     $class->engine( $engine->new );
1266 }
1267
1268 =item $c->setup_home
1269
1270 =cut
1271
1272 sub setup_home {
1273     my ( $class, $home ) = @_;
1274
1275     if ( $ENV{CATALYST_HOME} ) {
1276         $home = $ENV{CATALYST_HOME};
1277     }
1278
1279     if ( $ENV{ uc($class) . '_HOME' } ) {
1280         $home = $ENV{ uc($class) . '_HOME' };
1281     }
1282
1283     unless ($home) {
1284         $home = Catalyst::Utils::home($class);
1285     }
1286
1287     if ($home) {
1288         $class->config->{home} ||= $home;
1289         $class->config->{root} ||= dir($home)->subdir('root');
1290     }
1291 }
1292
1293 =item $c->setup_log
1294
1295 =cut
1296
1297 sub setup_log {
1298     my ( $class, $debug ) = @_;
1299
1300     unless ( $class->log ) {
1301         $class->log( Catalyst::Log->new );
1302     }
1303
1304     if ( $ENV{CATALYST_DEBUG} || $ENV{ uc($class) . '_DEBUG' } || $debug ) {
1305         no strict 'refs';
1306         *{"$class\::debug"} = sub { 1 };
1307         $class->log->debug('Debug messages enabled');
1308     }
1309 }
1310
1311 =item $c->setup_plugins
1312
1313 =cut
1314
1315 sub setup_plugins {
1316     my ( $class, $plugins ) = @_;
1317
1318     $plugins ||= [];
1319     for my $plugin ( reverse @$plugins ) {
1320
1321         $plugin = "Catalyst::Plugin::$plugin";
1322
1323         $plugin->require;
1324
1325         if ($@) {
1326             Catalyst::Exception->throw(
1327                 message => qq/Couldn't load plugin "$plugin", "$@"/ );
1328         }
1329
1330         {
1331             no strict 'refs';
1332             unshift @{"$class\::ISA"}, $plugin;
1333         }
1334     }
1335 }
1336
1337 =item $c->write( $data )
1338
1339 Writes $data to the output stream.  When using this method directly, you will
1340 need to manually set the Content-Length header to the length of your output
1341 data, if known.
1342
1343 =cut
1344
1345 sub write { my $c = shift; return $c->engine->write( $c, @_ ) }
1346
1347 =back
1348
1349 =head1 CASE SENSITIVITY
1350
1351 By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> becomes
1352 C</foo/bar>.
1353
1354 But you can activate case sensitivity with a config parameter.
1355
1356     MyApp->config->{case_sensitive} = 1;
1357
1358 So C<MyApp::C::Foo::Bar> becomes C</Foo/Bar>.
1359
1360 =head1 ON-DEMAND PARSER
1361
1362 The request body is usually parsed at the beginning of a request,
1363 but if you want to handle input yourself or speed things up a bit
1364 you can enable on-demand parsing with a config parameter.
1365
1366     MyApp->config->{parse_on_demand} = 1;
1367     
1368 =head1 PROXY SUPPORT
1369
1370 Many production servers operate using the common double-server approach, with
1371 a lightweight frontend web server passing requests to a larger backend
1372 server.  An application running on the backend server must deal with two
1373 problems: the remote user always appears to be '127.0.0.1' and the server's
1374 hostname will appear to be 'localhost' regardless of the virtual host the
1375 user connected through.
1376
1377 Catalyst will automatically detect this situation when you are running both
1378 the frontend and backend servers on the same machine.  The following changes
1379 are made to the request.
1380
1381     $c->req->address is set to the user's real IP address, as read from the
1382     HTTP_X_FORWARDED_FOR header.
1383     
1384     The host value for $c->req->base and $c->req->uri is set to the real host,
1385     as read from the HTTP_X_FORWARDED_HOST header.
1386
1387 Obviously, your web server must support these 2 headers for this to work.
1388
1389 In a more complex server farm environment where you may have your frontend
1390 proxy server(s) on different machines, you will need to set a configuration
1391 option to tell Catalyst to read the proxied data from the headers.
1392
1393     MyApp->config->{using_frontend_proxy} = 1;
1394     
1395 If you do not wish to use the proxy support at all, you may set:
1396
1397     MyApp->config->{ignore_frontend_proxy} = 1;
1398
1399 =head1 THREAD SAFETY
1400
1401 Catalyst has been tested under Apache 2's threading mpm_worker, mpm_winnt,
1402 and the standalone forking HTTP server on Windows.  We believe the Catalyst
1403 core to be thread-safe.
1404
1405 If you plan to operate in a threaded environment, remember that all other
1406 modules you are using must also be thread-safe.  Some modules, most notably
1407 DBD::SQLite, are not thread-safe.
1408
1409 =head1 SUPPORT
1410
1411 IRC:
1412
1413     Join #catalyst on irc.perl.org.
1414
1415 Mailing-Lists:
1416
1417     http://lists.rawmode.org/mailman/listinfo/catalyst
1418     http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1419
1420 Web:
1421
1422     http://catalyst.perl.org
1423
1424 =head1 SEE ALSO
1425
1426 =over 4
1427
1428 =item L<Catalyst::Manual> - The Catalyst Manual
1429
1430 =item L<Catalyst::Engine> - Core Engine
1431
1432 =item L<Catalyst::Log> - The Log Class.
1433
1434 =item L<Catalyst::Request> - The Request Object
1435
1436 =item L<Catalyst::Response> - The Response Object
1437
1438 =item L<Catalyst::Test> - The test suite.
1439
1440 =back
1441
1442 =head1 CREDITS
1443
1444 Andy Grundman
1445
1446 Andy Wardley
1447
1448 Andrew Ford
1449
1450 Andrew Ruthven
1451
1452 Arthur Bergman
1453
1454 Autrijus Tang
1455
1456 Christian Hansen
1457
1458 Christopher Hicks
1459
1460 Dan Sully
1461
1462 Danijel Milicevic
1463
1464 David Naughton
1465
1466 Gary Ashton Jones
1467
1468 Geoff Richards
1469
1470 Jesse Sheidlower
1471
1472 Jesse Vincent
1473
1474 Jody Belka
1475
1476 Johan Lindstrom
1477
1478 Juan Camacho
1479
1480 Leon Brocard
1481
1482 Marcus Ramberg
1483
1484 Matt S Trout
1485
1486 Robert Sedlacek
1487
1488 Tatsuhiko Miyagawa
1489
1490 Ulf Edvinsson
1491
1492 =head1 AUTHOR
1493
1494 Sebastian Riedel, C<sri@oook.de>
1495
1496 =head1 LICENSE
1497
1498 This library is free software . You can redistribute it and/or modify it under
1499 the same terms as perl itself.
1500
1501 =cut
1502
1503 1;