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 BEGIN { require 5.008001; }
30 __PACKAGE__->mk_accessors(
31 qw/counter request response state action stack namespace stats/
34 attributes->import( __PACKAGE__, \&namespace, 'lvalue' );
36 sub depth { scalar @{ shift->stack || [] }; }
43 # For backwards compatibility
44 *finalize_output = \&finalize_body;
49 our $RECURSION = 1000;
50 our $DETACH = "catalyst_detach\n";
52 require Module::Pluggable::Fast;
54 # Helper script generation
55 our $CATALYST_SCRIPT_GEN = 27;
57 __PACKAGE__->mk_classdata($_)
58 for qw/components arguments dispatcher engine log dispatcher_class
59 engine_class context_class request_class response_class setup_finished/;
61 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
62 __PACKAGE__->engine_class('Catalyst::Engine::CGI');
63 __PACKAGE__->request_class('Catalyst::Request');
64 __PACKAGE__->response_class('Catalyst::Response');
66 our $VERSION = '5.6902';
69 my ( $class, @arguments ) = @_;
71 # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
73 return unless $class eq 'Catalyst';
75 my $caller = caller(0);
77 unless ( $caller->isa('Catalyst') ) {
79 push @{"$caller\::ISA"}, $class, 'Catalyst::Controller';
82 $caller->arguments( [@arguments] );
88 Catalyst - The Elegant MVC Web Application Framework
92 # use the helper to create a new application
95 # add models, views, controllers
96 script/myapp_create.pl model Database DBIC::SchemaLoader dbi:SQLite:/path/to/db
97 script/myapp_create.pl view TT TT
98 script/myapp_create.pl controller Search
100 # built in testserver -- use -r to restart automatically on changes
101 script/myapp_server.pl
103 # command line testing interface
104 script/myapp_test.pl /yada
107 use Catalyst qw/-Debug/; # include plugins here as well
109 ### In libMyApp/Controller/Root.pm (autocreated)
110 sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
111 my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
112 $c->stash->{template} = 'foo.tt'; # set the template
113 # lookup something from db -- stash vars are passed to TT
115 $c->model('Database::Foo')->search( { country => $args[0] } );
116 if ( $c->req->params->{bar} ) { # access GET or POST parameters
117 $c->forward( 'bar' ); # process another action
118 # do something else after forward returns
122 # The foo.tt TT template can use the stash data from the database
123 [% WHILE (item = data.next) %]
127 # called for /bar/of/soap, /bar/of/soap/10, etc.
128 sub bar : Path('/bar/of/soap') { ... }
130 # called for all actions, from the top-most controller downwards
132 my ( $self, $c ) = @_;
133 if ( !$c->user_exists ) { # Catalyst::Plugin::Authentication
134 $c->res->redirect( '/login' ); # require login
135 return 0; # abort request and go immediately to end()
137 return 1; # success; carry on to next action
140 # called after all actions are finished
142 my ( $self, $c ) = @_;
143 if ( scalar @{ $c->error } ) { ... } # handle errors
144 return if $c->res->body; # already have a response
145 $c->forward( 'MyApp::View::TT' ); # render template
148 ### in MyApp/Controller/Foo.pm
149 # called for /foo/bar
150 sub bar : Local { ... }
152 # called for /blargle
153 sub blargle : Global { ... }
155 # an index action matches /foo, but not /foo/1, etc.
156 sub index : Private { ... }
158 ### in MyApp/Controller/Foo/Bar.pm
159 # called for /foo/bar/baz
160 sub baz : Local { ... }
162 # first Root auto is called, then Foo auto, then this
163 sub auto : Private { ... }
165 # powerful regular expression paths are also possible
166 sub details : Regex('^product/(\w+)/details$') {
167 my ( $self, $c ) = @_;
168 # extract the (\w+) from the URI
169 my $product = $c->req->captures->[0];
172 See L<Catalyst::Manual::Intro> for additional information.
176 Catalyst is a modern framework for making web applications without the pain usually associated with this process. This document is a reference to the main Catalyst application. If you are a new user, we suggest you start with L<Catalyst::Manual::Tutorial> or L<Catalyst::Manual::Intro>
178 See L<Catalyst::Manual> for more documentation.
180 Catalyst plugins can be loaded by naming them as arguments to the "use
181 Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the
182 plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes
185 use Catalyst qw/My::Module/;
187 If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
188 fully qualify the name by using a unary plus:
192 +Fully::Qualified::Plugin::Name
195 Special flags like C<-Debug> and C<-Engine> can also be specified as
196 arguments when Catalyst is loaded:
198 use Catalyst qw/-Debug My::Module/;
200 The position of plugins and flags in the chain is important, because
201 they are loaded in exactly the order in which they appear.
203 The following flags are supported:
207 Enables debug output. You can also force this setting from the system
208 environment with CATALYST_DEBUG or <MYAPP>_DEBUG. The environment settings
209 override the app, with <MYAPP>_DEBUG having highest priority.
213 Forces Catalyst to use a specific engine. Omit the
214 C<Catalyst::Engine::> prefix of the engine name, i.e.:
216 use Catalyst qw/-Engine=CGI/;
220 Forces Catalyst to use a specific home directory, e.g.:
222 use Catalyst qw[-Home=/usr/sri];
230 =head2 INFORMATION ABOUT THE CURRENT REQUEST
234 Returns a L<Catalyst::Action> object for the current action, which
235 stringifies to the action name. See L<Catalyst::Action>.
239 Returns the namespace of the current action, i.e., the uri prefix
240 corresponding to the controller of the current action. For example:
242 # in Controller::Foo::Bar
243 $c->namespace; # returns 'foo/bar';
249 Returns the current L<Catalyst::Request> object. See
250 L<Catalyst::Request>.
252 =head2 REQUEST FLOW HANDLING
254 =head2 $c->forward( $action [, \@arguments ] )
256 =head2 $c->forward( $class, $method, [, \@arguments ] )
258 Forwards processing to another action, by it's private name. If you give a
259 class name but no method, C<process()> is called. You may also optionally
260 pass arguments in an arrayref. The action will receive the arguments in
261 C<@_> and C<$c-E<gt>req-E<gt>args>. Upon returning from the function,
262 C<$c-E<gt>req-E<gt>args> will be restored to the previous values.
264 Any data C<return>ed from the action forwarded to, will be returned by the
267 my $foodata = $c->forward('/foo');
268 $c->forward('index');
269 $c->forward(qw/MyApp::Model::DBIC::Foo do_stuff/);
270 $c->forward('MyApp::View::TT');
272 Note that forward implies an C<<eval { }>> around the call (well, actually
273 C<execute> does), thus de-fatalizing all 'dies' within the called action. If
274 you want C<die> to propagate you need to do something like:
277 die $c->error if $c->error;
279 Or make sure to always return true values from your actions and write your code
282 $c->forward('foo') || return;
286 sub forward { my $c = shift; $c->dispatcher->forward( $c, @_ ) }
288 =head2 $c->detach( $action [, \@arguments ] )
290 =head2 $c->detach( $class, $method, [, \@arguments ] )
292 The same as C<forward>, but doesn't return to the previous action when
293 processing is finished.
297 sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
303 Returns the current L<Catalyst::Response> object.
307 Returns a hashref to the stash, which may be used to store data and pass
308 it between components during a request. You can also set hash keys by
309 passing arguments. The stash is automatically sent to the view. The
310 stash is cleared at the end of a request; it cannot be used for
313 $c->stash->{foo} = $bar;
314 $c->stash( { moose => 'majestic', qux => 0 } );
315 $c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref
317 # stash is automatically passed to the view for use in a template
318 $c->forward( 'MyApp::V::TT' );
325 my $stash = @_ > 1 ? {@_} : $_[0];
326 croak('stash takes a hash or hashref') unless ref $stash;
327 while ( my ( $key, $val ) = each %$stash ) {
328 $c->{stash}->{$key} = $val;
336 =head2 $c->error($error, ...)
338 =head2 $c->error($arrayref)
340 Returns an arrayref containing error messages. If Catalyst encounters an
341 error while processing a request, it stores the error in $c->error. This
342 method should not be used to store non-fatal error messages.
344 my @error = @{ $c->error };
348 $c->error('Something bad happened');
355 my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
356 croak @$error unless ref $c;
357 push @{ $c->{error} }, @$error;
359 elsif ( defined $_[0] ) { $c->{error} = undef }
360 return $c->{error} || [];
366 Contains the return value of the last executed action.
368 =head2 $c->clear_errors
370 Clear errors. You probably don't want to clear the errors unless you are
371 implementing a custom error screen.
373 This is equivalent to running
389 my ( $c, @names ) = @_;
391 foreach my $name (@names) {
392 foreach my $component ( keys %{ $c->components } ) {
393 return $c->components->{$component} if $component =~ /$name/i;
400 # try explicit component names
402 my ( $c, @names ) = @_;
404 foreach my $try (@names) {
405 return $c->components->{$try} if ( exists $c->components->{$try} );
411 # like component, but try just these prefixes before regex searching,
412 # and do not try to return "sort keys %{ $c->components }"
414 my ( $c, $name, @prefixes ) = @_;
416 my $appclass = ref $c || $c;
418 my @names = map { "${appclass}::${_}::${name}" } @prefixes;
420 my $comp = $c->_comp_explicit(@names);
421 return $comp if defined($comp);
422 $comp = $c->_comp_search($name);
426 # Find possible names for a prefix
429 my ( $c, @prefixes ) = @_;
431 my $appclass = ref $c || $c;
433 my @pre = map { "${appclass}::${_}::" } @prefixes;
437 COMPONENT: foreach my $comp ($c->component) {
438 foreach my $p (@pre) {
439 if ($comp =~ s/^$p//) {
449 # Return a component if only one matches.
451 my ( $c, @prefixes ) = @_;
453 my $appclass = ref $c || $c;
455 my ( $comp, $rest ) =
456 map { $c->_comp_search("^${appclass}::${_}::") } @prefixes;
457 return $comp unless $rest;
460 # Filter a component before returning by calling ACCEPT_CONTEXT if available
461 sub _filter_component {
462 my ( $c, $comp, @args ) = @_;
463 if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
464 return $comp->ACCEPT_CONTEXT( $c, @args );
466 else { return $comp }
469 =head2 COMPONENT ACCESSORS
471 =head2 $c->controller($name)
473 Gets a L<Catalyst::Controller> instance by name.
475 $c->controller('Foo')->do_stuff;
477 If name is omitted, will return the controller for the dispatched action.
482 my ( $c, $name, @args ) = @_;
483 return $c->_filter_component( $c->_comp_prefixes( $name, qw/Controller C/ ),
486 return $c->component( $c->action->class );
489 =head2 $c->model($name)
491 Gets a L<Catalyst::Model> instance by name.
493 $c->model('Foo')->do_stuff;
495 If the name is omitted, it will look for a config setting 'default_model',
496 or check if there is only one view, and return it if that's the case.
501 my ( $c, $name, @args ) = @_;
502 return $c->_filter_component( $c->_comp_prefixes( $name, qw/Model M/ ),
505 return $c->component( $c->config->{default_model} )
506 if $c->config->{default_model};
507 return $c->_filter_component( $c->_comp_singular(qw/Model M/), @args );
511 =head2 $c->controllers
513 Returns the available names which can be passed to $c->controller
519 return $c->_comp_names(qw/Controller C/);
523 =head2 $c->view($name)
525 Gets a L<Catalyst::View> instance by name.
527 $c->view('Foo')->do_stuff;
529 If the name is omitted, it will look for a config setting 'default_view',
530 or check if there is only one view, and forward to it if that's the case.
535 my ( $c, $name, @args ) = @_;
536 return $c->_filter_component( $c->_comp_prefixes( $name, qw/View V/ ),
539 return $c->component( $c->config->{default_view} )
540 if $c->config->{default_view};
541 return $c->_filter_component( $c->_comp_singular(qw/View V/) );
546 Returns the available names which can be passed to $c->model
552 return $c->_comp_names(qw/Model M/);
558 Returns the available names which can be passed to $c->view
564 return $c->_comp_names(qw/View V/);
567 =head2 $c->comp($name)
569 =head2 $c->component($name)
571 Gets a component object by name. This method is no longer recommended,
572 unless you want to get a specific component by full
573 class. C<$c-E<gt>controller>, C<$c-E<gt>model>, and C<$c-E<gt>view>
574 should be used instead.
585 my $appclass = ref $c || $c;
588 $name, "${appclass}::${name}",
589 map { "${appclass}::${_}::${name}" }
590 qw/Model M Controller C View V/
593 my $comp = $c->_comp_explicit(@names);
594 return $c->_filter_component( $comp, @_ ) if defined($comp);
596 $comp = $c->_comp_search($name);
597 return $c->_filter_component( $comp, @_ ) if defined($comp);
600 return sort keys %{ $c->components };
605 =head2 CLASS DATA AND HELPER CLASSES
609 Returns or takes a hashref containing the application's configuration.
611 __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } );
613 You can also use a L<YAML> config file like myapp.yml in your
614 applications home directory.
617 db: dsn:SQLite:foo.db
625 $c->log->warn("Setting config after setup has been run is not a good idea.")
626 if ( @_ and $c->setup_finished );
628 $c->NEXT::config(@_);
633 Returns the logging object instance. Unless it is already set, Catalyst sets
634 this up with a L<Catalyst::Log> object. To use your own log class, set the
635 logger with the C<< __PACKAGE__->log >> method prior to calling
636 C<< __PACKAGE__->setup >>.
638 __PACKAGE__->log( MyLogger->new );
643 $c->log->info( 'Now logging with my own logger!' );
645 Your log class should implement the methods described in the
646 L<Catalyst::Log> man page.
651 Overload to enable debug messages (same as -Debug option).
657 =head2 $c->dispatcher
659 Returns the dispatcher instance. Stringifies to class name. See
660 L<Catalyst::Dispatcher>.
664 Returns the engine instance. Stringifies to the class name. See
668 =head2 UTILITY METHODS
670 =head2 $c->path_to(@path)
672 Merges C<@path> with C<$c-E<gt>config-E<gt>{home}> and returns a
673 L<Path::Class> object.
677 $c->path_to( 'db', 'sqlite.db' );
682 my ( $c, @path ) = @_;
683 my $path = Path::Class::Dir->new( $c->config->{home}, @path );
684 if ( -d $path ) { return $path }
685 else { return Path::Class::File->new( $c->config->{home}, @path ) }
688 =head2 $c->plugin( $name, $class, @args )
690 Helper method for plugins. It creates a classdata accessor/mutator and
691 loads and instantiates the given class.
693 MyApp->plugin( 'prototype', 'HTML::Prototype' );
695 $c->prototype->define_javascript_functions;
700 my ( $class, $name, $plugin, @args ) = @_;
701 $class->_register_plugin( $plugin, 1 );
703 eval { $plugin->import };
704 $class->mk_classdata($name);
706 eval { $obj = $plugin->new(@args) };
709 Catalyst::Exception->throw( message =>
710 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
714 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
720 Initializes the dispatcher and engine, loads any plugins, and loads the
721 model, view, and controller components. You may also specify an array
722 of plugins to load here, if you choose to not load them in the C<use
726 MyApp->setup( qw/-Debug/ );
731 my ( $class, @arguments ) = @_;
733 $class->log->warn("Running setup twice is not a good idea.")
734 if ( $class->setup_finished );
736 unless ( $class->isa('Catalyst') ) {
738 Catalyst::Exception->throw(
739 message => qq/'$class' does not inherit from Catalyst/ );
742 if ( $class->arguments ) {
743 @arguments = ( @arguments, @{ $class->arguments } );
749 foreach (@arguments) {
753 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
755 elsif (/^-(\w+)=?(.*)$/) {
756 $flags->{ lc $1 } = $2;
759 push @{ $flags->{plugins} }, $_;
763 $class->setup_home( delete $flags->{home} );
765 $class->setup_log( delete $flags->{log} );
766 $class->setup_plugins( delete $flags->{plugins} );
767 $class->setup_dispatcher( delete $flags->{dispatcher} );
768 $class->setup_engine( delete $flags->{engine} );
770 for my $flag ( sort keys %{$flags} ) {
772 if ( my $code = $class->can( 'setup_' . $flag ) ) {
773 &$code( $class, delete $flags->{$flag} );
776 $class->log->warn(qq/Unknown flag "$flag"/);
781 <<"EOF") if ( $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::CATALYST_SCRIPT_GEN ) );
782 You are running an old script!
784 Please update by running (this will overwrite existing files):
785 catalyst.pl -force -scripts $class
787 or (this will not overwrite existing files):
788 catalyst.pl -scripts $class
791 if ( $class->debug ) {
798 map { $_ . ' ' . ( $_->VERSION || '' ) }
799 grep { /^Catalyst::Plugin/ } @{"$class\::ISA"};
803 my $t = Text::SimpleTable->new(74);
804 $t->row($_) for @plugins;
805 $class->log->debug( "Loaded plugins:\n" . $t->draw );
808 my $dispatcher = $class->dispatcher;
809 my $engine = $class->engine;
810 my $home = $class->config->{home};
812 $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
813 $class->log->debug(qq/Loaded engine "$engine"/);
817 ? $class->log->debug(qq/Found home "$home"/)
818 : $class->log->debug(qq/Home "$home" doesn't exist/)
819 : $class->log->debug(q/Couldn't find home/);
824 no warnings qw/redefine/;
825 local *setup = sub { };
829 # Initialize our data structure
830 $class->components( {} );
832 $class->setup_components;
834 if ( $class->debug ) {
835 my $t = Text::SimpleTable->new( [ 63, 'Class' ], [ 8, 'Type' ] );
836 for my $comp ( sort keys %{ $class->components } ) {
837 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
838 $t->row( $comp, $type );
840 $class->log->debug( "Loaded components:\n" . $t->draw )
841 if ( keys %{ $class->components } );
844 # Add our self to components, since we are also a component
845 $class->components->{$class} = $class;
847 $class->setup_actions;
849 if ( $class->debug ) {
850 my $name = $class->config->{name} || 'Application';
851 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
853 $class->log->_flush() if $class->log->can('_flush');
855 $class->setup_finished(1);
858 =head2 $c->uri_for( $path, @args?, \%query_values? )
860 Merges path with C<$c-E<gt>request-E<gt>base> for absolute uri's and
861 with C<$c-E<gt>namespace> for relative uri's, then returns a
862 normalized L<URI> object. If any args are passed, they are added at the
863 end of the path. If the last argument to uri_for is a hash reference,
864 it is assumed to contain GET parameter key/value pairs, which will be
865 appended to the URI in standard fashion.
870 my ( $c, $path, @args ) = @_;
871 my $base = $c->request->base->clone;
872 my $basepath = $base->path;
873 $basepath =~ s/\/$//;
875 my $namespace = $c->namespace || '';
877 # massage namespace, empty if absolute path
878 $namespace =~ s/^\/// if $namespace;
879 $namespace .= '/' if $namespace;
881 $namespace = '' if $path =~ /^\//;
885 ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
887 for my $value ( values %$params ) {
\r
888 my $isa_ref = ref $value;
\r
889 if( $isa_ref and $isa_ref ne 'ARRAY' ) {
\r
890 croak( "Non-array reference ($isa_ref) passed to uri_for()" );
\r
892 utf8::encode( $_ ) for grep { defined } $isa_ref ? @$value : $value;
\r
895 # join args with '/', or a blank string
896 my $args = ( scalar @args ? '/' . join( '/', @args ) : '' );
897 $args =~ s/^\/// unless $path;
899 URI->new_abs( URI->new_abs( "$path$args", "$basepath$namespace" ), $base )
901 $res->query_form(%$params);
905 =head2 $c->welcome_message
907 Returns the Catalyst welcome HTML page.
911 sub welcome_message {
913 my $name = $c->config->{name};
914 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
915 my $prefix = Catalyst::Utils::appprefix( ref $c );
916 $c->response->content_type('text/html; charset=utf-8');
918 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
919 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
920 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
922 <meta http-equiv="Content-Language" content="en" />
923 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
924 <title>$name on Catalyst $VERSION</title>
925 <style type="text/css">
928 background-color: #eee;
937 background-color: #ccc;
938 border: 1px solid #aaa;
943 font-family: verdana, tahoma, sans-serif;
946 font-family: verdana, tahoma, sans-serif;
949 text-decoration: none;
951 border-bottom: 1px dotted #bbb;
953 :link:hover, :visited:hover {
966 background-color: #fff;
967 border: 1px solid #aaa;
993 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
998 <img src="$logo" alt="Catalyst Logo" />
1000 <p>Welcome to the wonderful world of Catalyst.
1001 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
1002 framework will make web development something you had
1003 never expected it to be: Fun, rewarding, and quick.</p>
1004 <h2>What to do now?</h2>
1005 <p>That really depends on what <b>you</b> want to do.
1006 We do, however, provide you with a few starting points.</p>
1007 <p>If you want to jump right into web development with Catalyst
1008 you might want to check out the documentation.</p>
1009 <pre><code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
1010 perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
1011 perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual.pod">Catalyst::Manual</a></code></pre>
1012 <h2>What to do next?</h2>
1013 <p>Next it's time to write an actual application. Use the
1014 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&mode=all">controllers</a>,
1015 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&mode=all">models</a>, and
1016 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&mode=all">views</a>;
1017 they can save you a lot of work.</p>
1018 <pre><code>script/${prefix}_create.pl -help</code></pre>
1019 <p>Also, be sure to check out the vast and growing
1020 collection of <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3APlugin%3A%3A&mode=all">plugins for Catalyst on CPAN</a>;
1021 you are likely to find what you need there.
1025 <p>Catalyst has a very active community. Here are the main places to
1026 get in touch with us.</p>
1029 <a href="http://dev.catalyst.perl.org">Wiki</a>
1032 <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
1035 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
1038 <h2>In conclusion</h2>
1039 <p>The Catalyst team hopes you will enjoy using Catalyst as much
1040 as we enjoyed making it. Please contact us if you have ideas
1041 for improvement or other feedback.</p>
1049 =head1 INTERNAL METHODS
1051 These methods are not meant to be used by end users.
1053 =head2 $c->components
1055 Returns a hash of components.
1057 =head2 $c->context_class
1059 Returns or sets the context class.
1063 Returns a hashref containing coderefs and execution counts (needed for
1064 deep recursion detection).
1068 Returns the number of actions on the current internal execution stack.
1072 Dispatches a request to actions.
1076 sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
1078 =head2 $c->dispatcher_class
1080 Returns or sets the dispatcher class.
1082 =head2 $c->dump_these
1084 Returns a list of 2-element array references (name, structure) pairs
1085 that will be dumped on the error page in debug mode.
1091 [ Request => $c->req ],
1092 [ Response => $c->res ],
1093 [ Stash => $c->stash ],
1094 [ Config => $c->config ];
1097 =head2 $c->engine_class
1099 Returns or sets the engine class.
1101 =head2 $c->execute( $class, $coderef )
1103 Execute a coderef in given class and catch exceptions. Errors are available
1109 my ( $c, $class, $code ) = @_;
1110 $class = $c->component($class) || $class;
1113 if ( $c->depth >= $RECURSION ) {
1114 my $action = "$code";
1115 $action = "/$action" unless $action =~ /\-\>/;
1116 my $error = qq/Deep recursion detected calling "$action"/;
1117 $c->log->error($error);
1123 my $stats_info = $c->_stats_start_execute( $code );
1125 push( @{ $c->stack }, $code );
1127 eval { $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 ) };
1129 $c->_stats_finish_execute( $stats_info );
1131 my $last = ${ $c->stack }[-1];
1132 pop( @{ $c->stack } );
1134 if ( my $error = $@ ) {
1135 if ( $error eq $DETACH ) { die $DETACH if $c->depth > 1 }
1137 unless ( ref $error ) {
1139 my $class = $last->class;
1140 my $name = $last->name;
1141 $error = qq/Caught exception in $class->$name "$error"/;
1150 sub _stats_start_execute {
1151 my ( $c, $code ) = @_;
1153 return unless $c->debug;
1155 my $action = "$code";
1157 $action = "/$action" unless $action =~ /\-\>/;
1158 $c->counter->{"$code"}++;
1160 # determine if the call was the result of a forward
1161 # this is done by walking up the call stack and looking for a calling
1162 # sub of Catalyst::forward before the eval
1164 for my $index ( 2 .. 11 ) {
1166 if ( ( caller($index) )[0] eq 'Catalyst'
1167 && ( caller($index) )[3] eq '(eval)' );
1169 if ( ( caller($index) )[3] =~ /forward$/ ) {
1170 $callsub = ( caller($index) )[3];
1171 $action = "-> $action";
1176 my $node = Tree::Simple->new(
1179 elapsed => undef, # to be filled in later
1183 $node->setUID( "$code" . $c->counter->{"$code"} );
1185 unless ( ( $code->name =~ /^_.*/ )
1186 && ( !$c->config->{show_internal_actions} ) )
1188 # is this a root-level call or a forwarded call?
1189 if ( $callsub =~ /forward$/ ) {
1191 # forward, locate the caller
1192 if ( my $parent = $c->stack->[-1] ) {
1193 my $visitor = Tree::Simple::Visitor::FindByUID->new;
1194 $visitor->searchForUID(
1195 "$parent" . $c->counter->{"$parent"} );
1196 $c->stats->accept($visitor);
1197 if ( my $result = $visitor->getResult ) {
1198 $result->addChild($node);
1203 # forward with no caller may come from a plugin
1204 $c->stats->addChild($node);
1210 $c->stats->addChild($node);
1214 my $start = [gettimeofday];
1215 my $elapsed = tv_interval($start);
1219 elapsed => $elapsed,
1225 sub _stats_finish_execute {
1226 my ( $c, $info ) = @_;
1228 return unless $c->debug;
1230 my ( $code, $start, $elapsed ) = @{ $info }{qw/code start elapsed/};
1232 unless ( ( $code->name =~ /^_.*/ )
1233 && ( !$c->config->{show_internal_actions} ) )
1236 # FindByUID uses an internal die, so we save the existing error
1239 # locate the node in the tree and update the elapsed time
1240 my $visitor = Tree::Simple::Visitor::FindByUID->new;
1241 $visitor->searchForUID( "$code" . $c->counter->{"$code"} );
1242 $c->stats->accept($visitor);
1243 if ( my $result = $visitor->getResult ) {
1244 my $value = $result->getNodeValue;
1245 $value->{elapsed} = sprintf( '%fs', $elapsed );
1246 $result->setNodeValue($value);
1250 $@ = $error || undef;
1254 =head2 $c->_localize_fields( sub { }, \%keys );
1258 sub _localize_fields {
1259 my ( $c, $localized, $code ) = ( @_ );
1261 my $request = delete $localized->{request} || {};
1262 my $response = delete $localized->{response} || {};
1264 local @{ $c }{ keys %$localized } = values %$localized;
1265 local @{ $c->request }{ keys %$request } = values %$request;
1266 local @{ $c->response }{ keys %$response } = values %$response;
1273 Finalizes the request.
1280 for my $error ( @{ $c->error } ) {
1281 $c->log->error($error);
1284 # Allow engine to handle finalize flow (for POE)
1285 if ( $c->engine->can('finalize') ) {
1286 $c->engine->finalize($c);
1290 $c->finalize_uploads;
1293 if ( $#{ $c->error } >= 0 ) {
1297 $c->finalize_headers;
1300 if ( $c->request->method eq 'HEAD' ) {
1301 $c->response->body('');
1307 return $c->response->status;
1310 =head2 $c->finalize_body
1316 sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1318 =head2 $c->finalize_cookies
1324 sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
1326 =head2 $c->finalize_error
1332 sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1334 =head2 $c->finalize_headers
1340 sub finalize_headers {
1343 # Check if we already finalized headers
1344 return if $c->response->{_finalized_headers};
1347 if ( my $location = $c->response->redirect ) {
1348 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
1349 $c->response->header( Location => $location );
1353 if ( $c->response->body && !$c->response->content_length ) {
1355 # get the length from a filehandle
1356 if ( blessed( $c->response->body ) && $c->response->body->can('read') )
1358 if ( my $stat = stat $c->response->body ) {
1359 $c->response->content_length( $stat->size );
1362 $c->log->warn('Serving filehandle without a content-length');
1366 $c->response->content_length( bytes::length( $c->response->body ) );
1371 if ( $c->response->status =~ /^(1\d\d|[23]04)$/ ) {
1372 $c->response->headers->remove_header("Content-Length");
1373 $c->response->body('');
1376 $c->finalize_cookies;
1378 $c->engine->finalize_headers( $c, @_ );
1381 $c->response->{_finalized_headers} = 1;
1384 =head2 $c->finalize_output
1386 An alias for finalize_body.
1388 =head2 $c->finalize_read
1390 Finalizes the input after reading is complete.
1394 sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1396 =head2 $c->finalize_uploads
1398 Finalizes uploads. Cleans up any temporary files.
1402 sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1404 =head2 $c->get_action( $action, $namespace )
1406 Gets an action in a given namespace.
1410 sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
1412 =head2 $c->get_actions( $action, $namespace )
1414 Gets all actions of a given name in a namespace and all parent
1419 sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1421 =head2 $c->handle_request( $class, @arguments )
1423 Called to handle each HTTP request.
1427 sub handle_request {
1428 my ( $class, @arguments ) = @_;
1430 # Always expect worst case!
1433 my $stats = ( $class->debug ) ? Tree::Simple->new: q{};
1436 my $c = $class->prepare(@arguments);
1439 return $c->finalize;
1442 if ( $class->debug ) {
1443 my $start = [gettimeofday];
1444 $status = &$handler;
1445 my $elapsed = tv_interval $start;
1446 $elapsed = sprintf '%f', $elapsed;
1447 my $av = sprintf '%.3f',
1448 ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) );
1449 my $t = Text::SimpleTable->new( [ 62, 'Action' ], [ 9, 'Time' ] );
1454 my $stat = $action->getNodeValue;
1455 $t->row( ( q{ } x $action->getDepth ) . $stat->{action} . $stat->{comment},
1456 $stat->{elapsed} || '??' );
1461 "Request took ${elapsed}s ($av/s)\n" . $t->draw );
1463 else { $status = &$handler }
1467 if ( my $error = $@ ) {
1469 $class->log->error(qq/Caught exception in engine "$error"/);
1473 $class->log->_flush() if $class->log->can('_flush');
1477 =head2 $c->prepare( @arguments )
1479 Creates a Catalyst context from an engine-specific request (Apache, CGI,
1485 my ( $class, @arguments ) = @_;
1487 $class->context_class( ref $class || $class ) unless $class->context_class;
1488 my $c = $class->context_class->new(
1492 request => $class->request_class->new(
1495 body_parameters => {},
1497 headers => HTTP::Headers->new,
1499 query_parameters => {},
1505 response => $class->response_class->new(
1509 headers => HTTP::Headers->new(),
1518 # For on-demand data
1519 $c->request->{_context} = $c;
1520 $c->response->{_context} = $c;
1521 weaken( $c->request->{_context} );
1522 weaken( $c->response->{_context} );
1525 my $secs = time - $START || 1;
1526 my $av = sprintf '%.3f', $COUNT / $secs;
1527 my $time = localtime time;
1528 $c->log->info("*** Request $COUNT ($av/s) [$$] [$time] ***");
1529 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
1532 # Allow engine to direct the prepare flow (for POE)
1533 if ( $c->engine->can('prepare') ) {
1534 $c->engine->prepare( $c, @arguments );
1537 $c->prepare_request(@arguments);
1538 $c->prepare_connection;
1539 $c->prepare_query_parameters;
1540 $c->prepare_headers;
1541 $c->prepare_cookies;
1545 $c->prepare_body unless $c->config->{parse_on_demand};
1548 my $method = $c->req->method || '';
1549 my $path = $c->req->path || '/';
1550 my $address = $c->req->address || '';
1552 $c->log->debug(qq/"$method" request for "$path" from "$address"/)
1560 =head2 $c->prepare_action
1562 Prepares action. See L<Catalyst::Dispatcher>.
1566 sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1568 =head2 $c->prepare_body
1570 Prepares message body.
1577 # Do we run for the first time?
1578 return if defined $c->request->{_body};
1580 # Initialize on-demand data
1581 $c->engine->prepare_body( $c, @_ );
1582 $c->prepare_parameters;
1583 $c->prepare_uploads;
1585 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1586 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1587 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1588 my $param = $c->req->body_parameters->{$key};
1589 my $value = defined($param) ? $param : '';
1591 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1593 $c->log->debug( "Body Parameters are:\n" . $t->draw );
1597 =head2 $c->prepare_body_chunk( $chunk )
1599 Prepares a chunk of data before sending it to L<HTTP::Body>.
1601 See L<Catalyst::Engine>.
1605 sub prepare_body_chunk {
1607 $c->engine->prepare_body_chunk( $c, @_ );
1610 =head2 $c->prepare_body_parameters
1612 Prepares body parameters.
1616 sub prepare_body_parameters {
1618 $c->engine->prepare_body_parameters( $c, @_ );
1621 =head2 $c->prepare_connection
1623 Prepares connection.
1627 sub prepare_connection {
1629 $c->engine->prepare_connection( $c, @_ );
1632 =head2 $c->prepare_cookies
1638 sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1640 =head2 $c->prepare_headers
1646 sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1648 =head2 $c->prepare_parameters
1650 Prepares parameters.
1654 sub prepare_parameters {
1656 $c->prepare_body_parameters;
1657 $c->engine->prepare_parameters( $c, @_ );
1660 =head2 $c->prepare_path
1662 Prepares path and base.
1666 sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1668 =head2 $c->prepare_query_parameters
1670 Prepares query parameters.
1674 sub prepare_query_parameters {
1677 $c->engine->prepare_query_parameters( $c, @_ );
1679 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1680 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1681 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1682 my $param = $c->req->query_parameters->{$key};
1683 my $value = defined($param) ? $param : '';
1685 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1687 $c->log->debug( "Query Parameters are:\n" . $t->draw );
1691 =head2 $c->prepare_read
1693 Prepares the input for reading.
1697 sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1699 =head2 $c->prepare_request
1701 Prepares the engine request.
1705 sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1707 =head2 $c->prepare_uploads
1713 sub prepare_uploads {
1716 $c->engine->prepare_uploads( $c, @_ );
1718 if ( $c->debug && keys %{ $c->request->uploads } ) {
1719 my $t = Text::SimpleTable->new(
1720 [ 12, 'Parameter' ],
1725 for my $key ( sort keys %{ $c->request->uploads } ) {
1726 my $upload = $c->request->uploads->{$key};
1727 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
1728 $t->row( $key, $u->filename, $u->type, $u->size );
1731 $c->log->debug( "File Uploads are:\n" . $t->draw );
1735 =head2 $c->prepare_write
1737 Prepares the output for writing.
1741 sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1743 =head2 $c->request_class
1745 Returns or sets the request class.
1747 =head2 $c->response_class
1749 Returns or sets the response class.
1751 =head2 $c->read( [$maxlength] )
1753 Reads a chunk of data from the request body. This method is designed to
1754 be used in a while loop, reading C<$maxlength> bytes on every call.
1755 C<$maxlength> defaults to the size of the request if not specified.
1757 You have to set C<MyApp-E<gt>config-E<gt>{parse_on_demand}> to use this
1762 sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1770 sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1772 =head2 $c->set_action( $action, $code, $namespace, $attrs )
1774 Sets an action in a given namespace.
1778 sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1780 =head2 $c->setup_actions($component)
1782 Sets up actions for a component.
1786 sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1788 =head2 $c->setup_components
1794 sub setup_components {
1797 my $callback = sub {
1798 my ( $component, $context ) = @_;
1800 unless ( $component->can('COMPONENT') ) {
1804 my $suffix = Catalyst::Utils::class2classsuffix($component);
1805 my $config = $class->config->{$suffix} || {};
1809 eval { $instance = $component->COMPONENT( $context, $config ); };
1811 if ( my $error = $@ ) {
1815 Catalyst::Exception->throw( message =>
1816 qq/Couldn't instantiate component "$component", "$error"/ );
1819 Catalyst::Exception->throw( message =>
1820 qq/Couldn't instantiate component "$component", "COMPONENT() didn't return a object"/
1822 unless ref $instance;
1826 eval "package $class;\n" . q!Module::Pluggable::Fast->import(
1827 name => '_catalyst_components',
1829 "$class\::Controller", "$class\::C",
1830 "$class\::Model", "$class\::M",
1831 "$class\::View", "$class\::V"
1833 callback => $callback
1837 if ( my $error = $@ ) {
1841 Catalyst::Exception->throw(
1842 message => qq/Couldn't load components "$error"/ );
1845 for my $component ( $class->_catalyst_components($class) ) {
1846 $class->components->{ ref $component || $component } = $component;
1850 =head2 $c->setup_dispatcher
1856 sub setup_dispatcher {
1857 my ( $class, $dispatcher ) = @_;
1860 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1863 if ( $ENV{CATALYST_DISPATCHER} ) {
1864 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
1867 if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
1869 'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
1872 unless ($dispatcher) {
1873 $dispatcher = $class->dispatcher_class;
1876 $dispatcher->require;
1879 Catalyst::Exception->throw(
1880 message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
1883 # dispatcher instance
1884 $class->dispatcher( $dispatcher->new );
1887 =head2 $c->setup_engine
1894 my ( $class, $engine ) = @_;
1897 $engine = 'Catalyst::Engine::' . $engine;
1900 if ( $ENV{CATALYST_ENGINE} ) {
1901 $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
1904 if ( $ENV{ uc($class) . '_ENGINE' } ) {
1905 $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
1908 if ( $ENV{MOD_PERL} ) {
1910 # create the apache method
1913 *{"$class\::apache"} = sub { shift->engine->apache };
1916 my ( $software, $version ) =
1917 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
1920 $version =~ s/(\.[^.]+)\./$1/g;
1922 if ( $software eq 'mod_perl' ) {
1926 if ( $version >= 1.99922 ) {
1927 $engine = 'Catalyst::Engine::Apache2::MP20';
1930 elsif ( $version >= 1.9901 ) {
1931 $engine = 'Catalyst::Engine::Apache2::MP19';
1934 elsif ( $version >= 1.24 ) {
1935 $engine = 'Catalyst::Engine::Apache::MP13';
1939 Catalyst::Exception->throw( message =>
1940 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
1945 # install the correct mod_perl handler
1946 if ( $version >= 1.9901 ) {
1947 *handler = sub : method {
1948 shift->handle_request(@_);
1952 *handler = sub ($$) { shift->handle_request(@_) };
1957 elsif ( $software eq 'Zeus-Perl' ) {
1958 $engine = 'Catalyst::Engine::Zeus';
1962 Catalyst::Exception->throw(
1963 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
1968 $engine = $class->engine_class;
1974 Catalyst::Exception->throw( message =>
1975 qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
1979 # check for old engines that are no longer compatible
1981 if ( $engine->isa('Catalyst::Engine::Apache')
1982 && !Catalyst::Engine::Apache->VERSION )
1987 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
1988 && Catalyst::Engine::Server->VERSION le '0.02' )
1993 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
1994 && $engine->VERSION eq '0.01' )
1999 elsif ($engine->isa('Catalyst::Engine::Zeus')
2000 && $engine->VERSION eq '0.01' )
2006 Catalyst::Exception->throw( message =>
2007 qq/Engine "$engine" is not supported by this version of Catalyst/
2012 $class->engine( $engine->new );
2015 =head2 $c->setup_home
2017 Sets up the home directory.
2022 my ( $class, $home ) = @_;
2024 if ( $ENV{CATALYST_HOME} ) {
2025 $home = $ENV{CATALYST_HOME};
2028 if ( $ENV{ uc($class) . '_HOME' } ) {
2029 $home = $ENV{ uc($class) . '_HOME' };
2033 $home = Catalyst::Utils::home($class);
2037 $class->config->{home} ||= $home;
2038 $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
2042 =head2 $c->setup_log
2049 my ( $class, $debug ) = @_;
2051 unless ( $class->log ) {
2052 $class->log( Catalyst::Log->new );
2055 my $app_flag = Catalyst::Utils::class2env($class) . '_DEBUG';
2058 ( defined( $ENV{CATALYST_DEBUG} ) || defined( $ENV{$app_flag} ) )
2059 ? ( $ENV{CATALYST_DEBUG} || $ENV{$app_flag} )
2064 *{"$class\::debug"} = sub { 1 };
2065 $class->log->debug('Debug messages enabled');
2069 =head2 $c->setup_plugins
2075 =head2 $c->registered_plugins
2077 Returns a sorted list of the plugins which have either been stated in the
2078 import list or which have been added via C<< MyApp->plugin(@args); >>.
2080 If passed a given plugin name, it will report a boolean value indicating
2081 whether or not that plugin is loaded. A fully qualified name is required if
2082 the plugin name does not begin with C<Catalyst::Plugin::>.
2084 if ($c->registered_plugins('Some::Plugin')) {
2092 sub registered_plugins {
2094 return sort keys %{ $proto->_plugins } unless @_;
2096 return 1 if exists $proto->_plugins->{$plugin};
2097 return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
2100 sub _register_plugin {
2101 my ( $proto, $plugin, $instant ) = @_;
2102 my $class = ref $proto || $proto;
2106 if ( my $error = $@ ) {
2107 my $type = $instant ? "instant " : '';
2108 Catalyst::Exception->throw(
2109 message => qq/Couldn't load ${type}plugin "$plugin", $error/ );
2112 $proto->_plugins->{$plugin} = 1;
2115 unshift @{"$class\::ISA"}, $plugin;
2121 my ( $class, $plugins ) = @_;
2123 $class->_plugins( {} ) unless $class->_plugins;
2125 for my $plugin ( reverse @$plugins ) {
2127 unless ( $plugin =~ s/\A\+// ) {
2128 $plugin = "Catalyst::Plugin::$plugin";
2131 $class->_register_plugin($plugin);
2138 Returns an arrayref of the internal execution stack (actions that are currently
2141 =head2 $c->write( $data )
2143 Writes $data to the output stream. When using this method directly, you
2144 will need to manually set the C<Content-Length> header to the length of
2145 your output data, if known.
2152 # Finalize headers if someone manually writes output
2153 $c->finalize_headers;
2155 return $c->engine->write( $c, @_ );
2160 Returns the Catalyst version number. Mostly useful for "powered by"
2161 messages in template systems.
2165 sub version { return $Catalyst::VERSION }
2167 =head1 INTERNAL ACTIONS
2169 Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2170 C<_ACTION>, and C<_END>. These are by default not shown in the private
2171 action table, but you can make them visible with a config parameter.
2173 MyApp->config->{show_internal_actions} = 1;
2175 =head1 CASE SENSITIVITY
2177 By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
2178 mapped to C</foo/bar>. You can activate case sensitivity with a config
2181 MyApp->config->{case_sensitive} = 1;
2183 This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
2185 =head1 ON-DEMAND PARSER
2187 The request body is usually parsed at the beginning of a request,
2188 but if you want to handle input yourself or speed things up a bit,
2189 you can enable on-demand parsing with a config parameter.
2191 MyApp->config->{parse_on_demand} = 1;
2193 =head1 PROXY SUPPORT
2195 Many production servers operate using the common double-server approach,
2196 with a lightweight frontend web server passing requests to a larger
2197 backend server. An application running on the backend server must deal
2198 with two problems: the remote user always appears to be C<127.0.0.1> and
2199 the server's hostname will appear to be C<localhost> regardless of the
2200 virtual host that the user connected through.
2202 Catalyst will automatically detect this situation when you are running
2203 the frontend and backend servers on the same machine. The following
2204 changes are made to the request.
2206 $c->req->address is set to the user's real IP address, as read from
2207 the HTTP X-Forwarded-For header.
2209 The host value for $c->req->base and $c->req->uri is set to the real
2210 host, as read from the HTTP X-Forwarded-Host header.
2212 Obviously, your web server must support these headers for this to work.
2214 In a more complex server farm environment where you may have your
2215 frontend proxy server(s) on different machines, you will need to set a
2216 configuration option to tell Catalyst to read the proxied data from the
2219 MyApp->config->{using_frontend_proxy} = 1;
2221 If you do not wish to use the proxy support at all, you may set:
2223 MyApp->config->{ignore_frontend_proxy} = 1;
2225 =head1 THREAD SAFETY
2227 Catalyst has been tested under Apache 2's threading mpm_worker, mpm_winnt,
2228 and the standalone forking HTTP server on Windows. We believe the Catalyst
2229 core to be thread-safe.
2231 If you plan to operate in a threaded environment, remember that all other
2232 modules you are using must also be thread-safe. Some modules, most notably
2233 L<DBD::SQLite>, are not thread-safe.
2239 Join #catalyst on irc.perl.org.
2243 http://lists.rawmode.org/mailman/listinfo/catalyst
2244 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
2248 http://catalyst.perl.org
2252 http://dev.catalyst.perl.org
2256 =head2 L<Task::Catalyst> - All you need to start with Catalyst
2258 =head2 L<Catalyst::Manual> - The Catalyst Manual
2260 =head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
2262 =head2 L<Catalyst::Engine> - Core engine
2264 =head2 L<Catalyst::Log> - Log class.
2266 =head2 L<Catalyst::Request> - Request object
2268 =head2 L<Catalyst::Response> - Response object
2270 =head2 L<Catalyst::Test> - The test suite.
2342 Sebastian Riedel, C<sri@oook.de>
2346 This library is free software, you can redistribute it and/or modify it under
2347 the same terms as Perl itself.