4 use base 'Catalyst::Component';
6 use UNIVERSAL::require;
7 use Catalyst::Exception;
10 use Catalyst::Request::Upload;
11 use Catalyst::Response;
13 use Catalyst::Controller;
16 use Text::SimpleTable;
18 use Path::Class::File;
19 use Time::HiRes qw/gettimeofday tv_interval/;
21 use Scalar::Util qw/weaken blessed/;
22 use Tree::Simple qw/use_weak_refs/;
23 use Tree::Simple::Visitor::FindByUID;
28 __PACKAGE__->mk_accessors(
29 qw/counter request response state action stack namespace stats/
32 attributes->import( __PACKAGE__, \&namespace, 'lvalue' );
34 sub depth { scalar @{ shift->stack || [] }; }
41 # For backwards compatibility
42 *finalize_output = \&finalize_body;
47 our $RECURSION = 1000;
48 our $DETACH = "catalyst_detach\n";
50 require Module::Pluggable::Fast;
52 # Helper script generation
53 our $CATALYST_SCRIPT_GEN = 27;
55 __PACKAGE__->mk_classdata($_)
56 for qw/components arguments dispatcher engine log dispatcher_class
57 engine_class context_class request_class response_class setup_finished/;
59 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
60 __PACKAGE__->engine_class('Catalyst::Engine::CGI');
61 __PACKAGE__->request_class('Catalyst::Request');
62 __PACKAGE__->response_class('Catalyst::Response');
64 our $VERSION = '5.67';
67 my ( $class, @arguments ) = @_;
69 # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
71 return unless $class eq 'Catalyst';
73 my $caller = caller(0);
75 unless ( $caller->isa('Catalyst') ) {
77 push @{"$caller\::ISA"}, $class, 'Catalyst::Controller';
80 $caller->arguments( [@arguments] );
86 Catalyst - The Elegant MVC Web Application Framework
90 # use the helper to start a new application
93 # add models, views, controllers
94 script/myapp_create.pl model Database DBIC dbi:SQLite:/path/to/db
95 script/myapp_create.pl view TT TT
96 script/myapp_create.pl controller Search
98 # built in testserver -- use -r to restart automatically on changes
99 script/myapp_server.pl
101 # command line testing interface
102 script/myapp_test.pl /yada
105 use Catalyst qw/-Debug/; # include plugins here as well
107 sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
108 my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
109 $c->stash->{template} = 'foo.tt'; # set the template
110 # lookup something from db -- stash vars are passed to TT
112 MyApp::Model::Database::Foo->search( { country => $args[0] } );
113 if ( $c->req->params->{bar} ) { # access GET or POST parameters
114 $c->forward( 'bar' ); # process another action
115 # do something else after forward returns
119 # The foo.tt TT template can use the stash data from the database
120 [% WHILE (item = data.next) %]
124 # called for /bar/of/soap, /bar/of/soap/10, etc.
125 sub bar : Path('/bar/of/soap') { ... }
127 # called for all actions, from the top-most controller downwards
129 my ( $self, $c ) = @_;
131 $c->res->redirect( '/login' ); # require login
132 return 0; # abort request and go immediately to end()
134 return 1; # success; carry on to next action
137 # called after all actions are finished
139 my ( $self, $c ) = @_;
140 if ( scalar @{ $c->error } ) { ... } # handle errors
141 return if $c->res->body; # already have a response
142 $c->forward( 'MyApp::View::TT' ); # render template
145 ### in MyApp/Controller/Foo.pm
146 # called for /foo/bar
147 sub bar : Local { ... }
149 # called for /blargle
150 sub blargle : Global { ... }
152 # an index action matches /foo, but not /foo/1, etc.
153 sub index : Private { ... }
155 ### in MyApp/Controller/Foo/Bar.pm
156 # called for /foo/bar/baz
157 sub baz : Local { ... }
159 # first MyApp auto is called, then Foo auto, then this
160 sub auto : Private { ... }
162 # powerful regular expression paths are also possible
163 sub details : Regex('^product/(\w+)/details$') {
164 my ( $self, $c ) = @_;
165 # extract the (\w+) from the URI
166 my $product = $c->req->snippets->[0];
169 See L<Catalyst::Manual::Intro> for additional information.
173 The key concept of Catalyst is DRY (Don't Repeat Yourself).
175 See L<Catalyst::Manual> for more documentation.
177 Catalyst plugins can be loaded by naming them as arguments to the "use
178 Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the
179 plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes
182 use Catalyst qw/My::Module/;
184 If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
185 fully qualify the name by using a unary plus:
189 +Fully::Qualified::Plugin::Name
192 Special flags like C<-Debug> and C<-Engine> can also be specified as
193 arguments when Catalyst is loaded:
195 use Catalyst qw/-Debug My::Module/;
197 The position of plugins and flags in the chain is important, because
198 they are loaded in exactly the order in which they appear.
200 The following flags are supported:
204 Enables debug output.
208 Forces Catalyst to use a specific engine. Omit the
209 C<Catalyst::Engine::> prefix of the engine name, i.e.:
211 use Catalyst qw/-Engine=CGI/;
215 Forces Catalyst to use a specific home directory, e.g.:
217 use Catalyst qw[-Home=/usr/sri];
225 =head2 INFORMATION ABOUT THE CURRENT REQUEST
229 Returns a L<Catalyst::Action> object for the current action, which
230 stringifies to the action name. See L<Catalyst::Action>.
234 Returns the namespace of the current action, i.e., the uri prefix
235 corresponding to the controller of the current action. For example:
237 # in Controller::Foo::Bar
238 $c->namespace; # returns 'foo/bar';
244 Returns the current L<Catalyst::Request> object. See
245 L<Catalyst::Request>.
247 =head2 PROCESSING AND RESPONSE TO THE CURRENT REQUEST
249 =head2 $c->forward( $action [, \@arguments ] )
251 =head2 $c->forward( $class, $method, [, \@arguments ] )
253 Forwards processing to a private action. If you give a class name but no
254 method, C<process()> is called. You may also optionally pass arguments
255 in an arrayref. The action will receive the arguments in C<@_> and
256 C<$c-E<gt>req-E<gt>args>. Upon returning from the function,
257 C<$c-E<gt>req-E<gt>args> will be restored to the previous values.
259 Any data C<return>ed from the action forwarded to, will be returned by the
262 my $foodata = $c->forward('/foo');
263 $c->forward('index');
264 $c->forward(qw/MyApp::Model::DBIC::Foo do_stuff/);
265 $c->forward('MyApp::View::TT');
267 Note that forward implies an C<<eval { }>> around the call (well, actually
268 C<execute> does), thus de-fatalizing all 'dies' within the called action. If
269 you want C<die> to propagate you need to do something like:
272 die $c->error if $c->error;
274 Or make sure to always return true values from your actions and write your code
277 $c->forward('foo') || return;
281 sub forward { my $c = shift; $c->dispatcher->forward( $c, @_ ) }
283 =head2 $c->detach( $action [, \@arguments ] )
285 =head2 $c->detach( $class, $method, [, \@arguments ] )
287 The same as C<forward>, but doesn't return.
291 sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
295 =head2 $c->error($error, ...)
297 =head2 $c->error($arrayref)
299 Returns an arrayref containing error messages. If Catalyst encounters an
300 error while processing a request, it stores the error in $c->error. This
301 method should not be used to store non-fatal error messages.
303 my @error = @{ $c->error };
307 $c->error('Something bad happened');
314 my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
315 croak @$error unless ref $c;
316 push @{ $c->{error} }, @$error;
318 elsif ( defined $_[0] ) { $c->{error} = undef }
319 return $c->{error} || [];
322 =head2 $c->clear_errors
324 Clear errors. You probably don't want to clear the errors unless you are
325 implementing a custom error screen.
327 This is equivalent to running
342 Returns the current L<Catalyst::Response> object.
346 Returns a hashref to the stash, which may be used to store data and pass
347 it between components during a request. You can also set hash keys by
348 passing arguments. The stash is automatically sent to the view. The
349 stash is cleared at the end of a request; it cannot be used for
352 $c->stash->{foo} = $bar;
353 $c->stash( { moose => 'majestic', qux => 0 } );
354 $c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref
356 # stash is automatically passed to the view for use in a template
357 $c->forward( 'MyApp::V::TT' );
364 my $stash = @_ > 1 ? {@_} : $_[0];
365 while ( my ( $key, $val ) = each %$stash ) {
366 $c->{stash}->{$key} = $val;
374 Contains the return value of the last executed action.
380 my ( $c, @names ) = @_;
382 foreach my $name (@names) {
383 foreach my $component ( keys %{ $c->components } ) {
384 return $c->components->{$component} if $component =~ /$name/i;
391 # try explicit component names
393 my ( $c, @names ) = @_;
395 foreach my $try (@names) {
396 return $c->components->{$try} if ( exists $c->components->{$try} );
402 # like component, but try just these prefixes before regex searching,
403 # and do not try to return "sort keys %{ $c->components }"
405 my ( $c, $name, @prefixes ) = @_;
407 my $appclass = ref $c || $c;
409 my @names = map { "${appclass}::${_}::${name}" } @prefixes;
411 my $comp = $c->_comp_explicit(@names);
412 return $comp if defined($comp);
413 $comp = $c->_comp_search($name);
417 # Find possible names for a prefix
420 my ( $c, @prefixes ) = @_;
422 my $appclass = ref $c || $c;
424 my @pre = map { "${appclass}::${_}::" } @prefixes;
428 COMPONENT: foreach my $comp ($c->component) {
429 foreach my $p (@pre) {
430 if ($comp =~ s/^$p//) {
440 # Return a component if only one matches.
442 my ( $c, @prefixes ) = @_;
444 my $appclass = ref $c || $c;
446 my ( $comp, $rest ) =
447 map { $c->_comp_search("^${appclass}::${_}::") } @prefixes;
448 return $comp unless $rest;
451 # Filter a component before returning by calling ACCEPT_CONTEXT if available
452 sub _filter_component {
453 my ( $c, $comp, @args ) = @_;
454 if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
455 return $comp->ACCEPT_CONTEXT( $c, @args );
457 else { return $comp }
460 =head2 COMPONENT ACCESSORS
462 =head2 $c->comp($name)
464 =head2 $c->component($name)
466 Gets a component object by name. This method is no longer recommended,
467 unless you want to get a specific component by full
468 class. C<$c-E<gt>controller>, C<$c-E<gt>model>, and C<$c-E<gt>view>
469 should be used instead.
480 my $appclass = ref $c || $c;
483 $name, "${appclass}::${name}",
484 map { "${appclass}::${_}::${name}" }
485 qw/Model M Controller C View V/
488 my $comp = $c->_comp_explicit(@names);
489 return $c->_filter_component( $comp, @_ ) if defined($comp);
491 $comp = $c->_comp_search($name);
492 return $c->_filter_component( $comp, @_ ) if defined($comp);
495 return sort keys %{ $c->components };
498 =head2 $c->controller($name)
500 Gets a L<Catalyst::Controller> instance by name.
502 $c->controller('Foo')->do_stuff;
504 If name is omitted, will return the controller for the dispatched action.
509 my ( $c, $name, @args ) = @_;
510 return $c->_filter_component( $c->_comp_prefixes( $name, qw/Controller C/ ),
513 return $c->component( $c->action->class );
516 =head2 $c->controllers
518 Returns the available names which can be passed to $c->controller
524 return $c->_comp_names(qw/Controller C/);
527 =head2 $c->model($name)
529 Gets a L<Catalyst::Model> instance by name.
531 $c->model('Foo')->do_stuff;
533 If the name is omitted, it will look for a config setting 'default_model',
534 or check if there is only one model, and forward to it if that's the case.
539 my ( $c, $name, @args ) = @_;
540 return $c->_filter_component( $c->_comp_prefixes( $name, qw/Model M/ ),
543 return $c->component( $c->config->{default_model} )
544 if $c->config->{default_model};
545 return $c->_filter_component( $c->_comp_singular(qw/Model M/), @args );
551 Returns the available names which can be passed to $c->model
557 return $c->_comp_names(qw/Model M/);
560 =head2 $c->view($name)
562 Gets a L<Catalyst::View> instance by name.
564 $c->view('Foo')->do_stuff;
566 If the name is omitted, it will look for a config setting 'default_view',
567 or check if there is only one view, and forward to it if that's the case.
572 my ( $c, $name, @args ) = @_;
573 return $c->_filter_component( $c->_comp_prefixes( $name, qw/View V/ ),
576 return $c->component( $c->config->{default_view} )
577 if $c->config->{default_view};
578 return $c->_filter_component( $c->_comp_singular(qw/View V/) );
583 Returns the available names which can be passed to $c->view
589 return $c->_comp_names(qw/View V/);
592 =head2 Class data and helper classes
596 Returns or takes a hashref containing the application's configuration.
598 __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } );
600 You can also use a L<YAML> config file like myapp.yml in your
601 applications home directory.
604 db: dsn:SQLite:foo.db
611 $c->log->warn("Setting config after setup has been run is not a good idea.")
612 if ( @_ and $c->setup_finished );
614 $c->NEXT::config(@_);
619 Overload to enable debug messages (same as -Debug option).
625 =head2 $c->dispatcher
627 Returns the dispatcher instance. Stringifies to class name. See
628 L<Catalyst::Dispatcher>.
632 Returns the engine instance. Stringifies to the class name. See
637 Returns the logging object instance. Unless it is already set, Catalyst sets
638 this up with a L<Catalyst::Log> object. To use your own log class, set the
639 logger with the C<< __PACKAGE__->log >> method prior to calling
640 C<< __PACKAGE__->setup >>.
642 __PACKAGE__->log( MyLogger->new );
647 $c->log->info( 'Now logging with my own logger!' );
649 Your log class should implement the methods described in the
650 L<Catalyst::Log> man page.
654 =head2 UTILITY METHODS
656 =head2 $c->path_to(@path)
658 Merges C<@path> with C<$c-E<gt>config-E<gt>{home}> and returns a
659 L<Path::Class> object.
663 $c->path_to( 'db', 'sqlite.db' );
668 my ( $c, @path ) = @_;
669 my $path = Path::Class::Dir->new( $c->config->{home}, @path );
670 if ( -d $path ) { return $path }
671 else { return Path::Class::File->new( $c->config->{home}, @path ) }
674 =head2 $c->plugin( $name, $class, @args )
676 Helper method for plugins. It creates a classdata accessor/mutator and
677 loads and instantiates the given class.
679 MyApp->plugin( 'prototype', 'HTML::Prototype' );
681 $c->prototype->define_javascript_functions;
686 my ( $class, $name, $plugin, @args ) = @_;
687 $class->_register_plugin( $plugin, 1 );
689 eval { $plugin->import };
690 $class->mk_classdata($name);
692 eval { $obj = $plugin->new(@args) };
695 Catalyst::Exception->throw( message =>
696 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
700 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
706 Initializes the dispatcher and engine, loads any plugins, and loads the
707 model, view, and controller components. You may also specify an array
708 of plugins to load here, if you choose to not load them in the C<use
712 MyApp->setup( qw/-Debug/ );
717 my ( $class, @arguments ) = @_;
719 unless ( $class->isa('Catalyst') ) {
721 Catalyst::Exception->throw(
722 message => qq/'$class' does not inherit from Catalyst/ );
725 if ( $class->arguments ) {
726 @arguments = ( @arguments, @{ $class->arguments } );
732 foreach (@arguments) {
736 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
738 elsif (/^-(\w+)=?(.*)$/) {
739 $flags->{ lc $1 } = $2;
742 push @{ $flags->{plugins} }, $_;
746 $class->setup_home( delete $flags->{home} );
748 $class->setup_log( delete $flags->{log} );
749 $class->setup_plugins( delete $flags->{plugins} );
750 $class->setup_dispatcher( delete $flags->{dispatcher} );
751 $class->setup_engine( delete $flags->{engine} );
753 for my $flag ( sort keys %{$flags} ) {
755 if ( my $code = $class->can( 'setup_' . $flag ) ) {
756 &$code( $class, delete $flags->{$flag} );
759 $class->log->warn(qq/Unknown flag "$flag"/);
764 <<"EOF") if ( $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::CATALYST_SCRIPT_GEN ) );
765 You are running an old script!
767 Please update by running (this will overwrite existing files):
768 catalyst.pl -force -scripts $class
770 or (this will not overwrite existing files):
771 catalyst.pl -scripts $class
774 if ( $class->debug ) {
781 map { $_ . ' ' . ( $_->VERSION || '' ) }
782 grep { /^Catalyst::Plugin/ } @{"$class\::ISA"};
786 my $t = Text::SimpleTable->new(76);
787 $t->row($_) for @plugins;
788 $class->log->debug( "Loaded plugins:\n" . $t->draw );
791 my $dispatcher = $class->dispatcher;
792 my $engine = $class->engine;
793 my $home = $class->config->{home};
795 $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
796 $class->log->debug(qq/Loaded engine "$engine"/);
800 ? $class->log->debug(qq/Found home "$home"/)
801 : $class->log->debug(qq/Home "$home" doesn't exist/)
802 : $class->log->debug(q/Couldn't find home/);
807 no warnings qw/redefine/;
808 local *setup = sub { };
812 # Initialize our data structure
813 $class->components( {} );
815 $class->setup_components;
817 if ( $class->debug ) {
818 my $t = Text::SimpleTable->new( [ 65, 'Class' ], [ 8, 'Type' ] );
819 for my $comp ( sort keys %{ $class->components } ) {
820 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
821 $t->row( $comp, $type );
823 $class->log->debug( "Loaded components:\n" . $t->draw )
824 if ( keys %{ $class->components } );
827 # Add our self to components, since we are also a component
828 $class->components->{$class} = $class;
830 $class->setup_actions;
832 if ( $class->debug ) {
833 my $name = $class->config->{name} || 'Application';
834 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
836 $class->log->_flush() if $class->log->can('_flush');
838 $class->setup_finished(1);
841 =head2 $c->uri_for( $path, @args?, \%query_values? )
843 Merges path with C<$c-E<gt>request-E<gt>base> for absolute uri's and
844 with C<$c-E<gt>namespace> for relative uri's, then returns a
845 normalized L<URI> object. If any args are passed, they are added at the
846 end of the path. If the last argument to uri_for is a hash reference,
847 it is assumed to contain GET parameter key/value pairs, which will be
848 appended to the URI in standard fashion.
853 my ( $c, $path, @args ) = @_;
854 my $base = $c->request->base->clone;
855 my $basepath = $base->path;
856 $basepath =~ s/\/$//;
858 my $namespace = $c->namespace;
860 # massage namespace, empty if absolute path
861 $namespace =~ s/^\///;
862 $namespace .= '/' if $namespace;
864 $namespace = '' if $path =~ /^\//;
868 ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
870 for my $value ( values %$params ) {
\r
871 my $isa_ref = ref $value;
\r
872 if( $isa_ref and $isa_ref ne 'ARRAY' ) {
\r
873 croak( "Non-array reference ($isa_ref) passed to uri_for()" );
\r
875 utf8::encode( $_ ) for $isa_ref ? @$value : $value;
\r
878 # join args with '/', or a blank string
879 my $args = ( scalar @args ? '/' . join( '/', @args ) : '' );
880 $args =~ s/^\/// unless $path;
882 URI->new_abs( URI->new_abs( "$path$args", "$basepath$namespace" ), $base )
884 $res->query_form(%$params);
888 =head2 $c->welcome_message
890 Returns the Catalyst welcome HTML page.
894 sub welcome_message {
896 my $name = $c->config->{name};
897 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
898 my $prefix = Catalyst::Utils::appprefix( ref $c );
899 $c->response->content_type('text/html; charset=utf-8');
901 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
902 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
903 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
905 <meta http-equiv="Content-Language" content="en" />
906 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
907 <title>$name on Catalyst $VERSION</title>
908 <style type="text/css">
911 background-color: #eee;
920 background-color: #ccc;
921 border: 1px solid #aaa;
922 -moz-border-radius: 10px;
927 font-family: verdana, tahoma, sans-serif;
930 font-family: verdana, tahoma, sans-serif;
933 text-decoration: none;
935 border-bottom: 1px dotted #bbb;
937 :link:hover, :visited:hover {
950 background-color: #fff;
951 border: 1px solid #aaa;
952 -moz-border-radius: 10px;
978 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
983 <img src="$logo" alt="Catalyst Logo" />
985 <p>Welcome to the wonderful world of Catalyst.
986 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
987 framework will make web development something you had
988 never expected it to be: Fun, rewarding, and quick.</p>
989 <h2>What to do now?</h2>
990 <p>That really depends on what <b>you</b> want to do.
991 We do, however, provide you with a few starting points.</p>
992 <p>If you want to jump right into web development with Catalyst
993 you might want to check out the documentation.</p>
994 <pre><code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
995 perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
996 perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual.pod">Catalyst::Manual</a></code></pre>
997 <h2>What to do next?</h2>
998 <p>Next it's time to write an actual application. Use the
999 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&mode=all">controllers</a>,
1000 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&mode=all">models</a>, and
1001 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&mode=all">views</a>;
1002 they can save you a lot of work.</p>
1003 <pre><code>script/${prefix}_create.pl -help</code></pre>
1004 <p>Also, be sure to check out the vast and growing
1005 collection of <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3APlugin%3A%3A&mode=all">plugins for Catalyst on CPAN</a>;
1006 you are likely to find what you need there.
1010 <p>Catalyst has a very active community. Here are the main places to
1011 get in touch with us.</p>
1014 <a href="http://dev.catalyst.perl.org">Wiki</a>
1017 <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
1020 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
1023 <h2>In conclusion</h2>
1024 <p>The Catalyst team hopes you will enjoy using Catalyst as much
1025 as we enjoyed making it. Please contact us if you have ideas
1026 for improvement or other feedback.</p>
1034 =head1 INTERNAL METHODS
1036 These methods are not meant to be used by end users.
1038 =head2 $c->components
1040 Returns a hash of components.
1042 =head2 $c->context_class
1044 Returns or sets the context class.
1048 Returns a hashref containing coderefs and execution counts (needed for
1049 deep recursion detection).
1053 Returns the number of actions on the current internal execution stack.
1057 Dispatches a request to actions.
1061 sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
1063 =head2 $c->dispatcher_class
1065 Returns or sets the dispatcher class.
1067 =head2 $c->dump_these
1069 Returns a list of 2-element array references (name, structure) pairs
1070 that will be dumped on the error page in debug mode.
1076 [ Request => $c->req ], [ Response => $c->res ], [ Stash => $c->stash ],;
1079 =head2 $c->engine_class
1081 Returns or sets the engine class.
1083 =head2 $c->execute( $class, $coderef )
1085 Execute a coderef in given class and catch exceptions. Errors are available
1091 my ( $c, $class, $code ) = @_;
1092 $class = $c->component($class) || $class;
1095 if ( $c->depth >= $RECURSION ) {
1096 my $action = "$code";
1097 $action = "/$action" unless $action =~ /\-\>/;
1098 my $error = qq/Deep recursion detected calling "$action"/;
1099 $c->log->error($error);
1105 my $stats_info = $c->_stats_start_execute( $code );
1107 push( @{ $c->stack }, $code );
1109 eval { $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 ) };
1111 $c->_stats_finish_execute( $stats_info );
1113 my $last = ${ $c->stack }[-1];
1114 pop( @{ $c->stack } );
1116 if ( my $error = $@ ) {
1117 if ( $error eq $DETACH ) { die $DETACH if $c->depth > 1 }
1119 unless ( ref $error ) {
1121 my $class = $last->class;
1122 my $name = $last->name;
1123 $error = qq/Caught exception in $class->$name "$error"/;
1132 sub _stats_start_execute {
1133 my ( $c, $code ) = @_;
1135 return unless $c->debug;
1137 my $action = "$code";
1139 $action = "/$action" unless $action =~ /\-\>/;
1140 $c->counter->{"$code"}++;
1142 # determine if the call was the result of a forward
1143 # this is done by walking up the call stack and looking for a calling
1144 # sub of Catalyst::forward before the eval
1146 for my $index ( 2 .. 11 ) {
1148 if ( ( caller($index) )[0] eq 'Catalyst'
1149 && ( caller($index) )[3] eq '(eval)' );
1151 if ( ( caller($index) )[3] =~ /forward$/ ) {
1152 $callsub = ( caller($index) )[3];
1153 $action = "-> $action";
1158 my $node = Tree::Simple->new(
1161 elapsed => undef, # to be filled in later
1165 $node->setUID( "$code" . $c->counter->{"$code"} );
1167 unless ( ( $code->name =~ /^_.*/ )
1168 && ( !$c->config->{show_internal_actions} ) )
1170 # is this a root-level call or a forwarded call?
1171 if ( $callsub =~ /forward$/ ) {
1173 # forward, locate the caller
1174 if ( my $parent = $c->stack->[-1] ) {
1175 my $visitor = Tree::Simple::Visitor::FindByUID->new;
1176 $visitor->searchForUID(
1177 "$parent" . $c->counter->{"$parent"} );
1178 $c->stats->accept($visitor);
1179 if ( my $result = $visitor->getResult ) {
1180 $result->addChild($node);
1185 # forward with no caller may come from a plugin
1186 $c->stats->addChild($node);
1192 $c->stats->addChild($node);
1196 my $start = [gettimeofday];
1197 my $elapsed = tv_interval($start);
1201 elapsed => $elapsed,
1207 sub _stats_finish_execute {
1208 my ( $c, $info ) = @_;
1210 return unless $c->debug;
1212 my ( $code, $start, $elapsed ) = @{ $info }{qw/code start elapsed/};
1214 unless ( ( $code->name =~ /^_.*/ )
1215 && ( !$c->config->{show_internal_actions} ) )
1218 # FindByUID uses an internal die, so we save the existing error
1221 # locate the node in the tree and update the elapsed time
1222 my $visitor = Tree::Simple::Visitor::FindByUID->new;
1223 $visitor->searchForUID( "$code" . $c->counter->{"$code"} );
1224 $c->stats->accept($visitor);
1225 if ( my $result = $visitor->getResult ) {
1226 my $value = $result->getNodeValue;
1227 $value->{elapsed} = sprintf( '%fs', $elapsed );
1228 $result->setNodeValue($value);
1232 $@ = $error || undef;
1236 =head2 $c->_localize_fields( sub { }, \%keys );
1240 sub _localize_fields {
1241 my ( $c, $localized, $code ) = ( @_ );
1243 my $request = delete $localized->{request} || {};
1244 my $response = delete $localized->{response} || {};
1246 local @{ $c }{ keys %$localized } = values %$localized;
1247 local @{ $c->request }{ keys %$request } = values %$request;
1248 local @{ $c->response }{ keys %$response } = values %$response;
1255 Finalizes the request.
1262 for my $error ( @{ $c->error } ) {
1263 $c->log->error($error);
1266 # Allow engine to handle finalize flow (for POE)
1267 if ( $c->engine->can('finalize') ) {
1268 $c->engine->finalize( $c );
1272 $c->finalize_uploads;
1275 if ( $#{ $c->error } >= 0 ) {
1279 $c->finalize_headers;
1282 if ( $c->request->method eq 'HEAD' ) {
1283 $c->response->body('');
1289 return $c->response->status;
1292 =head2 $c->finalize_body
1298 sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1300 =head2 $c->finalize_cookies
1306 sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
1308 =head2 $c->finalize_error
1314 sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1316 =head2 $c->finalize_headers
1322 sub finalize_headers {
1325 # Check if we already finalized headers
1326 return if $c->response->{_finalized_headers};
1329 if ( my $location = $c->response->redirect ) {
1330 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
1331 $c->response->header( Location => $location );
1335 if ( $c->response->body && !$c->response->content_length ) {
1337 # get the length from a filehandle
1338 if ( blessed( $c->response->body ) && $c->response->body->can('read') )
1340 if ( my $stat = stat $c->response->body ) {
1341 $c->response->content_length( $stat->size );
1344 $c->log->warn('Serving filehandle without a content-length');
1348 $c->response->content_length( bytes::length( $c->response->body ) );
1353 if ( $c->response->status =~ /^(1\d\d|[23]04)$/ ) {
1354 $c->response->headers->remove_header("Content-Length");
1355 $c->response->body('');
1358 $c->finalize_cookies;
1360 $c->engine->finalize_headers( $c, @_ );
1363 $c->response->{_finalized_headers} = 1;
1366 =head2 $c->finalize_output
1368 An alias for finalize_body.
1370 =head2 $c->finalize_read
1372 Finalizes the input after reading is complete.
1376 sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1378 =head2 $c->finalize_uploads
1380 Finalizes uploads. Cleans up any temporary files.
1384 sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1386 =head2 $c->get_action( $action, $namespace )
1388 Gets an action in a given namespace.
1392 sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
1394 =head2 $c->get_actions( $action, $namespace )
1396 Gets all actions of a given name in a namespace and all parent
1401 sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1403 =head2 $c->handle_request( $class, @arguments )
1405 Called to handle each HTTP request.
1409 sub handle_request {
1410 my ( $class, @arguments ) = @_;
1412 # Always expect worst case!
1415 my $stats = ( $class->debug ) ? Tree::Simple->new: q{};
1418 my $c = $class->prepare(@arguments);
1421 return $c->finalize;
1424 if ( $class->debug ) {
1425 my $start = [gettimeofday];
1426 $status = &$handler;
1427 my $elapsed = tv_interval $start;
1428 $elapsed = sprintf '%f', $elapsed;
1429 my $av = sprintf '%.3f',
1430 ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) );
1431 my $t = Text::SimpleTable->new( [ 64, 'Action' ], [ 9, 'Time' ] );
1436 my $stat = $action->getNodeValue;
1437 $t->row( ( q{ } x $action->getDepth ) . $stat->{action} . $stat->{comment},
1438 $stat->{elapsed} || '??' );
1443 "Request took ${elapsed}s ($av/s)\n" . $t->draw );
1445 else { $status = &$handler }
1449 if ( my $error = $@ ) {
1451 $class->log->error(qq/Caught exception in engine "$error"/);
1455 $class->log->_flush() if $class->log->can('_flush');
1459 =head2 $c->prepare( @arguments )
1461 Creates a Catalyst context from an engine-specific request (Apache, CGI,
1467 my ( $class, @arguments ) = @_;
1469 $class->context_class( ref $class || $class ) unless $class->context_class;
1470 my $c = $class->context_class->new(
1474 request => $class->request_class->new(
1477 body_parameters => {},
1479 headers => HTTP::Headers->new,
1481 query_parameters => {},
1487 response => $class->response_class->new(
1491 headers => HTTP::Headers->new(),
1500 # For on-demand data
1501 $c->request->{_context} = $c;
1502 $c->response->{_context} = $c;
1503 weaken( $c->request->{_context} );
1504 weaken( $c->response->{_context} );
1507 my $secs = time - $START || 1;
1508 my $av = sprintf '%.3f', $COUNT / $secs;
1509 $c->log->debug('**********************************');
1510 $c->log->debug("* Request $COUNT ($av/s) [$$]");
1511 $c->log->debug('**********************************');
1512 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
1515 # Allow engine to direct the prepare flow (for POE)
1516 if ( $c->engine->can('prepare') ) {
1517 $c->engine->prepare( $c, @arguments );
1520 $c->prepare_request(@arguments);
1521 $c->prepare_connection;
1522 $c->prepare_query_parameters;
1523 $c->prepare_headers;
1524 $c->prepare_cookies;
1528 $c->prepare_body unless $c->config->{parse_on_demand};
1531 my $method = $c->req->method || '';
1532 my $path = $c->req->path || '';
1533 my $address = $c->req->address || '';
1535 $c->log->debug(qq/"$method" request for "$path" from "$address"/)
1543 =head2 $c->prepare_action
1549 sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1551 =head2 $c->prepare_body
1553 Prepares message body.
1560 # Do we run for the first time?
1561 return if defined $c->request->{_body};
1563 # Initialize on-demand data
1564 $c->engine->prepare_body( $c, @_ );
1565 $c->prepare_parameters;
1566 $c->prepare_uploads;
1568 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1569 my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
1570 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1571 my $param = $c->req->body_parameters->{$key};
1572 my $value = defined($param) ? $param : '';
1574 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1576 $c->log->debug( "Body Parameters are:\n" . $t->draw );
1580 =head2 $c->prepare_body_chunk( $chunk )
1582 Prepares a chunk of data before sending it to L<HTTP::Body>.
1586 sub prepare_body_chunk {
1588 $c->engine->prepare_body_chunk( $c, @_ );
1591 =head2 $c->prepare_body_parameters
1593 Prepares body parameters.
1597 sub prepare_body_parameters {
1599 $c->engine->prepare_body_parameters( $c, @_ );
1602 =head2 $c->prepare_connection
1604 Prepares connection.
1608 sub prepare_connection {
1610 $c->engine->prepare_connection( $c, @_ );
1613 =head2 $c->prepare_cookies
1619 sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1621 =head2 $c->prepare_headers
1627 sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1629 =head2 $c->prepare_parameters
1631 Prepares parameters.
1635 sub prepare_parameters {
1637 $c->prepare_body_parameters;
1638 $c->engine->prepare_parameters( $c, @_ );
1641 =head2 $c->prepare_path
1643 Prepares path and base.
1647 sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1649 =head2 $c->prepare_query_parameters
1651 Prepares query parameters.
1655 sub prepare_query_parameters {
1658 $c->engine->prepare_query_parameters( $c, @_ );
1660 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1661 my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
1662 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1663 my $param = $c->req->query_parameters->{$key};
1664 my $value = defined($param) ? $param : '';
1666 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1668 $c->log->debug( "Query Parameters are:\n" . $t->draw );
1672 =head2 $c->prepare_read
1674 Prepares the input for reading.
1678 sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1680 =head2 $c->prepare_request
1682 Prepares the engine request.
1686 sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1688 =head2 $c->prepare_uploads
1694 sub prepare_uploads {
1697 $c->engine->prepare_uploads( $c, @_ );
1699 if ( $c->debug && keys %{ $c->request->uploads } ) {
1700 my $t = Text::SimpleTable->new(
1706 for my $key ( sort keys %{ $c->request->uploads } ) {
1707 my $upload = $c->request->uploads->{$key};
1708 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
1709 $t->row( $key, $u->filename, $u->type, $u->size );
1712 $c->log->debug( "File Uploads are:\n" . $t->draw );
1716 =head2 $c->prepare_write
1718 Prepares the output for writing.
1722 sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1724 =head2 $c->request_class
1726 Returns or sets the request class.
1728 =head2 $c->response_class
1730 Returns or sets the response class.
1732 =head2 $c->read( [$maxlength] )
1734 Reads a chunk of data from the request body. This method is designed to
1735 be used in a while loop, reading C<$maxlength> bytes on every call.
1736 C<$maxlength> defaults to the size of the request if not specified.
1738 You have to set C<MyApp-E<gt>config-E<gt>{parse_on_demand}> to use this
1743 sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1751 sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1753 =head2 $c->set_action( $action, $code, $namespace, $attrs )
1755 Sets an action in a given namespace.
1759 sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1761 =head2 $c->setup_actions($component)
1763 Sets up actions for a component.
1767 sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1769 =head2 $c->setup_components
1775 sub setup_components {
1778 my $callback = sub {
1779 my ( $component, $context ) = @_;
1781 unless ( $component->can('COMPONENT') ) {
1785 my $suffix = Catalyst::Utils::class2classsuffix($component);
1786 my $config = $class->config->{$suffix} || {};
1790 eval { $instance = $component->COMPONENT( $context, $config ); };
1792 if ( my $error = $@ ) {
1796 Catalyst::Exception->throw( message =>
1797 qq/Couldn't instantiate component "$component", "$error"/ );
1800 Catalyst::Exception->throw( message =>
1801 qq/Couldn't instantiate component "$component", "COMPONENT() didn't return a object"/
1803 unless ref $instance;
1807 eval "package $class;\n" . q!Module::Pluggable::Fast->import(
1808 name => '_catalyst_components',
1810 "$class\::Controller", "$class\::C",
1811 "$class\::Model", "$class\::M",
1812 "$class\::View", "$class\::V"
1814 callback => $callback
1818 if ( my $error = $@ ) {
1822 Catalyst::Exception->throw(
1823 message => qq/Couldn't load components "$error"/ );
1826 for my $component ( $class->_catalyst_components($class) ) {
1827 $class->components->{ ref $component || $component } = $component;
1831 =head2 $c->setup_dispatcher
1837 sub setup_dispatcher {
1838 my ( $class, $dispatcher ) = @_;
1841 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1844 if ( $ENV{CATALYST_DISPATCHER} ) {
1845 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
1848 if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
1850 'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
1853 unless ($dispatcher) {
1854 $dispatcher = $class->dispatcher_class;
1857 $dispatcher->require;
1860 Catalyst::Exception->throw(
1861 message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
1864 # dispatcher instance
1865 $class->dispatcher( $dispatcher->new );
1868 =head2 $c->setup_engine
1875 my ( $class, $engine ) = @_;
1878 $engine = 'Catalyst::Engine::' . $engine;
1881 if ( $ENV{CATALYST_ENGINE} ) {
1882 $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
1885 if ( $ENV{ uc($class) . '_ENGINE' } ) {
1886 $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
1889 if ( $ENV{MOD_PERL} ) {
1891 # create the apache method
1894 *{"$class\::apache"} = sub { shift->engine->apache };
1897 my ( $software, $version ) =
1898 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
1901 $version =~ s/(\.[^.]+)\./$1/g;
1903 if ( $software eq 'mod_perl' ) {
1907 if ( $version >= 1.99922 ) {
1908 $engine = 'Catalyst::Engine::Apache2::MP20';
1911 elsif ( $version >= 1.9901 ) {
1912 $engine = 'Catalyst::Engine::Apache2::MP19';
1915 elsif ( $version >= 1.24 ) {
1916 $engine = 'Catalyst::Engine::Apache::MP13';
1920 Catalyst::Exception->throw( message =>
1921 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
1926 # install the correct mod_perl handler
1927 if ( $version >= 1.9901 ) {
1928 *handler = sub : method {
1929 shift->handle_request(@_);
1933 *handler = sub ($$) { shift->handle_request(@_) };
1938 elsif ( $software eq 'Zeus-Perl' ) {
1939 $engine = 'Catalyst::Engine::Zeus';
1943 Catalyst::Exception->throw(
1944 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
1949 $engine = $class->engine_class;
1955 Catalyst::Exception->throw( message =>
1956 qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
1960 # check for old engines that are no longer compatible
1962 if ( $engine->isa('Catalyst::Engine::Apache')
1963 && !Catalyst::Engine::Apache->VERSION )
1968 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
1969 && Catalyst::Engine::Server->VERSION le '0.02' )
1974 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
1975 && $engine->VERSION eq '0.01' )
1980 elsif ($engine->isa('Catalyst::Engine::Zeus')
1981 && $engine->VERSION eq '0.01' )
1987 Catalyst::Exception->throw( message =>
1988 qq/Engine "$engine" is not supported by this version of Catalyst/
1993 $class->engine( $engine->new );
1996 =head2 $c->setup_home
1998 Sets up the home directory.
2003 my ( $class, $home ) = @_;
2005 if ( $ENV{CATALYST_HOME} ) {
2006 $home = $ENV{CATALYST_HOME};
2009 if ( $ENV{ uc($class) . '_HOME' } ) {
2010 $home = $ENV{ uc($class) . '_HOME' };
2014 $home = Catalyst::Utils::home($class);
2018 $class->config->{home} ||= $home;
2019 $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
2023 =head2 $c->setup_log
2030 my ( $class, $debug ) = @_;
2032 unless ( $class->log ) {
2033 $class->log( Catalyst::Log->new );
2036 my $app_flag = Catalyst::Utils::class2env($class) . '_DEBUG';
2039 ( defined( $ENV{CATALYST_DEBUG} ) || defined( $ENV{$app_flag} ) )
2040 ? ( $ENV{CATALYST_DEBUG} || $ENV{$app_flag} )
2045 *{"$class\::debug"} = sub { 1 };
2046 $class->log->debug('Debug messages enabled');
2050 =head2 $c->setup_plugins
2056 =head2 $c->registered_plugins
2058 Returns a sorted list of the plugins which have either been stated in the
2059 import list or which have been added via C<< MyApp->plugin(@args); >>.
2061 If passed a given plugin name, it will report a boolean value indicating
2062 whether or not that plugin is loaded. A fully qualified name is required if
2063 the plugin name does not begin with C<Catalyst::Plugin::>.
2065 if ($c->registered_plugins('Some::Plugin')) {
2073 sub registered_plugins {
2075 return sort keys %{ $proto->_plugins } unless @_;
2077 return 1 if exists $proto->_plugins->{$plugin};
2078 return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
2081 sub _register_plugin {
2082 my ( $proto, $plugin, $instant ) = @_;
2083 my $class = ref $proto || $proto;
2087 if ( my $error = $@ ) {
2088 my $type = $instant ? "instant " : '';
2089 Catalyst::Exception->throw(
2090 message => qq/Couldn't load ${type}plugin "$plugin", $error/ );
2093 $proto->_plugins->{$plugin} = 1;
2096 unshift @{"$class\::ISA"}, $plugin;
2102 my ( $class, $plugins ) = @_;
2104 $class->_plugins( {} ) unless $class->_plugins;
2106 for my $plugin ( reverse @$plugins ) {
2108 unless ( $plugin =~ s/\A\+// ) {
2109 $plugin = "Catalyst::Plugin::$plugin";
2112 $class->_register_plugin($plugin);
2119 Returns an arrayref of the internal execution stack (actions that are currently
2122 =head2 $c->write( $data )
2124 Writes $data to the output stream. When using this method directly, you
2125 will need to manually set the C<Content-Length> header to the length of
2126 your output data, if known.
2133 # Finalize headers if someone manually writes output
2134 $c->finalize_headers;
2136 return $c->engine->write( $c, @_ );
2141 Returns the Catalyst version number. Mostly useful for "powered by"
2142 messages in template systems.
2146 sub version { return $Catalyst::VERSION }
2148 =head1 INTERNAL ACTIONS
2150 Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2151 C<_ACTION>, and C<_END>. These are by default not shown in the private
2152 action table, but you can make them visible with a config parameter.
2154 MyApp->config->{show_internal_actions} = 1;
2156 =head1 CASE SENSITIVITY
2158 By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
2159 mapped to C</foo/bar>. You can activate case sensitivity with a config
2162 MyApp->config->{case_sensitive} = 1;
2164 This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
2166 =head1 ON-DEMAND PARSER
2168 The request body is usually parsed at the beginning of a request,
2169 but if you want to handle input yourself or speed things up a bit,
2170 you can enable on-demand parsing with a config parameter.
2172 MyApp->config->{parse_on_demand} = 1;
2174 =head1 PROXY SUPPORT
2176 Many production servers operate using the common double-server approach,
2177 with a lightweight frontend web server passing requests to a larger
2178 backend server. An application running on the backend server must deal
2179 with two problems: the remote user always appears to be C<127.0.0.1> and
2180 the server's hostname will appear to be C<localhost> regardless of the
2181 virtual host that the user connected through.
2183 Catalyst will automatically detect this situation when you are running
2184 the frontend and backend servers on the same machine. The following
2185 changes are made to the request.
2187 $c->req->address is set to the user's real IP address, as read from
2188 the HTTP X-Forwarded-For header.
2190 The host value for $c->req->base and $c->req->uri is set to the real
2191 host, as read from the HTTP X-Forwarded-Host header.
2193 Obviously, your web server must support these headers for this to work.
2195 In a more complex server farm environment where you may have your
2196 frontend proxy server(s) on different machines, you will need to set a
2197 configuration option to tell Catalyst to read the proxied data from the
2200 MyApp->config->{using_frontend_proxy} = 1;
2202 If you do not wish to use the proxy support at all, you may set:
2204 MyApp->config->{ignore_frontend_proxy} = 1;
2206 =head1 THREAD SAFETY
2208 Catalyst has been tested under Apache 2's threading mpm_worker, mpm_winnt,
2209 and the standalone forking HTTP server on Windows. We believe the Catalyst
2210 core to be thread-safe.
2212 If you plan to operate in a threaded environment, remember that all other
2213 modules you are using must also be thread-safe. Some modules, most notably
2214 L<DBD::SQLite>, are not thread-safe.
2220 Join #catalyst on irc.perl.org.
2224 http://lists.rawmode.org/mailman/listinfo/catalyst
2225 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
2229 http://catalyst.perl.org
2233 http://dev.catalyst.perl.org
2237 =head2 L<Task::Catalyst> - All you need to start with Catalyst
2239 =head2 L<Catalyst::Manual> - The Catalyst Manual
2241 =head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
2243 =head2 L<Catalyst::Engine> - Core engine
2245 =head2 L<Catalyst::Log> - Log class.
2247 =head2 L<Catalyst::Request> - Request object
2249 =head2 L<Catalyst::Response> - Response object
2251 =head2 L<Catalyst::Test> - The test suite.
2323 Sebastian Riedel, C<sri@oook.de>
2327 This library is free software, you can redistribute it and/or modify it under
2328 the same terms as Perl itself.