4 use base 'Catalyst::Base';
6 use UNIVERSAL::require;
7 use Catalyst::Exception;
10 use Catalyst::Request::Upload;
11 use Catalyst::Response;
14 use Text::SimpleTable;
16 use Time::HiRes qw/gettimeofday tv_interval/;
18 use Scalar::Util qw/weaken/;
21 __PACKAGE__->mk_accessors(
22 qw/counter depth request response state action namespace/
25 attributes->import( __PACKAGE__, \&namespace, 'lvalue' );
32 # For backwards compatibility
33 *finalize_output = \&finalize_body;
38 our $RECURSION = 1000;
39 our $DETACH = "catalyst_detach\n";
41 require Module::Pluggable::Fast;
43 # Helper script generation
44 our $CATALYST_SCRIPT_GEN = 10;
46 __PACKAGE__->mk_classdata($_)
47 for qw/components arguments dispatcher engine log dispatcher_class
48 engine_class context_class request_class response_class/;
50 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
51 __PACKAGE__->engine_class('Catalyst::Engine::CGI');
52 __PACKAGE__->request_class('Catalyst::Request');
53 __PACKAGE__->response_class('Catalyst::Response');
55 our $VERSION = '5.49_03';
58 my ( $class, @arguments ) = @_;
60 # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
62 return unless $class eq 'Catalyst';
64 my $caller = caller(0);
66 unless ( $caller->isa('Catalyst') ) {
68 push @{"$caller\::ISA"}, $class;
71 $caller->arguments( [@arguments] );
77 Catalyst - The Elegant MVC Web Application Framework
81 # use the helper to start a new application
85 # add models, views, controllers
86 script/myapp_create.pl model Something
87 script/myapp_create.pl view Stuff
88 script/myapp_create.pl controller Yada
91 script/myapp_server.pl
93 # command line interface
94 script/myapp_test.pl /yada
99 use Catalyst qw/My::Module My::OtherModule/;
101 use Catalyst '-Debug';
103 use Catalyst qw/-Debug -Engine=CGI/;
105 sub default : Private { $_[1]->res->output('Hello') } );
107 sub index : Path('/index.html') {
108 my ( $self, $c ) = @_;
109 $c->res->output('Hello');
113 sub product : Regex('^product[_]*(\d*).html$') {
114 my ( $self, $c ) = @_;
115 $c->stash->{template} = 'product.tt';
116 $c->stash->{product} = $c->req->snippets->[0];
119 See also L<Catalyst::Manual::Intro>
123 The key concept of Catalyst is DRY (Don't Repeat Yourself).
125 See L<Catalyst::Manual> for more documentation.
127 Catalyst plugins can be loaded by naming them as arguments to the "use Catalyst" statement.
128 Omit the C<Catalyst::Plugin::> prefix from the plugin name,
129 so C<Catalyst::Plugin::My::Module> becomes C<My::Module>.
131 use Catalyst 'My::Module';
133 Special flags like -Debug and -Engine can also be specified as arguments when
136 use Catalyst qw/-Debug My::Module/;
138 The position of plugins and flags in the chain is important, because they are
139 loaded in exactly the order that they appear.
141 The following flags are supported:
147 enables debug output, i.e.:
149 use Catalyst '-Debug';
151 this is equivalent to:
158 Force Catalyst to use a specific dispatcher.
162 Force Catalyst to use a specific engine.
163 Omit the C<Catalyst::Engine::> prefix of the engine name, i.e.:
165 use Catalyst '-Engine=CGI';
169 Force Catalyst to use a specific home directory.
183 Accessor for the current action
185 =item $c->comp($name)
187 =item $c->component($name)
189 Get a component object by name.
191 $c->comp('MyApp::Model::MyModel')->do_stuff;
202 my $appclass = ref $c || $c;
205 $name, "${appclass}::${name}",
206 map { "${appclass}::${_}::${name}" } qw/M V C/
209 foreach my $try (@names) {
211 if ( exists $c->components->{$try} ) {
213 return $c->components->{$try};
217 foreach my $component ( keys %{ $c->components } ) {
219 return $c->components->{$component} if $component =~ /$name/i;
224 return sort keys %{ $c->components };
229 Returns a hashref containing your applications settings.
233 =item $c->controller($name)
235 Get a L<Catalyst::Controller> instance by name.
237 $c->controller('Foo')->do_stuff;
242 my ( $c, $name ) = @_;
243 my $controller = $c->comp("Controller::$name");
244 return $controller if $controller;
245 return $c->comp("C::$name");
250 Overload to enable debug messages.
256 =item $c->detach( $command [, \@arguments ] )
258 Like C<forward> but doesn't return.
262 sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
266 Contains the dispatcher instance.
267 Stringifies to class.
269 =item $c->forward( $command [, \@arguments ] )
271 Forward processing to a private action or a method from a class.
272 If you define a class without method it will default to process().
273 also takes an optional arrayref containing arguments to be passed
274 to the new function. $c->req->args will be reset upon returning
278 $c->forward('index');
279 $c->forward(qw/MyApp::Model::CDBI::Foo do_stuff/);
280 $c->forward('MyApp::View::TT');
284 sub forward { my $c = shift; $c->dispatcher->forward( $c, @_ ) }
286 =item $c->model($name)
288 Get a L<Catalyst::Model> instance by name.
290 $c->model('Foo')->do_stuff;
295 my ( $c, $name ) = @_;
296 my $model = $c->comp("Model::$name");
297 return $model if $model;
298 return $c->comp("M::$name");
303 Accessor to the namespace of the current action
305 =item $c->path_to(@path)
307 Merges C<@path> with $c->config->{home} and returns a L<Path::Class> object.
311 $c->path_to( 'db', 'sqlite.db' );
316 my ( $c, @path ) = @_;
317 my $path = dir( $c->config->{home}, @path );
318 if ( -d $path ) { return $path }
319 else { return file( $c->config->{home}, @path ) }
331 my ( $class, @arguments ) = @_;
333 unless ( $class->isa('Catalyst') ) {
335 Catalyst::Exception->throw(
336 message => qq/'$class' does not inherit from Catalyst/ );
339 if ( $class->arguments ) {
340 @arguments = ( @arguments, @{ $class->arguments } );
346 foreach (@arguments) {
350 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
352 elsif (/^-(\w+)=?(.*)$/) {
353 $flags->{ lc $1 } = $2;
356 push @{ $flags->{plugins} }, $_;
360 $class->setup_log( delete $flags->{log} );
361 $class->setup_plugins( delete $flags->{plugins} );
362 $class->setup_dispatcher( delete $flags->{dispatcher} );
363 $class->setup_engine( delete $flags->{engine} );
364 $class->setup_home( delete $flags->{home} );
366 for my $flag ( sort keys %{$flags} ) {
368 if ( my $code = $class->can( 'setup_' . $flag ) ) {
369 &$code( $class, delete $flags->{$flag} );
372 $class->log->warn(qq/Unknown flag "$flag"/);
376 $class->log->warn( "You are running an old helper script! "
377 . "Please update your scripts by regenerating the "
378 . "application and copying over the new scripts." )
379 if ( $ENV{CATALYST_SCRIPT_GEN}
380 && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::CATALYST_SCRIPT_GEN ) );
382 if ( $class->debug ) {
388 @plugins = grep { /^Catalyst::Plugin/ } @{"$class\::ISA"};
392 my $t = Text::SimpleTable->new(76);
393 $t->row($_) for @plugins;
394 $class->log->debug( "Loaded plugins:\n" . $t->draw );
397 my $dispatcher = $class->dispatcher;
398 my $engine = $class->engine;
399 my $home = $class->config->{home};
401 $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
402 $class->log->debug(qq/Loaded engine "$engine"/);
406 ? $class->log->debug(qq/Found home "$home"/)
407 : $class->log->debug(qq/Home "$home" doesn't exist/)
408 : $class->log->debug(q/Couldn't find home/);
413 no warnings qw/redefine/;
414 local *setup = sub { };
418 # Initialize our data structure
419 $class->components( {} );
421 $class->setup_components;
423 if ( $class->debug ) {
424 my $t = Text::SimpleTable->new( [ 65, 'Class' ], [ 8, 'Type' ] );
425 for my $comp ( sort keys %{ $class->components } ) {
426 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
427 $t->row( $comp, $type );
429 $class->log->debug( "Loaded components:\n" . $t->draw )
430 if ( keys %{ $class->components } );
433 # Add our self to components, since we are also a component
434 $class->components->{$class} = $class;
436 $class->setup_actions;
438 if ( $class->debug ) {
439 my $name = $class->config->{name} || 'Application';
440 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
442 $class->log->_flush() if $class->log->can('_flush');
445 =item $c->uri_for($path,[@args])
447 Merges path with $c->request->base for absolute uri's and with
448 $c->request->match for relative uri's, then returns a normalized
449 L<URI> object. If any args are passed, they are added at the end
455 my ( $c, $path, @args ) = @_;
456 my $base = $c->request->base->clone;
457 my $basepath = $base->path;
458 $basepath =~ s/\/$//;
460 my $match = $c->request->match;
462 # massage match, empty if absolute path
464 $match .= '/' if $match;
466 $match = '' if $path =~ /^\//;
469 # join args with '/', or a blank string
470 my $args = ( scalar @args ? '/' . join( '/', @args ) : '' );
471 return URI->new_abs( URI->new_abs( "$path$args", "$basepath$match" ),
477 =item $c->error($error, ...)
479 =item $c->error($arrayref)
481 Returns an arrayref containing error messages.
483 my @error = @{ $c->error };
487 $c->error('Something bad happened');
498 my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
499 push @{ $c->{error} }, @$error;
501 elsif ( defined $_[0] ) { $c->{error} = undef }
502 return $c->{error} || [];
507 Contains the engine instance.
508 Stringifies to the class.
512 Contains the logging object. Unless it is already set Catalyst sets this up with a
513 C<Catalyst::Log> object. To use your own log class:
515 $c->log( MyLogger->new );
516 $c->log->info("now logging with my own logger!");
518 Your log class should implement the methods described in the C<Catalyst::Log>
521 =item $c->plugin( $name, $class, @args )
523 Instant plugins for Catalyst.
524 Classdata accessor/mutator will be created, class loaded and instantiated.
526 MyApp->plugin( 'prototype', 'HTML::Prototype' );
528 $c->prototype->define_javascript_functions;
533 my ( $class, $name, $plugin, @args ) = @_;
536 if ( my $error = $UNIVERSAL::require::ERROR ) {
537 Catalyst::Exception->throw(
538 message => qq/Couldn't load instant plugin "$plugin", "$error"/ );
541 eval { $plugin->import };
542 $class->mk_classdata($name);
544 eval { $obj = $plugin->new(@args) };
547 Catalyst::Exception->throw( message =>
548 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
552 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
560 Returns a C<Catalyst::Request> object.
568 Returns a C<Catalyst::Response> object.
574 Contains the return value of the last executed action.
578 Returns a hashref containing all your data.
580 print $c->stash->{foo};
582 Keys may be set in the stash by assigning to the hash reference, or by passing
583 either a single hash reference or a list of key/value pairs as arguments.
587 $c->stash->{foo} ||= 'yada';
588 $c->stash( { moose => 'majestic', qux => 0 } );
589 $c->stash( bar => 1, gorch => 2 );
596 my $stash = @_ > 1 ? {@_} : $_[0];
597 while ( my ( $key, $val ) = each %$stash ) {
598 $c->{stash}->{$key} = $val;
604 =item $c->view($name)
606 Get a L<Catalyst::View> instance by name.
608 $c->view('Foo')->do_stuff;
613 my ( $c, $name ) = @_;
614 my $view = $c->comp("View::$name");
615 return $view if $view;
616 return $c->comp("V::$name");
619 =item $c->welcome_message
621 Returns the Catalyst welcome HTML page.
625 sub welcome_message {
627 my $name = $c->config->{name};
628 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
629 my $prefix = Catalyst::Utils::appprefix( ref $c );
630 $c->response->content_type('text/html; charset=utf-8');
632 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
633 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
634 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
636 <meta http-equiv="Content-Language" content="en" />
637 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
638 <title>$name on Catalyst $VERSION</title>
639 <style type="text/css">
642 background-color: #eee;
651 background-color: #ccc;
652 border: 1px solid #aaa;
653 -moz-border-radius: 10px;
658 font-family: verdana, tahoma, sans-serif;
661 font-family: verdana, tahoma, sans-serif;
664 text-decoration: none;
666 border-bottom: 1px dotted #bbb;
668 :link:hover, :visited:hover {
681 background-color: #fff;
682 border: 1px solid #aaa;
683 -moz-border-radius: 10px;
709 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
714 <img src="$logo" alt="Catalyst Logo" />
716 <p>Welcome to the wonderful world of Catalyst.
717 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
718 framework will make web development something you had
719 never expected it to be: Fun, rewarding and quick.</p>
720 <h2>What to do now?</h2>
721 <p>That really depends on what <b>you</b> want to do.
722 We do, however, provide you with a few starting points.</p>
723 <p>If you want to jump right into web development with Catalyst
724 you might want to check out the documentation.</p>
725 <pre><code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
726 perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual.pod">Catalyst::Manual</a></code></pre>
727 <h2>What to do next?</h2>
728 <p>Next it's time to write an actual application. Use the
729 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&mode=all">controllers</a>,
730 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&mode=all">models</a> and
731 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&mode=all">views</a>,
732 they can save you a lot of work.</p>
733 <pre><code>script/${prefix}_create.pl -help</code></pre>
734 <p>Also, be sure to check out the vast and growing
735 collection of <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3APlugin%3A%3A&mode=all">plugins for Catalyst on CPAN</a>,
736 you are likely to find what you need there.
740 <p>Catalyst has a very active community. Here are the main places to
741 get in touch with us.</p>
744 <a href="http://dev.catalyst.perl.org">Wiki</a>
747 <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
750 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
753 <h2>In conclusion</h2>
754 <p>The Catalyst team hopes you will enjoy using Catalyst as much
755 as we enjoyed making it. Please contact us if you have ideas
756 for improvement or other feedback.</p>
766 =head1 INTERNAL METHODS
770 =item $c->benchmark($coderef)
772 Takes a coderef with arguments and returns elapsed time as float.
774 my ( $elapsed, $status ) = $c->benchmark( sub { return 1 } );
775 $c->log->info( sprintf "Processing took %f seconds", $elapsed );
782 my $time = [gettimeofday];
783 my @return = &$code(@_);
784 my $elapsed = tv_interval $time;
785 return wantarray ? ( $elapsed, @return ) : $elapsed;
790 Contains the components.
792 =item $c->context_class($class)
794 Contains the context class.
798 Returns a hashref containing coderefs and execution counts.
799 (Needed for deep recursion detection)
803 Returns the actual forward depth.
807 Dispatch request to actions.
811 sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
813 =item $c->dispatcher_class($class)
815 Contains the dispatcher class.
819 Returns a list of 2-element array references (name, structure) pairs that will
820 be dumped on the error page in debug mode.
826 [ Request => $c->req ], [ Response => $c->res ], [ Stash => $c->stash ],;
829 =item $c->engine_class($class)
831 Contains the engine class.
833 =item $c->execute($class, $coderef)
835 Execute a coderef in given class and catch exceptions.
836 Errors are available via $c->error.
841 my ( $c, $class, $code ) = @_;
842 $class = $c->components->{$class} || $class;
844 my $callsub = ( caller(1) )[3];
849 $action = "/$action" unless $action =~ /\-\>/;
850 $c->counter->{"$code"}++;
852 if ( $c->counter->{"$code"} > $RECURSION ) {
853 my $error = qq/Deep recursion detected in "$action"/;
854 $c->log->error($error);
860 $action = "-> $action" if $callsub =~ /forward$/;
866 my ( $elapsed, @state ) =
867 $c->benchmark( $code, $class, $c, @{ $c->req->args } );
868 unless ( ( $code->name =~ /^_.*/ )
869 && ( !$c->config->{show_internal_actions} ) )
871 push @{ $c->{stats} }, [ $action, sprintf( '%fs', $elapsed ) ];
876 $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 );
881 if ( my $error = $@ ) {
883 if ( $error eq $DETACH ) { die $DETACH if $c->{depth} > 1 }
885 unless ( ref $error ) {
887 $error = qq/Caught exception "$error"/;
905 for my $error ( @{ $c->error } ) {
906 $c->log->error($error);
909 $c->finalize_uploads;
912 if ( $#{ $c->error } >= 0 ) {
916 $c->finalize_headers;
919 if ( $c->request->method eq 'HEAD' ) {
920 $c->response->body('');
925 return $c->response->status;
928 =item $c->finalize_body
934 sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
936 =item $c->finalize_cookies
942 sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
944 =item $c->finalize_error
950 sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
952 =item $c->finalize_headers
958 sub finalize_headers {
961 # Check if we already finalized headers
962 return if $c->response->{_finalized_headers};
965 if ( my $location = $c->response->redirect ) {
966 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
967 $c->response->header( Location => $location );
971 if ( $c->response->body && !$c->response->content_length ) {
972 $c->response->content_length( bytes::length( $c->response->body ) );
976 if ( $c->response->status =~ /^(1\d\d|[23]04)$/ ) {
977 $c->response->headers->remove_header("Content-Length");
978 $c->response->body('');
981 $c->finalize_cookies;
983 $c->engine->finalize_headers( $c, @_ );
986 $c->response->{_finalized_headers} = 1;
989 =item $c->finalize_output
991 An alias for finalize_body.
993 =item $c->finalize_read
995 Finalize the input after reading is complete.
999 sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1001 =item $c->finalize_uploads
1003 Finalize uploads. Cleans up any temporary files.
1007 sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1009 =item $c->get_action( $action, $namespace )
1011 Get an action in a given namespace.
1015 sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
1017 =item $c->get_actions( $action, $namespace )
1019 Get all actions of a given name in a namespace and all base namespaces.
1023 sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1025 =item handle_request( $class, @arguments )
1027 Handles the request.
1031 sub handle_request {
1032 my ( $class, @arguments ) = @_;
1034 # Always expect worst case!
1040 my $c = $class->prepare(@arguments);
1041 $c->{stats} = \@stats;
1043 return $c->finalize;
1046 if ( $class->debug ) {
1048 ( $elapsed, $status ) = $class->benchmark($handler);
1049 $elapsed = sprintf '%f', $elapsed;
1050 my $av = sprintf '%.3f',
1051 ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) );
1052 my $t = Text::SimpleTable->new( [ 64, 'Action' ], [ 9, 'Time' ] );
1054 for my $stat (@stats) { $t->row( $stat->[0], $stat->[1] ) }
1056 "Request took ${elapsed}s ($av/s)\n" . $t->draw );
1058 else { $status = &$handler }
1062 if ( my $error = $@ ) {
1064 $class->log->error(qq/Caught exception in engine "$error"/);
1068 $class->log->_flush() if $class->log->can('_flush');
1072 =item $c->prepare(@arguments)
1074 Turns the engine-specific request( Apache, CGI ... )
1075 into a Catalyst context .
1080 my ( $class, @arguments ) = @_;
1082 $class->context_class( ref $class || $class ) unless $class->context_class;
1083 my $c = $class->context_class->new(
1087 request => $class->request_class->new(
1090 body_parameters => {},
1092 headers => HTTP::Headers->new,
1094 query_parameters => {},
1100 response => $class->response_class->new(
1104 headers => HTTP::Headers->new(),
1113 # For on-demand data
1114 $c->request->{_context} = $c;
1115 $c->response->{_context} = $c;
1116 weaken( $c->request->{_context} );
1117 weaken( $c->response->{_context} );
1120 my $secs = time - $START || 1;
1121 my $av = sprintf '%.3f', $COUNT / $secs;
1122 $c->log->debug('**********************************');
1123 $c->log->debug("* Request $COUNT ($av/s) [$$]");
1124 $c->log->debug('**********************************');
1125 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
1128 $c->prepare_request(@arguments);
1129 $c->prepare_connection;
1130 $c->prepare_query_parameters;
1131 $c->prepare_headers;
1132 $c->prepare_cookies;
1136 $c->prepare_body unless $c->config->{parse_on_demand};
1139 my $method = $c->req->method || '';
1140 my $path = $c->req->path || '';
1141 my $address = $c->req->address || '';
1143 $c->log->debug(qq/"$method" request for "$path" from $address/)
1149 =item $c->prepare_action
1155 sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1157 =item $c->prepare_body
1159 Prepare message body.
1166 # Do we run for the first time?
1167 return if defined $c->request->{_body};
1169 # Initialize on-demand data
1170 $c->engine->prepare_body( $c, @_ );
1171 $c->prepare_parameters;
1172 $c->prepare_uploads;
1174 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1175 my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
1176 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1177 my $param = $c->req->body_parameters->{$key};
1178 my $value = defined($param) ? $param : '';
1180 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1182 $c->log->debug( "Body Parameters are:\n" . $t->draw );
1186 =item $c->prepare_body_chunk( $chunk )
1188 Prepare a chunk of data before sending it to HTTP::Body.
1192 sub prepare_body_chunk {
1194 $c->engine->prepare_body_chunk( $c, @_ );
1197 =item $c->prepare_body_parameters
1199 Prepare body parameters.
1203 sub prepare_body_parameters {
1205 $c->engine->prepare_body_parameters( $c, @_ );
1208 =item $c->prepare_connection
1214 sub prepare_connection {
1216 $c->engine->prepare_connection( $c, @_ );
1219 =item $c->prepare_cookies
1225 sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1227 =item $c->prepare_headers
1233 sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1235 =item $c->prepare_parameters
1241 sub prepare_parameters {
1243 $c->prepare_body_parameters;
1244 $c->engine->prepare_parameters( $c, @_ );
1247 =item $c->prepare_path
1249 Prepare path and base.
1253 sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1255 =item $c->prepare_query_parameters
1257 Prepare query parameters.
1261 sub prepare_query_parameters {
1264 $c->engine->prepare_query_parameters( $c, @_ );
1266 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1267 my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
1268 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1269 my $param = $c->req->query_parameters->{$key};
1270 my $value = defined($param) ? $param : '';
1272 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1274 $c->log->debug( "Query Parameters are:\n" . $t->draw );
1278 =item $c->prepare_read
1280 Prepare the input for reading.
1284 sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1286 =item $c->prepare_request
1288 Prepare the engine request.
1292 sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1294 =item $c->prepare_uploads
1300 sub prepare_uploads {
1303 $c->engine->prepare_uploads( $c, @_ );
1305 if ( $c->debug && keys %{ $c->request->uploads } ) {
1306 my $t = Text::SimpleTable->new(
1312 for my $key ( sort keys %{ $c->request->uploads } ) {
1313 my $upload = $c->request->uploads->{$key};
1314 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
1315 $t->row( $key, $u->filename, $u->type, $u->size );
1318 $c->log->debug( "File Uploads are:\n" . $t->draw );
1322 =item $c->prepare_write
1324 Prepare the output for writing.
1328 sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1330 =item $c->request_class($class)
1332 Contains the request class.
1334 =item $c->response_class($class)
1336 Contains the response class.
1338 =item $c->read( [$maxlength] )
1340 Read a chunk of data from the request body. This method is designed to be
1341 used in a while loop, reading $maxlength bytes on every call. $maxlength
1342 defaults to the size of the request if not specified.
1344 You have to set MyApp->config->{parse_on_demand} to use this directly.
1348 sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1356 sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1358 =item $c->set_action( $action, $code, $namespace, $attrs )
1360 Set an action in a given namespace.
1364 sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1366 =item $c->setup_actions($component)
1368 Setup actions for a component.
1372 sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1374 =item $c->setup_components
1380 sub setup_components {
1383 my $callback = sub {
1384 my ( $component, $context ) = @_;
1386 unless ( $component->isa('Catalyst::Component') ) {
1390 my $suffix = Catalyst::Utils::class2classsuffix($class);
1391 my $config = $class->config->{$suffix} || {};
1395 eval { $instance = $component->new( $context, $config ); };
1397 if ( my $error = $@ ) {
1401 Catalyst::Exception->throw( message =>
1402 qq/Couldn't instantiate component "$component", "$error"/ );
1405 Catalyst::Exception->throw( message =>
1406 qq/Couldn't instantiate component "$component", "new() didn't return a object"/
1408 unless ref $instance;
1413 Module::Pluggable::Fast->import(
1414 name => '_catalyst_components',
1416 "$class\::Controller", "$class\::C",
1417 "$class\::Model", "$class\::M",
1418 "$class\::View", "$class\::V"
1420 callback => $callback
1424 if ( my $error = $@ ) {
1428 Catalyst::Exception->throw(
1429 message => qq/Couldn't load components "$error"/ );
1432 for my $component ( $class->_catalyst_components($class) ) {
1433 $class->components->{ ref $component || $component } = $component;
1437 =item $c->setup_dispatcher
1441 sub setup_dispatcher {
1442 my ( $class, $dispatcher ) = @_;
1445 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1448 if ( $ENV{CATALYST_DISPATCHER} ) {
1449 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
1452 if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
1454 'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
1457 unless ($dispatcher) {
1458 $dispatcher = $class->dispatcher_class;
1461 $dispatcher->require;
1464 Catalyst::Exception->throw(
1465 message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
1468 # dispatcher instance
1469 $class->dispatcher( $dispatcher->new );
1472 =item $c->setup_engine
1477 my ( $class, $engine ) = @_;
1480 $engine = 'Catalyst::Engine::' . $engine;
1483 if ( $ENV{CATALYST_ENGINE} ) {
1484 $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
1487 if ( $ENV{ uc($class) . '_ENGINE' } ) {
1488 $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
1491 if ( !$engine && $ENV{MOD_PERL} ) {
1493 # create the apache method
1496 *{"$class\::apache"} = sub { shift->engine->apache };
1499 my ( $software, $version ) =
1500 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
1503 $version =~ s/(\.[^.]+)\./$1/g;
1505 if ( $software eq 'mod_perl' ) {
1507 if ( $version >= 1.99922 ) {
1508 $engine = 'Catalyst::Engine::Apache2::MP20';
1511 elsif ( $version >= 1.9901 ) {
1512 $engine = 'Catalyst::Engine::Apache2::MP19';
1515 elsif ( $version >= 1.24 ) {
1516 $engine = 'Catalyst::Engine::Apache::MP13';
1520 Catalyst::Exception->throw( message =>
1521 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
1524 # install the correct mod_perl handler
1525 if ( $version >= 1.9901 ) {
1526 *handler = sub : method {
1527 shift->handle_request(@_);
1531 *handler = sub ($$) { shift->handle_request(@_) };
1536 elsif ( $software eq 'Zeus-Perl' ) {
1537 $engine = 'Catalyst::Engine::Zeus';
1541 Catalyst::Exception->throw(
1542 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
1547 $engine = $class->engine_class;
1553 Catalyst::Exception->throw( message =>
1554 qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
1558 # check for old engines that are no longer compatible
1560 if ( $engine->isa('Catalyst::Engine::Apache')
1561 && !Catalyst::Engine::Apache->VERSION )
1566 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
1567 && Catalyst::Engine::Server->VERSION le '0.02' )
1572 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
1573 && $engine->VERSION eq '0.01' )
1578 elsif ($engine->isa('Catalyst::Engine::Zeus')
1579 && $engine->VERSION eq '0.01' )
1585 Catalyst::Exception->throw( message =>
1586 qq/Engine "$engine" is not supported by this version of Catalyst/
1591 $class->engine( $engine->new );
1594 =item $c->setup_home
1599 my ( $class, $home ) = @_;
1601 if ( $ENV{CATALYST_HOME} ) {
1602 $home = $ENV{CATALYST_HOME};
1605 if ( $ENV{ uc($class) . '_HOME' } ) {
1606 $home = $ENV{ uc($class) . '_HOME' };
1610 $home = Catalyst::Utils::home($class);
1614 $class->config->{home} ||= $home;
1615 $class->config->{root} ||= dir($home)->subdir('root');
1624 my ( $class, $debug ) = @_;
1626 unless ( $class->log ) {
1627 $class->log( Catalyst::Log->new );
1630 my $app_flag = Catalyst::Utils::class2env($class) . '_DEBUG';
1633 ( defined( $ENV{CATALYST_DEBUG} ) || defined( $ENV{$app_flag} ) )
1634 ? ( $ENV{CATALYST_DEBUG} || $ENV{$app_flag} )
1639 *{"$class\::debug"} = sub { 1 };
1640 $class->log->debug('Debug messages enabled');
1644 =item $c->setup_plugins
1649 my ( $class, $plugins ) = @_;
1652 for my $plugin ( reverse @$plugins ) {
1654 $plugin = "Catalyst::Plugin::$plugin";
1659 Catalyst::Exception->throw(
1660 message => qq/Couldn't load plugin "$plugin", "$@"/ );
1665 unshift @{"$class\::ISA"}, $plugin;
1670 =item $c->write( $data )
1672 Writes $data to the output stream. When using this method directly, you will
1673 need to manually set the Content-Length header to the length of your output
1681 # Finalize headers if someone manually writes output
1682 $c->finalize_headers;
1684 return $c->engine->write( $c, @_ );
1689 Returns the Catalyst version number. mostly useful for powered by messages
1690 in template systems.
1694 sub version { return $Catalyst::VERSION }
1698 =head1 INTERNAL ACTIONS
1700 Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>
1701 C<_ACTION> and C<_END>, these are by default not shown in the private
1704 But you can deactivate this with a config parameter.
1706 MyApp->config->{show_internal_actions} = 1;
1708 =head1 CASE SENSITIVITY
1710 By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> becomes
1713 But you can activate case sensitivity with a config parameter.
1715 MyApp->config->{case_sensitive} = 1;
1717 So C<MyApp::C::Foo::Bar> becomes C</Foo/Bar>.
1719 =head1 ON-DEMAND PARSER
1721 The request body is usually parsed at the beginning of a request,
1722 but if you want to handle input yourself or speed things up a bit
1723 you can enable on-demand parsing with a config parameter.
1725 MyApp->config->{parse_on_demand} = 1;
1727 =head1 PROXY SUPPORT
1729 Many production servers operate using the common double-server approach, with
1730 a lightweight frontend web server passing requests to a larger backend
1731 server. An application running on the backend server must deal with two
1732 problems: the remote user always appears to be '127.0.0.1' and the server's
1733 hostname will appear to be 'localhost' regardless of the virtual host the
1734 user connected through.
1736 Catalyst will automatically detect this situation when you are running both
1737 the frontend and backend servers on the same machine. The following changes
1738 are made to the request.
1740 $c->req->address is set to the user's real IP address, as read from the
1741 HTTP_X_FORWARDED_FOR header.
1743 The host value for $c->req->base and $c->req->uri is set to the real host,
1744 as read from the HTTP_X_FORWARDED_HOST header.
1746 Obviously, your web server must support these 2 headers for this to work.
1748 In a more complex server farm environment where you may have your frontend
1749 proxy server(s) on different machines, you will need to set a configuration
1750 option to tell Catalyst to read the proxied data from the headers.
1752 MyApp->config->{using_frontend_proxy} = 1;
1754 If you do not wish to use the proxy support at all, you may set:
1756 MyApp->config->{ignore_frontend_proxy} = 1;
1758 =head1 THREAD SAFETY
1760 Catalyst has been tested under Apache 2's threading mpm_worker, mpm_winnt,
1761 and the standalone forking HTTP server on Windows. We believe the Catalyst
1762 core to be thread-safe.
1764 If you plan to operate in a threaded environment, remember that all other
1765 modules you are using must also be thread-safe. Some modules, most notably
1766 DBD::SQLite, are not thread-safe.
1772 Join #catalyst on irc.perl.org.
1776 http://lists.rawmode.org/mailman/listinfo/catalyst
1777 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1781 http://catalyst.perl.org
1787 =item L<Catalyst::Manual> - The Catalyst Manual
1789 =item L<Catalyst::Engine> - Core Engine
1791 =item L<Catalyst::Log> - The Log Class.
1793 =item L<Catalyst::Request> - The Request Object
1795 =item L<Catalyst::Response> - The Response Object
1797 =item L<Catalyst::Test> - The test suite.
1865 Sebastian Riedel, C<sri@oook.de>
1869 This library is free software, you can redistribute it and/or modify it under
1870 the same terms as Perl itself.