t0m++ fixed go/visit.
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
CommitLineData
fc7ec1d9 1package Catalyst;
2
a7caa492 3use Moose;
4extends 'Catalyst::Component';
fbcc39ad 5use bytes;
edb20ed3 6use Scope::Upper ();
a2f2cde9 7use Catalyst::Exception;
fc7ec1d9 8use Catalyst::Log;
fbcc39ad 9use Catalyst::Request;
10use Catalyst::Request::Upload;
11use Catalyst::Response;
812a28c9 12use Catalyst::Utils;
31375184 13use Catalyst::Controller;
364d7324 14use Devel::InnerPackage ();
8f62c91a 15use File::stat;
c50f595c 16use Module::Pluggable::Object ();
c50f595c 17use Text::SimpleTable ();
18use Path::Class::Dir ();
19use Path::Class::File ();
c50f595c 20use URI ();
933ba403 21use URI::http;
22use URI::https;
5513038d 23use Tree::Simple qw/use_weak_refs/;
24use Tree::Simple::Visitor::FindByUID;
269408a4 25use Class::C3::Adopt::NEXT;
261c571e 26use attributes;
5789a3d8 27use utf8;
108201b5 28use Carp qw/croak carp shortmess/;
fc7ec1d9 29
f63c03e4 30BEGIN { require 5.008001; }
31
8a440eba 32has stack => (is => 'ro', default => sub { [] });
6680c772 33has stash => (is => 'rw', default => sub { {} });
34has state => (is => 'rw', default => 0);
b6d4ee6e 35has stats => (is => 'rw');
36has action => (is => 'rw');
6680c772 37has counter => (is => 'rw', default => sub { {} });
38has request => (is => 'rw', default => sub { $_[0]->request_class->new({}) }, required => 1, lazy => 1);
39has response => (is => 'rw', default => sub { $_[0]->response_class->new({}) }, required => 1, lazy => 1);
e63bdf38 40has namespace => (is => 'rw');
41
8767c5a3 42sub depth { scalar @{ shift->stack || [] }; }
0fc2d522 43sub comp { shift->component(@_) }
6680c772 44
45sub req {
46 # carp "the use of req() is deprecated in favour of request()";
47 my $self = shift; return $self->request(@_);
48}
49sub res {
50 # carp "the use of res() is deprecated in favour of response()";
51 my $self = shift; return $self->response(@_);
52}
fbcc39ad 53
54# For backwards compatibility
0fc2d522 55sub finalize_output { shift->finalize_body(@_) };
fbcc39ad 56
57# For statistics
58our $COUNT = 1;
59our $START = time;
60our $RECURSION = 1000;
61our $DETACH = "catalyst_detach\n";
55424863 62our $GO = "catalyst_go\n";
fbcc39ad 63
b6d4ee6e 64#I imagine that very few of these really need to be class variables. if any.
65#maybe we should just make them attributes with a default?
fbcc39ad 66__PACKAGE__->mk_classdata($_)
3cec521a 67 for qw/components arguments dispatcher engine log dispatcher_class
ac5c933b 68 engine_class context_class request_class response_class stats_class
dc5f035e 69 setup_finished/;
cb0354c6 70
3cec521a 71__PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
72__PACKAGE__->engine_class('Catalyst::Engine::CGI');
73__PACKAGE__->request_class('Catalyst::Request');
74__PACKAGE__->response_class('Catalyst::Response');
dc5f035e 75__PACKAGE__->stats_class('Catalyst::Stats');
fbcc39ad 76
6415bb4d 77# Remember to update this in Catalyst::Runtime as well!
78
46b6daa3 79our $VERSION = '5.8000_06';
4ed63588 80
81{
82 my $dev_version = $VERSION =~ /_\d{2}$/;
83 *_IS_DEVELOPMENT_VERSION = sub () { $dev_version };
84}
85
c3f6d73a 86$VERSION = eval $VERSION;
189e2a51 87
fbcc39ad 88sub import {
89 my ( $class, @arguments ) = @_;
90
91 # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
92 # callers @ISA.
93 return unless $class eq 'Catalyst';
94
84ff88cf 95 my $caller = caller();
96 return if $caller eq 'main';
269408a4 97
98 # Kill Adopt::NEXT warnings if we're a non-RC version
4ed63588 99 unless (_IS_DEVELOPMENT_VERSION()) {
8833fe2c 100 Class::C3::Adopt::NEXT->unimport(qr/^Catalyst::/);
269408a4 101 }
102
84ff88cf 103 my $meta = Moose::Meta::Class->initialize($caller);
104 #Moose->import({ into => $caller }); #do we want to do this?
fbcc39ad 105
106 unless ( $caller->isa('Catalyst') ) {
84ff88cf 107 my @superclasses = ($meta->superclasses, $class, 'Catalyst::Controller');
108 $meta->superclasses(@superclasses);
109 }
110 unless( $meta->has_method('meta') ){
111 $meta->add_method(meta => sub { Moose::Meta::Class->initialize("${caller}") } );
fbcc39ad 112 }
113
114 $caller->arguments( [@arguments] );
115 $caller->setup_home;
116}
fc7ec1d9 117
118=head1 NAME
119
120Catalyst - The Elegant MVC Web Application Framework
121
122=head1 SYNOPSIS
123
e7ad3b81 124See the L<Catalyst::Manual> distribution for comprehensive
125documentation and tutorials.
126
86418559 127 # Install Catalyst::Devel for helpers and other development tools
b4b01a8a 128 # use the helper to create a new application
91864987 129 catalyst.pl MyApp
fc7ec1d9 130
131 # add models, views, controllers
2f381252 132 script/myapp_create.pl model MyDatabase DBIC::Schema create=static dbi:SQLite:/path/to/db
cc95842f 133 script/myapp_create.pl view MyTemplate TT
0ef52a96 134 script/myapp_create.pl controller Search
fc7ec1d9 135
e7f1cf73 136 # built in testserver -- use -r to restart automatically on changes
cc95842f 137 # --help to see all available options
ae4e40a7 138 script/myapp_server.pl
fc7ec1d9 139
0ef52a96 140 # command line testing interface
ae4e40a7 141 script/myapp_test.pl /yada
fc7ec1d9 142
b4b01a8a 143 ### in lib/MyApp.pm
0ef52a96 144 use Catalyst qw/-Debug/; # include plugins here as well
ac5c933b 145
85d9fce6 146 ### In lib/MyApp/Controller/Root.pm (autocreated)
0ef52a96 147 sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
ae1e6b59 148 my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
149 $c->stash->{template} = 'foo.tt'; # set the template
0ef52a96 150 # lookup something from db -- stash vars are passed to TT
ac5c933b 151 $c->stash->{data} =
b4b01a8a 152 $c->model('Database::Foo')->search( { country => $args[0] } );
0ef52a96 153 if ( $c->req->params->{bar} ) { # access GET or POST parameters
154 $c->forward( 'bar' ); # process another action
ac5c933b 155 # do something else after forward returns
0ef52a96 156 }
157 }
ac5c933b 158
ae1e6b59 159 # The foo.tt TT template can use the stash data from the database
0ef52a96 160 [% WHILE (item = data.next) %]
161 [% item.foo %]
162 [% END %]
ac5c933b 163
0ef52a96 164 # called for /bar/of/soap, /bar/of/soap/10, etc.
165 sub bar : Path('/bar/of/soap') { ... }
fc7ec1d9 166
ae1e6b59 167 # called for all actions, from the top-most controller downwards
ac5c933b 168 sub auto : Private {
0ef52a96 169 my ( $self, $c ) = @_;
b4b01a8a 170 if ( !$c->user_exists ) { # Catalyst::Plugin::Authentication
0ef52a96 171 $c->res->redirect( '/login' ); # require login
172 return 0; # abort request and go immediately to end()
173 }
ae1e6b59 174 return 1; # success; carry on to next action
0ef52a96 175 }
ac5c933b 176
ae1e6b59 177 # called after all actions are finished
ac5c933b 178 sub end : Private {
5a8ed4fe 179 my ( $self, $c ) = @_;
0ef52a96 180 if ( scalar @{ $c->error } ) { ... } # handle errors
181 return if $c->res->body; # already have a response
182 $c->forward( 'MyApp::View::TT' ); # render template
5a8ed4fe 183 }
184
0ef52a96 185 ### in MyApp/Controller/Foo.pm
186 # called for /foo/bar
187 sub bar : Local { ... }
ac5c933b 188
5400c668 189 # called for /blargle
190 sub blargle : Global { ... }
ac5c933b 191
5400c668 192 # an index action matches /foo, but not /foo/1, etc.
193 sub index : Private { ... }
ac5c933b 194
0ef52a96 195 ### in MyApp/Controller/Foo/Bar.pm
196 # called for /foo/bar/baz
197 sub baz : Local { ... }
ac5c933b 198
b4b01a8a 199 # first Root auto is called, then Foo auto, then this
0ef52a96 200 sub auto : Private { ... }
ac5c933b 201
0ef52a96 202 # powerful regular expression paths are also possible
203 sub details : Regex('^product/(\w+)/details$') {
5a8ed4fe 204 my ( $self, $c ) = @_;
0ef52a96 205 # extract the (\w+) from the URI
2982e768 206 my $product = $c->req->captures->[0];
5a8ed4fe 207 }
fc7ec1d9 208
0ef52a96 209See L<Catalyst::Manual::Intro> for additional information.
3803e98f 210
fc7ec1d9 211=head1 DESCRIPTION
212
86418559 213Catalyst is a modern framework for making web applications without the
214pain usually associated with this process. This document is a reference
215to the main Catalyst application. If you are a new user, we suggest you
216start with L<Catalyst::Manual::Tutorial> or L<Catalyst::Manual::Intro>.
fc7ec1d9 217
218See L<Catalyst::Manual> for more documentation.
219
ae1e6b59 220Catalyst plugins can be loaded by naming them as arguments to the "use
221Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the
222plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes
223C<My::Module>.
fc7ec1d9 224
0ef52a96 225 use Catalyst qw/My::Module/;
fc7ec1d9 226
836e1134 227If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
228fully qualify the name by using a unary plus:
229
230 use Catalyst qw/
231 My::Module
232 +Fully::Qualified::Plugin::Name
233 /;
234
ae1e6b59 235Special flags like C<-Debug> and C<-Engine> can also be specified as
236arguments when Catalyst is loaded:
fc7ec1d9 237
238 use Catalyst qw/-Debug My::Module/;
239
ae1e6b59 240The position of plugins and flags in the chain is important, because
86418559 241they are loaded in the order in which they appear.
fc7ec1d9 242
23f9d934 243The following flags are supported:
244
b5ecfcf0 245=head2 -Debug
23f9d934 246
f8ad6ea5 247Enables debug output. You can also force this setting from the system
86418559 248environment with CATALYST_DEBUG or <MYAPP>_DEBUG. The environment
249settings override the application, with <MYAPP>_DEBUG having the highest
250priority.
fc7ec1d9 251
b5ecfcf0 252=head2 -Engine
fc7ec1d9 253
ae1e6b59 254Forces Catalyst to use a specific engine. Omit the
255C<Catalyst::Engine::> prefix of the engine name, i.e.:
fc7ec1d9 256
0ef52a96 257 use Catalyst qw/-Engine=CGI/;
fc7ec1d9 258
b5ecfcf0 259=head2 -Home
fbcc39ad 260
ae1e6b59 261Forces Catalyst to use a specific home directory, e.g.:
262
86418559 263 use Catalyst qw[-Home=/usr/mst];
fbcc39ad 264
cc95842f 265This can also be done in the shell environment by setting either the
266C<CATALYST_HOME> environment variable or C<MYAPP_HOME>; where C<MYAPP>
267is replaced with the uppercased name of your application, any "::" in
268the name will be replaced with underscores, e.g. MyApp::Web should use
269MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used.
270
b5ecfcf0 271=head2 -Log
fbcc39ad 272
0fa676a7 273 use Catalyst '-Log=warn,fatal,error';
274
275Specifies a comma-delimited list of log levels.
fbcc39ad 276
dc5f035e 277=head2 -Stats
278
279Enables statistics collection and reporting. You can also force this setting
280from the system environment with CATALYST_STATS or <MYAPP>_STATS. The
281environment settings override the application, with <MYAPP>_STATS having the
282highest priority.
283
ac5c933b 284e.g.
dc5f035e 285
286 use Catalyst qw/-Stats=1/
287
23f9d934 288=head1 METHODS
289
f7b672ef 290=head2 INFORMATION ABOUT THE CURRENT REQUEST
0ef52a96 291
b5ecfcf0 292=head2 $c->action
66e28e3f 293
ae1e6b59 294Returns a L<Catalyst::Action> object for the current action, which
295stringifies to the action name. See L<Catalyst::Action>.
0ef52a96 296
b5ecfcf0 297=head2 $c->namespace
0ef52a96 298
86418559 299Returns the namespace of the current action, i.e., the URI prefix
ae1e6b59 300corresponding to the controller of the current action. For example:
301
302 # in Controller::Foo::Bar
303 $c->namespace; # returns 'foo/bar';
0ef52a96 304
b5ecfcf0 305=head2 $c->request
0ef52a96 306
b5ecfcf0 307=head2 $c->req
0ef52a96 308
86418559 309Returns the current L<Catalyst::Request> object, giving access to
310information about the current client request (including parameters,
311cookies, HTTP headers, etc.). See L<Catalyst::Request>.
0ef52a96 312
b4b01a8a 313=head2 REQUEST FLOW HANDLING
0ef52a96 314
b5ecfcf0 315=head2 $c->forward( $action [, \@arguments ] )
0ef52a96 316
b5ecfcf0 317=head2 $c->forward( $class, $method, [, \@arguments ] )
0ef52a96 318
86418559 319Forwards processing to another action, by its private name. If you give a
b4b01a8a 320class name but no method, C<process()> is called. You may also optionally
321pass arguments in an arrayref. The action will receive the arguments in
cc95842f 322C<@_> and C<< $c->req->args >>. Upon returning from the function,
323C<< $c->req->args >> will be restored to the previous values.
0ef52a96 324
3b984c64 325Any data C<return>ed from the action forwarded to, will be returned by the
d759db1e 326call to forward.
3b984c64 327
328 my $foodata = $c->forward('/foo');
0ef52a96 329 $c->forward('index');
e112461a 330 $c->forward(qw/MyApp::Model::DBIC::Foo do_stuff/);
0ef52a96 331 $c->forward('MyApp::View::TT');
332
86418559 333Note that forward implies an C<<eval { }>> around the call (actually
334C<execute> does), thus de-fatalizing all 'dies' within the called
335action. If you want C<die> to propagate you need to do something like:
f3e6a8c0 336
337 $c->forward('foo');
338 die $c->error if $c->error;
339
86418559 340Or make sure to always return true values from your actions and write
341your code like this:
f3e6a8c0 342
343 $c->forward('foo') || return;
344
0ef52a96 345=cut
346
6680c772 347sub forward { my $c = shift; no warnings 'recursion'; $c->dispatcher->forward( $c, @_ ) }
0ef52a96 348
b5ecfcf0 349=head2 $c->detach( $action [, \@arguments ] )
0ef52a96 350
b5ecfcf0 351=head2 $c->detach( $class, $method, [, \@arguments ] )
0ef52a96 352
264bac8c 353=head2 $c->detach()
354
ac5c933b 355The same as C<forward>, but doesn't return to the previous action when
356processing is finished.
0ef52a96 357
264bac8c 358When called with no arguments it escapes the processing chain entirely.
359
0ef52a96 360=cut
361
362sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
363
5d91ffe2 364=head2 $c->visit( $action [, \@captures, \@arguments ] )
ae0e35ee 365
5d91ffe2 366=head2 $c->visit( $class, $method, [, \@captures, \@arguments ] )
ae0e35ee 367
368Almost the same as C<forward>, but does a full dispatch, instead of just
369calling the new C<$action> / C<$class-E<gt>$method>. This means that C<begin>,
370C<auto> and the method you go to are called, just like a new request.
371
4b48773e 372In addition both C<< $c->action >> and C<< $c->namespace >> are localized.
373This means, for example, that $c->action methods such as C<name>, C<class> and
374C<reverse> return information for the visited action when they are invoked
375within the visited action. This is different from the behavior of C<forward>
376which continues to use the $c->action object from the caller action even when
377invoked from the callee.
378
ae0e35ee 379C<$c-E<gt>stash> is kept unchanged.
380
381In effect, C<visit> allows you to "wrap" another action, just as it
382would have been called by dispatching from a URL, while the analogous
383C<go> allows you to transfer control to another action as if it had
384been reached directly from a URL.
385
386=cut
387
388sub visit { my $c = shift; $c->dispatcher->visit( $c, @_ ) }
389
5d91ffe2 390=head2 $c->go( $action [, \@captures, \@arguments ] )
2f381252 391
5d91ffe2 392=head2 $c->go( $class, $method, [, \@captures, \@arguments ] )
2f381252 393
ae0e35ee 394Almost the same as C<detach>, but does a full dispatch like C<visit>,
395instead of just calling the new C<$action> /
396C<$class-E<gt>$method>. This means that C<begin>, C<auto> and the
397method you visit are called, just like a new request.
2f381252 398
399C<$c-E<gt>stash> is kept unchanged.
400
401=cut
402
403sub go { my $c = shift; $c->dispatcher->go( $c, @_ ) }
404
b4b01a8a 405=head2 $c->response
406
407=head2 $c->res
408
cc95842f 409Returns the current L<Catalyst::Response> object, see there for details.
b4b01a8a 410
411=head2 $c->stash
412
413Returns a hashref to the stash, which may be used to store data and pass
414it between components during a request. You can also set hash keys by
415passing arguments. The stash is automatically sent to the view. The
416stash is cleared at the end of a request; it cannot be used for
86418559 417persistent storage (for this you must use a session; see
418L<Catalyst::Plugin::Session> for a complete system integrated with
419Catalyst).
b4b01a8a 420
421 $c->stash->{foo} = $bar;
422 $c->stash( { moose => 'majestic', qux => 0 } );
423 $c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref
ac5c933b 424
b4b01a8a 425 # stash is automatically passed to the view for use in a template
cc95842f 426 $c->forward( 'MyApp::View::TT' );
b4b01a8a 427
428=cut
429
4090e3bb 430around stash => sub {
431 my $orig = shift;
b4b01a8a 432 my $c = shift;
4090e3bb 433 my $stash = $orig->($c);
b4b01a8a 434 if (@_) {
4090e3bb 435 my $new_stash = @_ > 1 ? {@_} : $_[0];
436 croak('stash takes a hash or hashref') unless ref $new_stash;
437 foreach my $key ( keys %$new_stash ) {
438 $stash->{$key} = $new_stash->{$key};
b4b01a8a 439 }
440 }
0fc2d522 441
4090e3bb 442 return $stash;
443};
0fc2d522 444
b4b01a8a 445
b5ecfcf0 446=head2 $c->error
0ef52a96 447
b5ecfcf0 448=head2 $c->error($error, ...)
0ef52a96 449
b5ecfcf0 450=head2 $c->error($arrayref)
0ef52a96 451
83a8fcac 452Returns an arrayref containing error messages. If Catalyst encounters an
453error while processing a request, it stores the error in $c->error. This
e7ad3b81 454method should only be used to store fatal error messages.
0ef52a96 455
456 my @error = @{ $c->error };
457
458Add a new error.
459
460 $c->error('Something bad happened');
461
0ef52a96 462=cut
463
464sub error {
465 my $c = shift;
466 if ( $_[0] ) {
467 my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
9ce44430 468 croak @$error unless ref $c;
0ef52a96 469 push @{ $c->{error} }, @$error;
470 }
471 elsif ( defined $_[0] ) { $c->{error} = undef }
472 return $c->{error} || [];
473}
474
b4b01a8a 475
476=head2 $c->state
477
478Contains the return value of the last executed action.
479
ca81eb67 480=head2 $c->clear_errors
481
482Clear errors. You probably don't want to clear the errors unless you are
483implementing a custom error screen.
484
485This is equivalent to running
486
487 $c->error(0);
488
489=cut
490
491sub clear_errors {
492 my $c = shift;
493 $c->error(0);
494}
495
2f381252 496# search components given a name and some prefixes
497sub _comp_search_prefixes {
498 my ( $c, $name, @prefixes ) = @_;
499 my $appclass = ref $c || $c;
500 my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::';
cce626ed 501 $filter = qr/$filter/; # Compile regex now rather than once per loop
0ef52a96 502
2f381252 503 # map the original component name to the sub part that we will search against
504 my %eligible = map { my $n = $_; $n =~ s{^$appclass\::[^:]+::}{}; $_ => $n; }
505 grep { /$filter/ } keys %{ $c->components };
0756fe3b 506
2f381252 507 # undef for a name will return all
508 return keys %eligible if !defined $name;
0756fe3b 509
2f381252 510 my $query = ref $name ? $name : qr/^$name$/i;
511 my @result = grep { $eligible{$_} =~ m{$query} } keys %eligible;
0756fe3b 512
2f381252 513 return map { $c->components->{ $_ } } @result if @result;
0756fe3b 514
2f381252 515 # if we were given a regexp to search against, we're done.
516 return if ref $name;
0756fe3b 517
2f381252 518 # regexp fallback
519 $query = qr/$name/i;
520 @result = map { $c->components->{ $_ } } grep { $eligible{ $_ } =~ m{$query} } keys %eligible;
0756fe3b 521
2f381252 522 # no results? try against full names
523 if( !@result ) {
524 @result = map { $c->components->{ $_ } } grep { m{$query} } keys %eligible;
525 }
0756fe3b 526
2f381252 527 # don't warn if we didn't find any results, it just might not exist
528 if( @result ) {
cce626ed 529 # Disgusting hack to work out correct method name
530 my $warn_for = lc $prefixes[0];
531 my $msg = "Used regexp fallback for \$c->{$warn_for}('${name}'), which found '" .
108201b5 532 (join '", "', @result) . "'. Relying on regexp fallback behavior for " .
533 "component resolution is unreliable and unsafe.";
534 my $short = $result[0];
535 $short =~ s/.*?Model:://;
536 my $shortmess = Carp::shortmess('');
537 if ($shortmess =~ m#Catalyst/Plugin#) {
538 $msg .= " You probably need to set '$short' instead of '${name}' in this " .
539 "plugin's config";
540 } elsif ($shortmess =~ m#Catalyst/lib/(View|Controller)#) {
541 $msg .= " You probably need to set '$short' instead of '${name}' in this " .
542 "component's config";
543 } else {
cce626ed 544 $msg .= " You probably meant \$c->${warn_for}('$short') instead of \$c->${warn_for}({'${name}'}), " .
108201b5 545 "but if you really wanted to search, pass in a regexp as the argument " .
cce626ed 546 "like so: \$c->${warn_for}(qr/${name}/)";
108201b5 547 }
548 $c->log->warn( "${msg}$shortmess" );
2f381252 549 }
0756fe3b 550
2f381252 551 return @result;
0756fe3b 552}
553
ac5c933b 554# Find possible names for a prefix
3b88a455 555sub _comp_names {
556 my ( $c, @prefixes ) = @_;
3b88a455 557 my $appclass = ref $c || $c;
558
2f381252 559 my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::';
3b88a455 560
2f381252 561 my @names = map { s{$filter}{}; $_; } $c->_comp_search_prefixes( undef, @prefixes );
3b88a455 562 return @names;
563}
564
197bd788 565# Filter a component before returning by calling ACCEPT_CONTEXT if available
566sub _filter_component {
567 my ( $c, $comp, @args ) = @_;
2f381252 568
8abaac85 569 if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
197bd788 570 return $comp->ACCEPT_CONTEXT( $c, @args );
571 }
2f381252 572
573 return $comp;
197bd788 574}
575
f7b672ef 576=head2 COMPONENT ACCESSORS
0ef52a96 577
b5ecfcf0 578=head2 $c->controller($name)
af3ff00e 579
0ef52a96 580Gets a L<Catalyst::Controller> instance by name.
af3ff00e 581
582 $c->controller('Foo')->do_stuff;
583
86418559 584If the name is omitted, will return the controller for the dispatched
585action.
649fd1fa 586
2f381252 587If you want to search for controllers, pass in a regexp as the argument.
588
589 # find all controllers that start with Foo
590 my @foo_controllers = $c->controller(qr{^Foo});
591
592
af3ff00e 593=cut
594
595sub controller {
197bd788 596 my ( $c, $name, @args ) = @_;
2f381252 597
598 if( $name ) {
599 my @result = $c->_comp_search_prefixes( $name, qw/Controller C/ );
600 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
601 return $c->_filter_component( $result[ 0 ], @args );
602 }
603
197bd788 604 return $c->component( $c->action->class );
af3ff00e 605}
606
b5ecfcf0 607=head2 $c->model($name)
fc7ec1d9 608
0ef52a96 609Gets a L<Catalyst::Model> instance by name.
610
611 $c->model('Foo')->do_stuff;
fc7ec1d9 612
72f87c4b 613Any extra arguments are directly passed to ACCEPT_CONTEXT.
614
ac5c933b 615If the name is omitted, it will look for
2f381252 616 - a model object in $c->stash->{current_model_instance}, then
a3b71f0f 617 - a model name in $c->stash->{current_model}, then
618 - a config setting 'default_model', or
619 - check if there is only one model, and return it if that's the case.
649fd1fa 620
2f381252 621If you want to search for models, pass in a regexp as the argument.
622
623 # find all models that start with Foo
624 my @foo_models = $c->model(qr{^Foo});
625
fc7ec1d9 626=cut
627
0ef52a96 628sub model {
197bd788 629 my ( $c, $name, @args ) = @_;
2f381252 630
631 if( $name ) {
632 my @result = $c->_comp_search_prefixes( $name, qw/Model M/ );
633 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
634 return $c->_filter_component( $result[ 0 ], @args );
635 }
636
a3b71f0f 637 if (ref $c) {
ac5c933b 638 return $c->stash->{current_model_instance}
a3b71f0f 639 if $c->stash->{current_model_instance};
640 return $c->model( $c->stash->{current_model} )
641 if $c->stash->{current_model};
a3b71f0f 642 }
72f87c4b 643 return $c->model( $c->config->{default_model} )
644 if $c->config->{default_model};
3b88a455 645
2f381252 646 my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/Model M/);
3b88a455 647
2f381252 648 if( $rest ) {
108201b5 649 $c->log->warn( Carp::shortmess('Calling $c->model() will return a random model unless you specify one of:') );
2f381252 650 $c->log->warn( '* $c->config->{default_model} # the name of the default model to use' );
651 $c->log->warn( '* $c->stash->{current_model} # the name of the model to use for this request' );
652 $c->log->warn( '* $c->stash->{current_model_instance} # the instance of the model to use for this request' );
11c270bd 653 $c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' );
2f381252 654 }
3b88a455 655
2f381252 656 return $c->_filter_component( $comp );
3b88a455 657}
658
b4b01a8a 659
b5ecfcf0 660=head2 $c->view($name)
0ef52a96 661
662Gets a L<Catalyst::View> instance by name.
fc7ec1d9 663
0ef52a96 664 $c->view('Foo')->do_stuff;
fc7ec1d9 665
72f87c4b 666Any extra arguments are directly passed to ACCEPT_CONTEXT.
667
ac5c933b 668If the name is omitted, it will look for
2f381252 669 - a view object in $c->stash->{current_view_instance}, then
a3b71f0f 670 - a view name in $c->stash->{current_view}, then
671 - a config setting 'default_view', or
672 - check if there is only one view, and return it if that's the case.
649fd1fa 673
2f381252 674If you want to search for views, pass in a regexp as the argument.
675
676 # find all views that start with Foo
677 my @foo_views = $c->view(qr{^Foo});
678
fc7ec1d9 679=cut
680
0ef52a96 681sub view {
197bd788 682 my ( $c, $name, @args ) = @_;
2f381252 683
684 if( $name ) {
685 my @result = $c->_comp_search_prefixes( $name, qw/View V/ );
686 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
687 return $c->_filter_component( $result[ 0 ], @args );
688 }
689
a3b71f0f 690 if (ref $c) {
ac5c933b 691 return $c->stash->{current_view_instance}
a3b71f0f 692 if $c->stash->{current_view_instance};
693 return $c->view( $c->stash->{current_view} )
694 if $c->stash->{current_view};
a3b71f0f 695 }
72f87c4b 696 return $c->view( $c->config->{default_view} )
697 if $c->config->{default_view};
2f381252 698
699 my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/View V/);
700
701 if( $rest ) {
702 $c->log->warn( 'Calling $c->view() will return a random view unless you specify one of:' );
703 $c->log->warn( '* $c->config->{default_view} # the name of the default view to use' );
704 $c->log->warn( '* $c->stash->{current_view} # the name of the view to use for this request' );
705 $c->log->warn( '* $c->stash->{current_view_instance} # the instance of the view to use for this request' );
11c270bd 706 $c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' );
2f381252 707 }
708
709 return $c->_filter_component( $comp );
710}
711
712=head2 $c->controllers
713
714Returns the available names which can be passed to $c->controller
715
716=cut
717
718sub controllers {
719 my ( $c ) = @_;
720 return $c->_comp_names(qw/Controller C/);
0ef52a96 721}
fbcc39ad 722
b4b01a8a 723=head2 $c->models
724
725Returns the available names which can be passed to $c->model
726
727=cut
728
729sub models {
730 my ( $c ) = @_;
731 return $c->_comp_names(qw/Model M/);
732}
733
734
3b88a455 735=head2 $c->views
736
737Returns the available names which can be passed to $c->view
738
739=cut
740
741sub views {
742 my ( $c ) = @_;
743 return $c->_comp_names(qw/View V/);
744}
745
b4b01a8a 746=head2 $c->comp($name)
747
748=head2 $c->component($name)
749
cc95842f 750Gets a component object by name. This method is not recommended,
b4b01a8a 751unless you want to get a specific component by full
cc95842f 752class. C<< $c->controller >>, C<< $c->model >>, and C<< $c->view >>
b4b01a8a 753should be used instead.
754
2f381252 755If C<$name> is a regexp, a list of components matched against the full
756component name will be returned.
757
b4b01a8a 758=cut
759
760sub component {
2f381252 761 my ( $c, $name, @args ) = @_;
b4b01a8a 762
2f381252 763 if( $name ) {
764 my $comps = $c->components;
b4b01a8a 765
2f381252 766 if( !ref $name ) {
767 # is it the exact name?
768 return $c->_filter_component( $comps->{ $name }, @args )
769 if exists $comps->{ $name };
b4b01a8a 770
2f381252 771 # perhaps we just omitted "MyApp"?
772 my $composed = ( ref $c || $c ) . "::${name}";
773 return $c->_filter_component( $comps->{ $composed }, @args )
774 if exists $comps->{ $composed };
b4b01a8a 775
2f381252 776 # search all of the models, views and controllers
777 my( $comp ) = $c->_comp_search_prefixes( $name, qw/Model M Controller C View V/ );
778 return $c->_filter_component( $comp, @args ) if $comp;
779 }
780
781 # This is here so $c->comp( '::M::' ) works
782 my $query = ref $name ? $name : qr{$name}i;
b4b01a8a 783
2f381252 784 my @result = grep { m{$query} } keys %{ $c->components };
785 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
b4b01a8a 786
2f381252 787 if( $result[ 0 ] ) {
108201b5 788 $c->log->warn( Carp::shortmess(qq(Found results for "${name}" using regexp fallback)) );
2f381252 789 $c->log->warn( 'Relying on the regexp fallback behavior for component resolution' );
790 $c->log->warn( 'is unreliable and unsafe. You have been warned' );
791 return $c->_filter_component( $result[ 0 ], @args );
792 }
793
794 # I would expect to return an empty list here, but that breaks back-compat
b4b01a8a 795 }
796
2f381252 797 # fallback
b4b01a8a 798 return sort keys %{ $c->components };
799}
800
b4b01a8a 801=head2 CLASS DATA AND HELPER CLASSES
fbcc39ad 802
b5ecfcf0 803=head2 $c->config
fbcc39ad 804
0ef52a96 805Returns or takes a hashref containing the application's configuration.
806
61b1d329 807 __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } );
81557adf 808
cc95842f 809You can also use a C<YAML>, C<XML> or C<Config::General> config file
810like myapp.yml in your applications home directory. See
811L<Catalyst::Plugin::ConfigLoader>.
a6ad13b6 812
813 ---
814 db: dsn:SQLite:foo.db
815
b4b01a8a 816
3643e890 817=cut
818
4090e3bb 819around config => sub {
820 my $orig = shift;
3643e890 821 my $c = shift;
822
fcf89172 823 croak('Setting config after setup has been run is not allowed.')
824 if ( @_ and $c->setup_finished );
3643e890 825
4090e3bb 826 $c->$orig(@_);
827};
3643e890 828
b5ecfcf0 829=head2 $c->log
0ef52a96 830
86418559 831Returns the logging object instance. Unless it is already set, Catalyst
832sets this up with a L<Catalyst::Log> object. To use your own log class,
833set the logger with the C<< __PACKAGE__->log >> method prior to calling
9e7673af 834C<< __PACKAGE__->setup >>.
835
836 __PACKAGE__->log( MyLogger->new );
837 __PACKAGE__->setup;
838
839And later:
0ef52a96 840
ae1e6b59 841 $c->log->info( 'Now logging with my own logger!' );
0ef52a96 842
86418559 843Your log class should implement the methods described in
844L<Catalyst::Log>.
af3ff00e 845
b4b01a8a 846
847=head2 $c->debug
848
c74d3f0c 849Returns 1 if debug mode is enabled, 0 otherwise.
b4b01a8a 850
7e5c67f2 851You can enable debug mode in several ways:
852
853=over
854
855=item With the environment variables MYAPP_DEBUG, or CATALYST_DEBUG
856
857=item The -Debug option in your MyApp.pm
858
859=item By declaring "sub debug { 1 }" in your MyApp.pm.
860
861=back
c74d3f0c 862
863Calling $c->debug(1) has no effect.
e80e8542 864
af3ff00e 865=cut
866
b4b01a8a 867sub debug { 0 }
868
869=head2 $c->dispatcher
870
2887a7f1 871Returns the dispatcher instance. See L<Catalyst::Dispatcher>.
b4b01a8a 872
873=head2 $c->engine
874
2887a7f1 875Returns the engine instance. See L<Catalyst::Engine>.
b4b01a8a 876
877
f7b672ef 878=head2 UTILITY METHODS
66e28e3f 879
b5ecfcf0 880=head2 $c->path_to(@path)
01033d73 881
cc95842f 882Merges C<@path> with C<< $c->config->{home} >> and returns a
afbb9aa3 883L<Path::Class::Dir> object.
01033d73 884
885For example:
886
887 $c->path_to( 'db', 'sqlite.db' );
888
889=cut
890
891sub path_to {
892 my ( $c, @path ) = @_;
a738ab68 893 my $path = Path::Class::Dir->new( $c->config->{home}, @path );
01033d73 894 if ( -d $path ) { return $path }
a738ab68 895 else { return Path::Class::File->new( $c->config->{home}, @path ) }
01033d73 896}
897
b5ecfcf0 898=head2 $c->plugin( $name, $class, @args )
0ef52a96 899
10011c19 900Helper method for plugins. It creates a class data accessor/mutator and
ae1e6b59 901loads and instantiates the given class.
0ef52a96 902
903 MyApp->plugin( 'prototype', 'HTML::Prototype' );
904
905 $c->prototype->define_javascript_functions;
6b2a933b 906
907B<Note:> This method of adding plugins is deprecated. The ability
908to add plugins like this B<will be removed> in a Catalyst 5.9.
909Please do not use this functionality in new code.
0ef52a96 910
911=cut
912
913sub plugin {
914 my ( $class, $name, $plugin, @args ) = @_;
6b2a933b 915
916 # See block comment in t/unit_core_plugin.t
d6ce7d52 917 $class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in Catalyst 5.9/);
6b2a933b 918
97b58e17 919 $class->_register_plugin( $plugin, 1 );
0ef52a96 920
921 eval { $plugin->import };
922 $class->mk_classdata($name);
923 my $obj;
924 eval { $obj = $plugin->new(@args) };
925
926 if ($@) {
927 Catalyst::Exception->throw( message =>
928 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
929 }
930
931 $class->$name($obj);
932 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
933 if $class->debug;
934}
935
b5ecfcf0 936=head2 MyApp->setup
fbcc39ad 937
e7f1cf73 938Initializes the dispatcher and engine, loads any plugins, and loads the
ae1e6b59 939model, view, and controller components. You may also specify an array
940of plugins to load here, if you choose to not load them in the C<use
941Catalyst> line.
fbcc39ad 942
0ef52a96 943 MyApp->setup;
944 MyApp->setup( qw/-Debug/ );
fbcc39ad 945
946=cut
947
948sub setup {
0319a12c 949 my ( $class, @arguments ) = @_;
c2f3cc1b 950 croak('Running setup more than once')
951 if ( $class->setup_finished );
5168a5fc 952
fbcc39ad 953 unless ( $class->isa('Catalyst') ) {
953b0e15 954
fbcc39ad 955 Catalyst::Exception->throw(
956 message => qq/'$class' does not inherit from Catalyst/ );
1c99e125 957 }
0319a12c 958
fbcc39ad 959 if ( $class->arguments ) {
960 @arguments = ( @arguments, @{ $class->arguments } );
961 }
962
963 # Process options
964 my $flags = {};
965
966 foreach (@arguments) {
967
968 if (/^-Debug$/) {
969 $flags->{log} =
970 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
971 }
972 elsif (/^-(\w+)=?(.*)$/) {
973 $flags->{ lc $1 } = $2;
974 }
975 else {
976 push @{ $flags->{plugins} }, $_;
977 }
978 }
979
99f187d6 980 $class->setup_home( delete $flags->{home} );
981
fbcc39ad 982 $class->setup_log( delete $flags->{log} );
983 $class->setup_plugins( delete $flags->{plugins} );
984 $class->setup_dispatcher( delete $flags->{dispatcher} );
985 $class->setup_engine( delete $flags->{engine} );
dc5f035e 986 $class->setup_stats( delete $flags->{stats} );
fbcc39ad 987
988 for my $flag ( sort keys %{$flags} ) {
989
990 if ( my $code = $class->can( 'setup_' . $flag ) ) {
991 &$code( $class, delete $flags->{$flag} );
992 }
993 else {
994 $class->log->warn(qq/Unknown flag "$flag"/);
995 }
996 }
997
0eb4af72 998 eval { require Catalyst::Devel; };
999 if( !$@ && $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::Devel::CATALYST_SCRIPT_GEN ) ) {
1000 $class->log->warn(<<"EOF");
4ff0d824 1001You are running an old script!
1002
34a83d89 1003 Please update by running (this will overwrite existing files):
1004 catalyst.pl -force -scripts $class
1005
1006 or (this will not overwrite existing files):
1007 catalyst.pl -scripts $class
1cf0345b 1008
4ff0d824 1009EOF
0eb4af72 1010 }
ac5c933b 1011
fbcc39ad 1012 if ( $class->debug ) {
6601f2ad 1013 my @plugins = map { "$_ " . ( $_->VERSION || '' ) } $class->registered_plugins;
fbcc39ad 1014
1015 if (@plugins) {
39fc2ce1 1016 my $column_width = Catalyst::Utils::term_width() - 6;
1017 my $t = Text::SimpleTable->new($column_width);
8c113188 1018 $t->row($_) for @plugins;
1cf0345b 1019 $class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" );
fbcc39ad 1020 }
1021
1022 my $dispatcher = $class->dispatcher;
1023 my $engine = $class->engine;
1024 my $home = $class->config->{home};
1025
01ce7075 1026 $class->log->debug(sprintf(q/Loaded dispatcher "%s"/, blessed($dispatcher)));
1027 $class->log->debug(sprintf(q/Loaded engine "%s"/, blessed($engine)));
fbcc39ad 1028
1029 $home
1030 ? ( -d $home )
1031 ? $class->log->debug(qq/Found home "$home"/)
1032 : $class->log->debug(qq/Home "$home" doesn't exist/)
1033 : $class->log->debug(q/Couldn't find home/);
1034 }
1035
54f4bfef 1036 # Call plugins setup, this is stupid and evil.
fbcc39ad 1037 {
1038 no warnings qw/redefine/;
1039 local *setup = sub { };
1040 $class->setup;
1041 }
1042
1043 # Initialize our data structure
1044 $class->components( {} );
1045
1046 $class->setup_components;
1047
1048 if ( $class->debug ) {
39fc2ce1 1049 my $column_width = Catalyst::Utils::term_width() - 8 - 9;
1050 my $t = Text::SimpleTable->new( [ $column_width, 'Class' ], [ 8, 'Type' ] );
684d10ed 1051 for my $comp ( sort keys %{ $class->components } ) {
1052 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
1053 $t->row( $comp, $type );
1054 }
1cf0345b 1055 $class->log->debug( "Loaded components:\n" . $t->draw . "\n" )
8c113188 1056 if ( keys %{ $class->components } );
fbcc39ad 1057 }
1058
1059 # Add our self to components, since we are also a component
96d8d513 1060 if( $class->isa('Catalyst::Controller') ){
1061 $class->components->{$class} = $class;
1062 }
fbcc39ad 1063
1064 $class->setup_actions;
1065
1066 if ( $class->debug ) {
1067 my $name = $class->config->{name} || 'Application';
1068 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
1069 }
1070 $class->log->_flush() if $class->log->can('_flush');
3643e890 1071
3d041c32 1072 # Make sure that the application class becomes immutable at this point,
1073 # which ensures that it gets an inlined constructor. This means that it
1074 # works even if the user has added a plugin which contains a new method.
1075 # Note however that we have to do the work on scope end, so that method
1076 # modifiers work correctly in MyApp (as you have to call setup _before_
1077 # applying modifiers).
edb20ed3 1078 Scope::Upper::reap(sub {
e106a59f 1079 my $meta = Class::MOP::get_metaclass_by_name($class);
3d041c32 1080 $meta->make_immutable unless $meta->is_immutable;
d134bcca 1081 }, Scope::Upper::SCOPE(1));
3d041c32 1082
a5d07d29 1083 $class->setup_finalize;
1084}
1085
23c63a17 1086
1087=head2 $app->setup_finalize
1088
1089A hook to attach modifiers to.
1090Using C< after setup => sub{}; > doesn't work, because of quirky things done for plugin setup.
1091Also better than C< setup_finished(); >, as that is a getter method.
1092
1093 sub setup_finalize {
1094
1095 my $app = shift;
1096
1097 ## do stuff, i.e., determine a primary key column for sessions stored in a DB
1098
1099 $app->next::method(@_);
1100
1101
1102 }
1103
1104=cut
1105
a5d07d29 1106sub setup_finalize {
1107 my ($class) = @_;
3643e890 1108 $class->setup_finished(1);
fbcc39ad 1109}
1110
8a27f860 1111=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values? )
1112
73664287 1113=head2 $c->uri_for( $path, @args?, \%query_values? )
fbcc39ad 1114
8a27f860 1115=over
fbcc39ad 1116
8a27f860 1117=item $action
8dc69021 1118
8a27f860 1119A Catalyst::Action object representing the Catalyst action you want to
1120create a URI for. To get one for an action in the current controller,
1121use C<< $c->action('someactionname') >>. To get one from different
1122controller, fetch the controller using C<< $c->controller() >>, then
1123call C<action_for> on it.
ea0e58d9 1124
9df7c5d9 1125You can maintain the arguments captured by an action (e.g.: Regex, Chained)
1126using C<< $c->req->captures >>.
1127
1128 # For the current action
1129 $c->uri_for($c->action, $c->req->captures);
1130
1131 # For the Foo action in the Bar controller
1132 $c->uri_for($c->controller->('Bar')->action_for('Foo'), $c->req->captures);
1133
d5e3d528 1134=back
1135
4cf1dd00 1136=cut
1137
fbcc39ad 1138sub uri_for {
00e6a2b7 1139 my ( $c, $path, @args ) = @_;
00e6a2b7 1140
7e95ba12 1141 if ( blessed($path) ) { # action object
ea0e58d9 1142 my $captures = ( scalar @args && ref $args[0] eq 'ARRAY'
1143 ? shift(@args)
1144 : [] );
aa7e913e 1145 my $action = $path;
1146 $path = $c->dispatcher->uri_for_action($action, $captures);
1147 if (not defined $path) {
1148 $c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
1149 if $c->debug;
1150 return undef;
1151 }
81e75875 1152 $path = '/' if $path eq '';
ea0e58d9 1153 }
1154
51674a63 1155 undef($path) if (defined $path && $path eq '');
00e6a2b7 1156
97b58e17 1157 my $params =
1158 ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
8327e2e2 1159
cbb93105 1160 carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
51674a63 1161 s/([^$URI::uric])/$URI::Escape::escapes{$1}/go for @args;
1162
1163 unshift(@args, $path);
1164
1165 unless (defined $path && $path =~ s!^/!!) { # in-place strip
1166 my $namespace = $c->namespace;
1167 if (defined $path) { # cheesy hack to handle path '../foo'
1168 $namespace =~ s{(?:^|/)[^/]+$}{} while $args[0] =~ s{^\.\./}{};
6601f2ad 1169 }
51674a63 1170 unshift(@args, $namespace || '');
1171 }
ac5c933b 1172
189e2a51 1173 # join args with '/', or a blank string
51674a63 1174 my $args = join('/', grep { defined($_) } @args);
1175 $args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
7a2295bc 1176 $args =~ s!^/+!!;
51674a63 1177 my $base = $c->req->base;
1178 my $class = ref($base);
1179 $base =~ s{(?<!/)$}{/};
1180
1181 my $query = '';
1182
1183 if (my @keys = keys %$params) {
1184 # somewhat lifted from URI::_query's query_form
1185 $query = '?'.join('&', map {
2f381252 1186 my $val = $params->{$_};
51674a63 1187 s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
1188 s/ /+/g;
1189 my $key = $_;
51674a63 1190 $val = '' unless defined $val;
1191 (map {
1192 $_ = "$_";
0ce485e9 1193 utf8::encode( $_ ) if utf8::is_utf8($_);
51674a63 1194 # using the URI::Escape pattern here so utf8 chars survive
1195 s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
1196 s/ /+/g;
1197 "${key}=$_"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
1198 } @keys);
1199 }
1200
1201 my $res = bless(\"${base}${args}${query}", $class);
d3e7a648 1202 $res;
fbcc39ad 1203}
1204
b5ecfcf0 1205=head2 $c->welcome_message
ab2374d3 1206
1207Returns the Catalyst welcome HTML page.
1208
1209=cut
1210
1211sub welcome_message {
bf1f2c60 1212 my $c = shift;
1213 my $name = $c->config->{name};
1214 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
1215 my $prefix = Catalyst::Utils::appprefix( ref $c );
80cdbbff 1216 $c->response->content_type('text/html; charset=utf-8');
ab2374d3 1217 return <<"EOF";
80cdbbff 1218<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1219 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1220<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
ab2374d3 1221 <head>
85d9fce6 1222 <meta http-equiv="Content-Language" content="en" />
1223 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
ab2374d3 1224 <title>$name on Catalyst $VERSION</title>
1225 <style type="text/css">
1226 body {
ab2374d3 1227 color: #000;
1228 background-color: #eee;
1229 }
1230 div#content {
1231 width: 640px;
80cdbbff 1232 margin-left: auto;
1233 margin-right: auto;
ab2374d3 1234 margin-top: 10px;
1235 margin-bottom: 10px;
1236 text-align: left;
1237 background-color: #ccc;
1238 border: 1px solid #aaa;
ab2374d3 1239 }
d84c4dab 1240 p, h1, h2 {
ab2374d3 1241 margin-left: 20px;
1242 margin-right: 20px;
16215972 1243 font-family: verdana, tahoma, sans-serif;
ab2374d3 1244 }
d84c4dab 1245 a {
1246 font-family: verdana, tahoma, sans-serif;
1247 }
d114e033 1248 :link, :visited {
1249 text-decoration: none;
1250 color: #b00;
1251 border-bottom: 1px dotted #bbb;
1252 }
1253 :link:hover, :visited:hover {
d114e033 1254 color: #555;
1255 }
ab2374d3 1256 div#topbar {
1257 margin: 0px;
1258 }
3e82a295 1259 pre {
3e82a295 1260 margin: 10px;
1261 padding: 8px;
1262 }
ab2374d3 1263 div#answers {
1264 padding: 8px;
1265 margin: 10px;
d114e033 1266 background-color: #fff;
ab2374d3 1267 border: 1px solid #aaa;
ab2374d3 1268 }
1269 h1 {
33108eaf 1270 font-size: 0.9em;
1271 font-weight: normal;
ab2374d3 1272 text-align: center;
1273 }
1274 h2 {
1275 font-size: 1.0em;
1276 }
1277 p {
1278 font-size: 0.9em;
1279 }
ae7c5252 1280 p img {
1281 float: right;
1282 margin-left: 10px;
1283 }
9619f23c 1284 span#appname {
1285 font-weight: bold;
33108eaf 1286 font-size: 1.6em;
ab2374d3 1287 }
1288 </style>
1289 </head>
1290 <body>
1291 <div id="content">
1292 <div id="topbar">
9619f23c 1293 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
d84c4dab 1294 $VERSION</h1>
ab2374d3 1295 </div>
1296 <div id="answers">
ae7c5252 1297 <p>
80cdbbff 1298 <img src="$logo" alt="Catalyst Logo" />
ae7c5252 1299 </p>
596aaffe 1300 <p>Welcome to the world of Catalyst.
f92fd545 1301 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
1302 framework will make web development something you had
60dd6e1d 1303 never expected it to be: Fun, rewarding, and quick.</p>
ab2374d3 1304 <h2>What to do now?</h2>
4b8cb778 1305 <p>That really depends on what <b>you</b> want to do.
ab2374d3 1306 We do, however, provide you with a few starting points.</p>
1307 <p>If you want to jump right into web development with Catalyst
2f381252 1308 you might want to start with a tutorial.</p>
b607f8a0 1309<pre>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
596aaffe 1310</pre>
1311<p>Afterwards you can go on to check out a more complete look at our features.</p>
1312<pre>
b607f8a0 1313<code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
1314<!-- Something else should go here, but the Catalyst::Manual link seems unhelpful -->
1315</code></pre>
ab2374d3 1316 <h2>What to do next?</h2>
f5681c92 1317 <p>Next it's time to write an actual application. Use the
80cdbbff 1318 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&amp;mode=all">controllers</a>,
60dd6e1d 1319 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&amp;mode=all">models</a>, and
1320 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&amp;mode=all">views</a>;
bf1f2c60 1321 they can save you a lot of work.</p>
1322 <pre><code>script/${prefix}_create.pl -help</code></pre>
1323 <p>Also, be sure to check out the vast and growing
802bf2cb 1324 collection of <a href="http://search.cpan.org/search?query=Catalyst">plugins for Catalyst on CPAN</a>;
bf1f2c60 1325 you are likely to find what you need there.
f5681c92 1326 </p>
1327
82245cc4 1328 <h2>Need help?</h2>
f5681c92 1329 <p>Catalyst has a very active community. Here are the main places to
1330 get in touch with us.</p>
16215972 1331 <ul>
1332 <li>
2b9a7d76 1333 <a href="http://dev.catalyst.perl.org">Wiki</a>
16215972 1334 </li>
1335 <li>
6d4c3368 1336 <a href="http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst">Mailing-List</a>
16215972 1337 </li>
1338 <li>
4eaf7c88 1339 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
16215972 1340 </li>
1341 </ul>
ab2374d3 1342 <h2>In conclusion</h2>
ac5c933b 1343 <p>The Catalyst team hopes you will enjoy using Catalyst as much
f5681c92 1344 as we enjoyed making it. Please contact us if you have ideas
1345 for improvement or other feedback.</p>
ab2374d3 1346 </div>
1347 </div>
1348 </body>
1349</html>
1350EOF
1351}
1352
fbcc39ad 1353=head1 INTERNAL METHODS
1354
ae1e6b59 1355These methods are not meant to be used by end users.
1356
b5ecfcf0 1357=head2 $c->components
fbcc39ad 1358
e7f1cf73 1359Returns a hash of components.
fbcc39ad 1360
b5ecfcf0 1361=head2 $c->context_class
1f9cb7c1 1362
e7f1cf73 1363Returns or sets the context class.
1f9cb7c1 1364
b5ecfcf0 1365=head2 $c->counter
fbcc39ad 1366
ae1e6b59 1367Returns a hashref containing coderefs and execution counts (needed for
1368deep recursion detection).
fbcc39ad 1369
b5ecfcf0 1370=head2 $c->depth
fbcc39ad 1371
e7f1cf73 1372Returns the number of actions on the current internal execution stack.
fbcc39ad 1373
b5ecfcf0 1374=head2 $c->dispatch
fbcc39ad 1375
e7f1cf73 1376Dispatches a request to actions.
fbcc39ad 1377
1378=cut
1379
1380sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
1381
b5ecfcf0 1382=head2 $c->dispatcher_class
1f9cb7c1 1383
e7f1cf73 1384Returns or sets the dispatcher class.
1f9cb7c1 1385
b5ecfcf0 1386=head2 $c->dump_these
7f92deef 1387
ae1e6b59 1388Returns a list of 2-element array references (name, structure) pairs
1389that will be dumped on the error page in debug mode.
7f92deef 1390
1391=cut
1392
1393sub dump_these {
1394 my $c = shift;
ac5c933b 1395 [ Request => $c->req ],
1396 [ Response => $c->res ],
052a2d89 1397 [ Stash => $c->stash ],
1398 [ Config => $c->config ];
7f92deef 1399}
1400
b5ecfcf0 1401=head2 $c->engine_class
1f9cb7c1 1402
e7f1cf73 1403Returns or sets the engine class.
1f9cb7c1 1404
b5ecfcf0 1405=head2 $c->execute( $class, $coderef )
fbcc39ad 1406
0ef52a96 1407Execute a coderef in given class and catch exceptions. Errors are available
1408via $c->error.
fbcc39ad 1409
1410=cut
1411
1412sub execute {
1413 my ( $c, $class, $code ) = @_;
858828dd 1414 $class = $c->component($class) || $class;
fbcc39ad 1415 $c->state(0);
a0eca838 1416
197bd788 1417 if ( $c->depth >= $RECURSION ) {
f3414019 1418 my $action = $code->reverse();
91d08727 1419 $action = "/$action" unless $action =~ /->/;
f3414019 1420 my $error = qq/Deep recursion detected calling "${action}"/;
1627551a 1421 $c->log->error($error);
1422 $c->error($error);
1423 $c->state(0);
1424 return $c->state;
1425 }
1426
dc5f035e 1427 my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats;
22247e54 1428
8767c5a3 1429 push( @{ $c->stack }, $code );
ac5c933b 1430
f3414019 1431 eval { $c->state( $code->execute( $class, $c, @{ $c->req->args } ) || 0 ) };
22247e54 1432
dc5f035e 1433 $c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info;
ac5c933b 1434
a6724a82 1435 my $last = pop( @{ $c->stack } );
fbcc39ad 1436
1437 if ( my $error = $@ ) {
2f381252 1438 if ( !ref($error) and $error eq $DETACH ) {
1439 die $DETACH if($c->depth > 1);
1440 }
55424863 1441 elsif ( !ref($error) and $error eq $GO ) {
1442 die $GO if($c->depth > 0);
1443 }
fbcc39ad 1444 else {
1445 unless ( ref $error ) {
91d08727 1446 no warnings 'uninitialized';
fbcc39ad 1447 chomp $error;
f59def82 1448 my $class = $last->class;
1449 my $name = $last->name;
1450 $error = qq/Caught exception in $class->$name "$error"/;
fbcc39ad 1451 }
fbcc39ad 1452 $c->error($error);
1453 $c->state(0);
1454 }
1455 }
1456 return $c->state;
1457}
1458
7a7d7af5 1459sub _stats_start_execute {
1460 my ( $c, $code ) = @_;
1461
a6724a82 1462 return if ( ( $code->name =~ /^_.*/ )
1463 && ( !$c->config->{show_internal_actions} ) );
7a7d7af5 1464
f3414019 1465 my $action_name = $code->reverse();
1466 $c->counter->{$action_name}++;
7a7d7af5 1467
f3414019 1468 my $action = $action_name;
a6724a82 1469 $action = "/$action" unless $action =~ /->/;
1470
7a7d7af5 1471 # determine if the call was the result of a forward
1472 # this is done by walking up the call stack and looking for a calling
1473 # sub of Catalyst::forward before the eval
1474 my $callsub = q{};
1475 for my $index ( 2 .. 11 ) {
1476 last
1477 if ( ( caller($index) )[0] eq 'Catalyst'
1478 && ( caller($index) )[3] eq '(eval)' );
1479
1480 if ( ( caller($index) )[3] =~ /forward$/ ) {
1481 $callsub = ( caller($index) )[3];
1482 $action = "-> $action";
1483 last;
1484 }
1485 }
1486
f3414019 1487 my $uid = $action_name . $c->counter->{$action_name};
74efc144 1488
a6724a82 1489 # is this a root-level call or a forwarded call?
1490 if ( $callsub =~ /forward$/ ) {
1491
1492 # forward, locate the caller
1493 if ( my $parent = $c->stack->[-1] ) {
69d8f33c 1494 $c->stats->profile(
ac5c933b 1495 begin => $action,
69d8f33c 1496 parent => "$parent" . $c->counter->{"$parent"},
1497 uid => $uid,
1498 );
7a7d7af5 1499 }
1500 else {
1501
a6724a82 1502 # forward with no caller may come from a plugin
69d8f33c 1503 $c->stats->profile(
1504 begin => $action,
1505 uid => $uid,
1506 );
7a7d7af5 1507 }
1508 }
a6724a82 1509 else {
ac5c933b 1510
a6724a82 1511 # root-level call
69d8f33c 1512 $c->stats->profile(
1513 begin => $action,
1514 uid => $uid,
1515 );
a6724a82 1516 }
dc5f035e 1517 return $action;
7a7d7af5 1518
7a7d7af5 1519}
1520
1521sub _stats_finish_execute {
1522 my ( $c, $info ) = @_;
69d8f33c 1523 $c->stats->profile( end => $info );
7a7d7af5 1524}
1525
3d0d6d21 1526=head2 $c->_localize_fields( sub { }, \%keys );
1527
1528=cut
1529
e63bdf38 1530#Why does this exist? This is no longer safe and WILL NOT WORK.
1531# it doesnt seem to be used anywhere. can we remove it?
3d0d6d21 1532sub _localize_fields {
1533 my ( $c, $localized, $code ) = ( @_ );
1534
1535 my $request = delete $localized->{request} || {};
1536 my $response = delete $localized->{response} || {};
ac5c933b 1537
3d0d6d21 1538 local @{ $c }{ keys %$localized } = values %$localized;
1539 local @{ $c->request }{ keys %$request } = values %$request;
1540 local @{ $c->response }{ keys %$response } = values %$response;
1541
1542 $code->();
1543}
1544
b5ecfcf0 1545=head2 $c->finalize
fbcc39ad 1546
e7f1cf73 1547Finalizes the request.
fbcc39ad 1548
1549=cut
1550
1551sub finalize {
1552 my $c = shift;
1553
369c09bc 1554 for my $error ( @{ $c->error } ) {
1555 $c->log->error($error);
1556 }
1557
5050d7a7 1558 # Allow engine to handle finalize flow (for POE)
e63bdf38 1559 my $engine = $c->engine;
1560 if ( my $code = $engine->can('finalize') ) {
1561 $engine->$code($c);
fbcc39ad 1562 }
5050d7a7 1563 else {
fbcc39ad 1564
5050d7a7 1565 $c->finalize_uploads;
fbcc39ad 1566
5050d7a7 1567 # Error
1568 if ( $#{ $c->error } >= 0 ) {
1569 $c->finalize_error;
1570 }
1571
1572 $c->finalize_headers;
fbcc39ad 1573
5050d7a7 1574 # HEAD request
1575 if ( $c->request->method eq 'HEAD' ) {
1576 $c->response->body('');
1577 }
1578
1579 $c->finalize_body;
1580 }
ac5c933b 1581
1582 if ($c->use_stats) {
596677b6 1583 my $elapsed = sprintf '%f', $c->stats->elapsed;
12bf12c0 1584 my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
908e3d9e 1585 $c->log->info(
ac5c933b 1586 "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
908e3d9e 1587 }
fbcc39ad 1588
1589 return $c->response->status;
1590}
1591
b5ecfcf0 1592=head2 $c->finalize_body
fbcc39ad 1593
e7f1cf73 1594Finalizes body.
fbcc39ad 1595
1596=cut
1597
1598sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1599
b5ecfcf0 1600=head2 $c->finalize_cookies
fbcc39ad 1601
e7f1cf73 1602Finalizes cookies.
fbcc39ad 1603
1604=cut
1605
147821ea 1606sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
fbcc39ad 1607
b5ecfcf0 1608=head2 $c->finalize_error
fbcc39ad 1609
e7f1cf73 1610Finalizes error.
fbcc39ad 1611
1612=cut
1613
1614sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1615
b5ecfcf0 1616=head2 $c->finalize_headers
fbcc39ad 1617
e7f1cf73 1618Finalizes headers.
fbcc39ad 1619
1620=cut
1621
1622sub finalize_headers {
1623 my $c = shift;
1624
e63bdf38 1625 my $response = $c->response; #accessor calls can add up?
1626
fbcc39ad 1627 # Check if we already finalized headers
6680c772 1628 return if $response->finalized_headers;
fbcc39ad 1629
1630 # Handle redirects
e63bdf38 1631 if ( my $location = $response->redirect ) {
fbcc39ad 1632 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
e63bdf38 1633 $response->header( Location => $location );
a7caa492 1634
02570318 1635 if ( !$response->has_body ) {
39655cdc 1636 # Add a default body if none is already present
e63bdf38 1637 $response->body(
e422816e 1638 qq{<html><body><p>This item has moved <a href="$location">here</a>.</p></body></html>}
39655cdc 1639 );
1640 }
fbcc39ad 1641 }
1642
1643 # Content-Length
e63bdf38 1644 if ( $response->body && !$response->content_length ) {
775878ac 1645
8f62c91a 1646 # get the length from a filehandle
e63bdf38 1647 if ( blessed( $response->body ) && $response->body->can('read') )
197bd788 1648 {
e63bdf38 1649 my $stat = stat $response->body;
3b6a1db1 1650 if ( $stat && $stat->size > 0 ) {
e63bdf38 1651 $response->content_length( $stat->size );
8f62c91a 1652 }
1653 else {
775878ac 1654 $c->log->warn('Serving filehandle without a content-length');
8f62c91a 1655 }
1656 }
1657 else {
b5d7a61f 1658 # everything should be bytes at this point, but just in case
e63bdf38 1659 $response->content_length( bytes::length( $response->body ) );
8f62c91a 1660 }
fbcc39ad 1661 }
1662
1663 # Errors
e63bdf38 1664 if ( $response->status =~ /^(1\d\d|[23]04)$/ ) {
1665 $response->headers->remove_header("Content-Length");
1666 $response->body('');
fbcc39ad 1667 }
1668
1669 $c->finalize_cookies;
1670
1671 $c->engine->finalize_headers( $c, @_ );
1672
1673 # Done
6680c772 1674 $response->finalized_headers(1);
fbcc39ad 1675}
1676
b5ecfcf0 1677=head2 $c->finalize_output
fbcc39ad 1678
1679An alias for finalize_body.
1680
b5ecfcf0 1681=head2 $c->finalize_read
fbcc39ad 1682
e7f1cf73 1683Finalizes the input after reading is complete.
fbcc39ad 1684
1685=cut
1686
1687sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1688
b5ecfcf0 1689=head2 $c->finalize_uploads
fbcc39ad 1690
ae1e6b59 1691Finalizes uploads. Cleans up any temporary files.
fbcc39ad 1692
1693=cut
1694
1695sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1696
b5ecfcf0 1697=head2 $c->get_action( $action, $namespace )
fbcc39ad 1698
e7f1cf73 1699Gets an action in a given namespace.
fbcc39ad 1700
1701=cut
1702
684d10ed 1703sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
fbcc39ad 1704
b5ecfcf0 1705=head2 $c->get_actions( $action, $namespace )
a9dc674c 1706
ae1e6b59 1707Gets all actions of a given name in a namespace and all parent
1708namespaces.
a9dc674c 1709
1710=cut
1711
1712sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1713
f7b672ef 1714=head2 $c->handle_request( $class, @arguments )
fbcc39ad 1715
e7f1cf73 1716Called to handle each HTTP request.
fbcc39ad 1717
1718=cut
1719
1720sub handle_request {
1721 my ( $class, @arguments ) = @_;
1722
1723 # Always expect worst case!
1724 my $status = -1;
1725 eval {
dea1884f 1726 if ($class->debug) {
908e3d9e 1727 my $secs = time - $START || 1;
1728 my $av = sprintf '%.3f', $COUNT / $secs;
1729 my $time = localtime time;
1730 $class->log->info("*** Request $COUNT ($av/s) [$$] [$time] ***");
dea1884f 1731 }
908e3d9e 1732
1733 my $c = $class->prepare(@arguments);
1734 $c->dispatch;
ac5c933b 1735 $status = $c->finalize;
fbcc39ad 1736 };
1737
1738 if ( my $error = $@ ) {
1739 chomp $error;
1740 $class->log->error(qq/Caught exception in engine "$error"/);
1741 }
1742
1743 $COUNT++;
6680c772 1744
1745 if(my $coderef = $class->log->can('_flush')){
1746 $class->log->$coderef();
1747 }
fbcc39ad 1748 return $status;
1749}
1750
b5ecfcf0 1751=head2 $c->prepare( @arguments )
fbcc39ad 1752
ae1e6b59 1753Creates a Catalyst context from an engine-specific request (Apache, CGI,
1754etc.).
fbcc39ad 1755
1756=cut
1757
1758sub prepare {
1759 my ( $class, @arguments ) = @_;
1760
6680c772 1761 # XXX
1762 # After the app/ctxt split, this should become an attribute based on something passed
1763 # into the application.
3cec521a 1764 $class->context_class( ref $class || $class ) unless $class->context_class;
6680c772 1765
1766 my $c = $class->context_class->new({});
1767
1768 # For on-demand data
1769 $c->request->_context($c);
1770 $c->response->_context($c);
fbcc39ad 1771
b6d4ee6e 1772 #surely this is not the most efficient way to do things...
dc5f035e 1773 $c->stats($class->stats_class->new)->enable($c->use_stats);
908e3d9e 1774 if ( $c->debug ) {
ac5c933b 1775 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
908e3d9e 1776 }
1777
e63bdf38 1778 #XXX reuse coderef from can
5050d7a7 1779 # Allow engine to direct the prepare flow (for POE)
1780 if ( $c->engine->can('prepare') ) {
1781 $c->engine->prepare( $c, @arguments );
1782 }
1783 else {
1784 $c->prepare_request(@arguments);
1785 $c->prepare_connection;
1786 $c->prepare_query_parameters;
1787 $c->prepare_headers;
1788 $c->prepare_cookies;
1789 $c->prepare_path;
1790
878b821c 1791 # Prepare the body for reading, either by prepare_body
1792 # or the user, if they are using $c->read
1793 $c->prepare_read;
ac5c933b 1794
878b821c 1795 # Parse the body unless the user wants it on-demand
1796 unless ( $c->config->{parse_on_demand} ) {
1797 $c->prepare_body;
1798 }
5050d7a7 1799 }
fbcc39ad 1800
fbcc39ad 1801 my $method = $c->req->method || '';
2f381252 1802 my $path = $c->req->path;
1803 $path = '/' unless length $path;
fbcc39ad 1804 my $address = $c->req->address || '';
1805
e3a13771 1806 $c->log->debug(qq/"$method" request for "$path" from "$address"/)
fbcc39ad 1807 if $c->debug;
1808
e3a13771 1809 $c->prepare_action;
1810
fbcc39ad 1811 return $c;
1812}
1813
b5ecfcf0 1814=head2 $c->prepare_action
fbcc39ad 1815
b4b01a8a 1816Prepares action. See L<Catalyst::Dispatcher>.
fbcc39ad 1817
1818=cut
1819
1820sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1821
b5ecfcf0 1822=head2 $c->prepare_body
fbcc39ad 1823
e7f1cf73 1824Prepares message body.
fbcc39ad 1825
1826=cut
1827
1828sub prepare_body {
1829 my $c = shift;
1830
0f56bbcf 1831 return if $c->request->_has_body;
fbcc39ad 1832
1833 # Initialize on-demand data
1834 $c->engine->prepare_body( $c, @_ );
1835 $c->prepare_parameters;
1836 $c->prepare_uploads;
1837
0584323b 1838 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1839 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1840 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1841 my $param = $c->req->body_parameters->{$key};
1842 my $value = defined($param) ? $param : '';
1843 $t->row( $key,
1844 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1845 }
1846 $c->log->debug( "Body Parameters are:\n" . $t->draw );
fbcc39ad 1847 }
1848}
1849
b5ecfcf0 1850=head2 $c->prepare_body_chunk( $chunk )
4bd82c41 1851
e7f1cf73 1852Prepares a chunk of data before sending it to L<HTTP::Body>.
4bd82c41 1853
b4b01a8a 1854See L<Catalyst::Engine>.
1855
4bd82c41 1856=cut
1857
4f5ebacd 1858sub prepare_body_chunk {
1859 my $c = shift;
4bd82c41 1860 $c->engine->prepare_body_chunk( $c, @_ );
1861}
1862
b5ecfcf0 1863=head2 $c->prepare_body_parameters
fbcc39ad 1864
e7f1cf73 1865Prepares body parameters.
fbcc39ad 1866
1867=cut
1868
1869sub prepare_body_parameters {
1870 my $c = shift;
1871 $c->engine->prepare_body_parameters( $c, @_ );
1872}
1873
b5ecfcf0 1874=head2 $c->prepare_connection
fbcc39ad 1875
e7f1cf73 1876Prepares connection.
fbcc39ad 1877
1878=cut
1879
1880sub prepare_connection {
1881 my $c = shift;
1882 $c->engine->prepare_connection( $c, @_ );
1883}
1884
b5ecfcf0 1885=head2 $c->prepare_cookies
fbcc39ad 1886
e7f1cf73 1887Prepares cookies.
fbcc39ad 1888
1889=cut
1890
1891sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1892
b5ecfcf0 1893=head2 $c->prepare_headers
fbcc39ad 1894
e7f1cf73 1895Prepares headers.
fbcc39ad 1896
1897=cut
1898
1899sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1900
b5ecfcf0 1901=head2 $c->prepare_parameters
fbcc39ad 1902
e7f1cf73 1903Prepares parameters.
fbcc39ad 1904
1905=cut
1906
1907sub prepare_parameters {
1908 my $c = shift;
1909 $c->prepare_body_parameters;
1910 $c->engine->prepare_parameters( $c, @_ );
1911}
1912
b5ecfcf0 1913=head2 $c->prepare_path
fbcc39ad 1914
e7f1cf73 1915Prepares path and base.
fbcc39ad 1916
1917=cut
1918
1919sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1920
b5ecfcf0 1921=head2 $c->prepare_query_parameters
fbcc39ad 1922
e7f1cf73 1923Prepares query parameters.
fbcc39ad 1924
1925=cut
1926
1927sub prepare_query_parameters {
1928 my $c = shift;
1929
1930 $c->engine->prepare_query_parameters( $c, @_ );
1931
0584323b 1932 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1933 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1934 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1935 my $param = $c->req->query_parameters->{$key};
fbcc39ad 1936 my $value = defined($param) ? $param : '';
8c113188 1937 $t->row( $key,
fbcc39ad 1938 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1939 }
0584323b 1940 $c->log->debug( "Query Parameters are:\n" . $t->draw );
fbcc39ad 1941 }
1942}
1943
b5ecfcf0 1944=head2 $c->prepare_read
fbcc39ad 1945
e7f1cf73 1946Prepares the input for reading.
fbcc39ad 1947
1948=cut
1949
1950sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1951
b5ecfcf0 1952=head2 $c->prepare_request
fbcc39ad 1953
e7f1cf73 1954Prepares the engine request.
fbcc39ad 1955
1956=cut
1957
1958sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1959
b5ecfcf0 1960=head2 $c->prepare_uploads
fbcc39ad 1961
e7f1cf73 1962Prepares uploads.
fbcc39ad 1963
1964=cut
1965
1966sub prepare_uploads {
1967 my $c = shift;
1968
1969 $c->engine->prepare_uploads( $c, @_ );
1970
1971 if ( $c->debug && keys %{ $c->request->uploads } ) {
8c113188 1972 my $t = Text::SimpleTable->new(
34d28dfd 1973 [ 12, 'Parameter' ],
1974 [ 26, 'Filename' ],
8c113188 1975 [ 18, 'Type' ],
1976 [ 9, 'Size' ]
1977 );
fbcc39ad 1978 for my $key ( sort keys %{ $c->request->uploads } ) {
1979 my $upload = $c->request->uploads->{$key};
1980 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
8c113188 1981 $t->row( $key, $u->filename, $u->type, $u->size );
fbcc39ad 1982 }
1983 }
1984 $c->log->debug( "File Uploads are:\n" . $t->draw );
1985 }
1986}
1987
b5ecfcf0 1988=head2 $c->prepare_write
fbcc39ad 1989
e7f1cf73 1990Prepares the output for writing.
fbcc39ad 1991
1992=cut
1993
1994sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1995
b5ecfcf0 1996=head2 $c->request_class
1f9cb7c1 1997
e7f1cf73 1998Returns or sets the request class.
1f9cb7c1 1999
b5ecfcf0 2000=head2 $c->response_class
1f9cb7c1 2001
e7f1cf73 2002Returns or sets the response class.
1f9cb7c1 2003
b5ecfcf0 2004=head2 $c->read( [$maxlength] )
fbcc39ad 2005
ae1e6b59 2006Reads a chunk of data from the request body. This method is designed to
2007be used in a while loop, reading C<$maxlength> bytes on every call.
2008C<$maxlength> defaults to the size of the request if not specified.
fbcc39ad 2009
cc95842f 2010You have to set C<< MyApp->config->{parse_on_demand} >> to use this
ae1e6b59 2011directly.
fbcc39ad 2012
878b821c 2013Warning: If you use read(), Catalyst will not process the body,
2014so you will not be able to access POST parameters or file uploads via
2015$c->request. You must handle all body parsing yourself.
2016
fbcc39ad 2017=cut
2018
2019sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
2020
b5ecfcf0 2021=head2 $c->run
fbcc39ad 2022
2023Starts the engine.
2024
2025=cut
2026
2027sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
2028
b5ecfcf0 2029=head2 $c->set_action( $action, $code, $namespace, $attrs )
fbcc39ad 2030
e7f1cf73 2031Sets an action in a given namespace.
fbcc39ad 2032
2033=cut
2034
2035sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
2036
b5ecfcf0 2037=head2 $c->setup_actions($component)
fbcc39ad 2038
e7f1cf73 2039Sets up actions for a component.
fbcc39ad 2040
2041=cut
2042
2043sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
2044
b5ecfcf0 2045=head2 $c->setup_components
fbcc39ad 2046
86418559 2047Sets up components. Specify a C<setup_components> config option to pass
2048additional options directly to L<Module::Pluggable>. To add additional
2049search paths, specify a key named C<search_extra> as an array
2050reference. Items in the array beginning with C<::> will have the
18de900e 2051application class name prepended to them.
fbcc39ad 2052
2f381252 2053All components found will also have any
2054L<Devel::InnerPackage|inner packages> loaded and set up as components.
2055Note, that modules which are B<not> an I<inner package> of the main
2056file namespace loaded will not be instantiated as components.
2057
fbcc39ad 2058=cut
2059
2060sub setup_components {
2061 my $class = shift;
2062
18de900e 2063 my @paths = qw( ::Controller ::C ::Model ::M ::View ::V );
2064 my $config = $class->config->{ setup_components };
2065 my $extra = delete $config->{ search_extra } || [];
ac5c933b 2066
18de900e 2067 push @paths, @$extra;
ac5c933b 2068
364d7324 2069 my $locator = Module::Pluggable::Object->new(
18de900e 2070 search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
2071 %$config
364d7324 2072 );
b94b200c 2073
2074 my @comps = sort { length $a <=> length $b } $locator->plugins;
2075 my %comps = map { $_ => 1 } @comps;
73e1183e 2076
2077 my $deprecated_component_names = grep { /::[CMV]::/ } @comps;
2078 $class->log->warn(qq{Your application is using the deprecated ::[MVC]:: type naming scheme.\n}.
2079 qq{Please switch your class names to ::Model::, ::View:: and ::Controller: as appropriate.\n}
19a24dbb 2080 ) if $deprecated_component_names;
73e1183e 2081
b94b200c 2082 for my $component ( @comps ) {
dd91afb5 2083
2084 # We pass ignore_loaded here so that overlay files for (e.g.)
2085 # Model::DBI::Schema sub-classes are loaded - if it's in @comps
2086 # we know M::P::O found a file on disk so this is safe
2087
f5a4863c 2088 Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } );
2089 #Class::MOP::load_class($component);
364d7324 2090
2091 my $module = $class->setup_component( $component );
2092 my %modules = (
2093 $component => $module,
2094 map {
2095 $_ => $class->setup_component( $_ )
ac5c933b 2096 } grep {
b94b200c 2097 not exists $comps{$_}
364d7324 2098 } Devel::InnerPackage::list_packages( $component )
2099 );
ac5c933b 2100
364d7324 2101 for my $key ( keys %modules ) {
2102 $class->components->{ $key } = $modules{ $key };
fbcc39ad 2103 }
364d7324 2104 }
2105}
fbcc39ad 2106
364d7324 2107=head2 $c->setup_component
fbcc39ad 2108
364d7324 2109=cut
fbcc39ad 2110
364d7324 2111sub setup_component {
2112 my( $class, $component ) = @_;
fbcc39ad 2113
364d7324 2114 unless ( $component->can( 'COMPONENT' ) ) {
2115 return $component;
2116 }
fbcc39ad 2117
364d7324 2118 my $suffix = Catalyst::Utils::class2classsuffix( $component );
2119 my $config = $class->config->{ $suffix } || {};
fbcc39ad 2120
364d7324 2121 my $instance = eval { $component->COMPONENT( $class, $config ); };
fbcc39ad 2122
2123 if ( my $error = $@ ) {
fbcc39ad 2124 chomp $error;
fbcc39ad 2125 Catalyst::Exception->throw(
364d7324 2126 message => qq/Couldn't instantiate component "$component", "$error"/
2127 );
fbcc39ad 2128 }
2129
364d7324 2130 Catalyst::Exception->throw(
2131 message =>
2132 qq/Couldn't instantiate component "$component", "COMPONENT() didn't return an object-like value"/
84ff88cf 2133 ) unless blessed($instance);
364d7324 2134
2135 return $instance;
fbcc39ad 2136}
2137
b5ecfcf0 2138=head2 $c->setup_dispatcher
fbcc39ad 2139
ae1e6b59 2140Sets up dispatcher.
2141
fbcc39ad 2142=cut
2143
2144sub setup_dispatcher {
2145 my ( $class, $dispatcher ) = @_;
2146
2147 if ($dispatcher) {
2148 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
2149 }
2150
cb69249e 2151 if ( my $env = Catalyst::Utils::env_value( $class, 'DISPATCHER' ) ) {
2152 $dispatcher = 'Catalyst::Dispatcher::' . $env;
fbcc39ad 2153 }
2154
2155 unless ($dispatcher) {
cb0354c6 2156 $dispatcher = $class->dispatcher_class;
fbcc39ad 2157 }
2158
e63bdf38 2159 Class::MOP::load_class($dispatcher);
fbcc39ad 2160
2161 # dispatcher instance
2162 $class->dispatcher( $dispatcher->new );
2163}
2164
b5ecfcf0 2165=head2 $c->setup_engine
fbcc39ad 2166
ae1e6b59 2167Sets up engine.
2168
fbcc39ad 2169=cut
2170
2171sub setup_engine {
2172 my ( $class, $engine ) = @_;
2173
2174 if ($engine) {
2175 $engine = 'Catalyst::Engine::' . $engine;
2176 }
2177
cb69249e 2178 if ( my $env = Catalyst::Utils::env_value( $class, 'ENGINE' ) ) {
2179 $engine = 'Catalyst::Engine::' . $env;
fbcc39ad 2180 }
2181
9b0a3e0f 2182 if ( $ENV{MOD_PERL} ) {
e106a59f 2183 my $meta = Class::MOP::get_metaclass_by_name($class);
74c89dea 2184
fbcc39ad 2185 # create the apache method
74c89dea 2186 $meta->add_method('apache' => sub { shift->engine->apache });
fbcc39ad 2187
2188 my ( $software, $version ) =
2189 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
2190
2191 $version =~ s/_//g;
2192 $version =~ s/(\.[^.]+)\./$1/g;
2193
2194 if ( $software eq 'mod_perl' ) {
2195
9b0a3e0f 2196 if ( !$engine ) {
22247e54 2197
9b0a3e0f 2198 if ( $version >= 1.99922 ) {
2199 $engine = 'Catalyst::Engine::Apache2::MP20';
2200 }
22247e54 2201
9b0a3e0f 2202 elsif ( $version >= 1.9901 ) {
2203 $engine = 'Catalyst::Engine::Apache2::MP19';
2204 }
22247e54 2205
9b0a3e0f 2206 elsif ( $version >= 1.24 ) {
2207 $engine = 'Catalyst::Engine::Apache::MP13';
2208 }
22247e54 2209
9b0a3e0f 2210 else {
2211 Catalyst::Exception->throw( message =>
2212 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
2213 }
fbcc39ad 2214
fbcc39ad 2215 }
2216
2217 # install the correct mod_perl handler
2218 if ( $version >= 1.9901 ) {
2219 *handler = sub : method {
2220 shift->handle_request(@_);
2221 };
2222 }
2223 else {
2224 *handler = sub ($$) { shift->handle_request(@_) };
2225 }
2226
2227 }
2228
2229 elsif ( $software eq 'Zeus-Perl' ) {
2230 $engine = 'Catalyst::Engine::Zeus';
2231 }
2232
2233 else {
2234 Catalyst::Exception->throw(
2235 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
2236 }
2237 }
2238
2239 unless ($engine) {
cb0354c6 2240 $engine = $class->engine_class;
fbcc39ad 2241 }
2242
e63bdf38 2243 Class::MOP::load_class($engine);
0e7f5826 2244
d54484bf 2245 # check for old engines that are no longer compatible
2246 my $old_engine;
0e7f5826 2247 if ( $engine->isa('Catalyst::Engine::Apache')
2248 && !Catalyst::Engine::Apache->VERSION )
d54484bf 2249 {
2250 $old_engine = 1;
2251 }
0e7f5826 2252
d54484bf 2253 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
0e7f5826 2254 && Catalyst::Engine::Server->VERSION le '0.02' )
d54484bf 2255 {
2256 $old_engine = 1;
2257 }
0e7f5826 2258
2259 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
2260 && $engine->VERSION eq '0.01' )
d54484bf 2261 {
2262 $old_engine = 1;
2263 }
0e7f5826 2264
2265 elsif ($engine->isa('Catalyst::Engine::Zeus')
2266 && $engine->VERSION eq '0.01' )
d54484bf 2267 {
2268 $old_engine = 1;
2269 }
fbcc39ad 2270
d54484bf 2271 if ($old_engine) {
2272 Catalyst::Exception->throw( message =>
0e7f5826 2273 qq/Engine "$engine" is not supported by this version of Catalyst/
d54484bf 2274 );
2275 }
0e7f5826 2276
fbcc39ad 2277 # engine instance
2278 $class->engine( $engine->new );
2279}
2280
b5ecfcf0 2281=head2 $c->setup_home
fbcc39ad 2282
ae1e6b59 2283Sets up the home directory.
2284
fbcc39ad 2285=cut
2286
2287sub setup_home {
2288 my ( $class, $home ) = @_;
2289
cb69249e 2290 if ( my $env = Catalyst::Utils::env_value( $class, 'HOME' ) ) {
2291 $home = $env;
fbcc39ad 2292 }
2293
b6d4ee6e 2294 $home ||= Catalyst::Utils::home($class);
fbcc39ad 2295
2296 if ($home) {
e63bdf38 2297 #I remember recently being scolded for assigning config values like this
fbcc39ad 2298 $class->config->{home} ||= $home;
a738ab68 2299 $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
fbcc39ad 2300 }
2301}
2302
b5ecfcf0 2303=head2 $c->setup_log
fbcc39ad 2304
0fa676a7 2305Sets up log by instantiating a L<Catalyst::Log|Catalyst::Log> object and
2306passing it to C<log()>. Pass in a comma-delimited list of levels to set the
2307log to.
2308
2309This method also installs a C<debug> method that returns a true value into the
2310catalyst subclass if the "debug" level is passed in the comma-delimited list,
2311or if the C<$CATALYST_DEBUG> environment variable is set to a true value.
2312
2313Note that if the log has already been setup, by either a previous call to
2314C<setup_log> or by a call such as C<< __PACKAGE__->log( MyLogger->new ) >>,
5baa3bbc 2315that this method won't actually set up the log object.
ae1e6b59 2316
fbcc39ad 2317=cut
2318
2319sub setup_log {
0fa676a7 2320 my ( $class, $levels ) = @_;
fbcc39ad 2321
5baa3bbc 2322 $levels ||= '';
2323 $levels =~ s/^\s+//;
2324 $levels =~ s/\s+$//;
2325 my %levels = map { $_ => 1 } split /\s*,\s*/, $levels || '';
2326
fbcc39ad 2327 unless ( $class->log ) {
0fa676a7 2328 $class->log( Catalyst::Log->new(keys %levels) );
fbcc39ad 2329 }
af3ff00e 2330
cb69249e 2331 my $env_debug = Catalyst::Utils::env_value( $class, 'DEBUG' );
0fa676a7 2332 if ( defined($env_debug) or $levels{debug} ) {
e106a59f 2333 Class::MOP::get_metaclass_by_name($class)->add_method('debug' => sub { 1 });
fbcc39ad 2334 $class->log->debug('Debug messages enabled');
2335 }
2336}
2337
b5ecfcf0 2338=head2 $c->setup_plugins
fbcc39ad 2339
ae1e6b59 2340Sets up plugins.
2341
fbcc39ad 2342=cut
2343
dc5f035e 2344=head2 $c->setup_stats
2345
2346Sets up timing statistics class.
2347
2348=cut
2349
2350sub setup_stats {
2351 my ( $class, $stats ) = @_;
2352
2353 Catalyst::Utils::ensure_class_loaded($class->stats_class);
2354
2355 my $env = Catalyst::Utils::env_value( $class, 'STATS' );
2356 if ( defined($env) ? $env : ($stats || $class->debug ) ) {
e106a59f 2357 Class::MOP::get_metaclass_by_name($class)->add_method('use_stats' => sub { 1 });
b01f0c69 2358 $class->log->debug('Statistics enabled');
dc5f035e 2359 }
2360}
2361
2362
ac5c933b 2363=head2 $c->registered_plugins
836e1134 2364
2365Returns a sorted list of the plugins which have either been stated in the
2366import list or which have been added via C<< MyApp->plugin(@args); >>.
2367
2368If passed a given plugin name, it will report a boolean value indicating
2369whether or not that plugin is loaded. A fully qualified name is required if
2370the plugin name does not begin with C<Catalyst::Plugin::>.
2371
2372 if ($c->registered_plugins('Some::Plugin')) {
2373 ...
2374 }
2375
2376=cut
fbcc39ad 2377
836e1134 2378{
97b58e17 2379
2380 sub registered_plugins {
836e1134 2381 my $proto = shift;
197bd788 2382 return sort keys %{ $proto->_plugins } unless @_;
836e1134 2383 my $plugin = shift;
d0d4d785 2384 return 1 if exists $proto->_plugins->{$plugin};
2385 return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
836e1134 2386 }
fbcc39ad 2387
836e1134 2388 sub _register_plugin {
2389 my ( $proto, $plugin, $instant ) = @_;
2390 my $class = ref $proto || $proto;
fbcc39ad 2391
dd91afb5 2392 # no ignore_loaded here, the plugin may already have been
2393 # defined in memory and we don't want to error on "no file" if so
2394
b6d4ee6e 2395 Class::MOP::load_class( $plugin );
fbcc39ad 2396
197bd788 2397 $proto->_plugins->{$plugin} = 1;
836e1134 2398 unless ($instant) {
fbcc39ad 2399 no strict 'refs';
e106a59f 2400 if ( my $meta = Class::MOP::get_metaclass_by_name($class) ) {
74c89dea 2401 my @superclasses = ($plugin, $meta->superclasses );
2402 $meta->superclasses(@superclasses);
5fb67d52 2403 } else {
2404 unshift @{"$class\::ISA"}, $plugin;
2405 }
fbcc39ad 2406 }
836e1134 2407 return $class;
2408 }
2409
2410 sub setup_plugins {
2411 my ( $class, $plugins ) = @_;
2412
d0d4d785 2413 $class->_plugins( {} ) unless $class->_plugins;
836e1134 2414 $plugins ||= [];
2415 for my $plugin ( reverse @$plugins ) {
2416
2417 unless ( $plugin =~ s/\A\+// ) {
2418 $plugin = "Catalyst::Plugin::$plugin";
2419 }
2420
2421 $class->_register_plugin($plugin);
2422 }
fbcc39ad 2423 }
2424}
2425
b5ecfcf0 2426=head2 $c->stack
8767c5a3 2427
86418559 2428Returns an arrayref of the internal execution stack (actions that are
2429currently executing).
8767c5a3 2430
dc5f035e 2431=head2 $c->stats_class
2432
2433Returns or sets the stats (timing statistics) class.
2434
2435=head2 $c->use_stats
2436
2437Returns 1 when stats collection is enabled. Stats collection is enabled
2438when the -Stats options is set, debug is on or when the <MYAPP>_STATS
2439environment variable is set.
2440
2441Note that this is a static method, not an accessor and should be overloaded
2442by declaring "sub use_stats { 1 }" in your MyApp.pm, not by calling $c->use_stats(1).
2443
2444=cut
2445
2446sub use_stats { 0 }
2447
2448
b5ecfcf0 2449=head2 $c->write( $data )
fbcc39ad 2450
ae1e6b59 2451Writes $data to the output stream. When using this method directly, you
2452will need to manually set the C<Content-Length> header to the length of
2453your output data, if known.
fbcc39ad 2454
2455=cut
2456
4f5ebacd 2457sub write {
2458 my $c = shift;
2459
2460 # Finalize headers if someone manually writes output
2461 $c->finalize_headers;
2462
2463 return $c->engine->write( $c, @_ );
2464}
fbcc39ad 2465
b5ecfcf0 2466=head2 version
bf88a181 2467
ae1e6b59 2468Returns the Catalyst version number. Mostly useful for "powered by"
2469messages in template systems.
bf88a181 2470
2471=cut
2472
2473sub version { return $Catalyst::VERSION }
2474
b0bb11ec 2475=head1 INTERNAL ACTIONS
2476
ae1e6b59 2477Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2478C<_ACTION>, and C<_END>. These are by default not shown in the private
3e705254 2479action table, but you can make them visible with a config parameter.
b0bb11ec 2480
2481 MyApp->config->{show_internal_actions} = 1;
2482
d2ee9760 2483=head1 CASE SENSITIVITY
2484
3e705254 2485By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
ae1e6b59 2486mapped to C</foo/bar>. You can activate case sensitivity with a config
3e705254 2487parameter.
d2ee9760 2488
2489 MyApp->config->{case_sensitive} = 1;
2490
3e705254 2491This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
fbcc39ad 2492
2493=head1 ON-DEMAND PARSER
2494
2495The request body is usually parsed at the beginning of a request,
878b821c 2496but if you want to handle input yourself, you can enable on-demand
2497parsing with a config parameter.
fbcc39ad 2498
2499 MyApp->config->{parse_on_demand} = 1;
ac5c933b 2500
fbcc39ad 2501=head1 PROXY SUPPORT
2502
ae1e6b59 2503Many production servers operate using the common double-server approach,
2504with a lightweight frontend web server passing requests to a larger
2505backend server. An application running on the backend server must deal
2506with two problems: the remote user always appears to be C<127.0.0.1> and
2507the server's hostname will appear to be C<localhost> regardless of the
2508virtual host that the user connected through.
fbcc39ad 2509
ae1e6b59 2510Catalyst will automatically detect this situation when you are running
2511the frontend and backend servers on the same machine. The following
2512changes are made to the request.
fbcc39ad 2513
ac5c933b 2514 $c->req->address is set to the user's real IP address, as read from
ae1e6b59 2515 the HTTP X-Forwarded-For header.
ac5c933b 2516
ae1e6b59 2517 The host value for $c->req->base and $c->req->uri is set to the real
2518 host, as read from the HTTP X-Forwarded-Host header.
fbcc39ad 2519
3e705254 2520Obviously, your web server must support these headers for this to work.
fbcc39ad 2521
ae1e6b59 2522In a more complex server farm environment where you may have your
2523frontend proxy server(s) on different machines, you will need to set a
2524configuration option to tell Catalyst to read the proxied data from the
2525headers.
fbcc39ad 2526
2527 MyApp->config->{using_frontend_proxy} = 1;
ac5c933b 2528
fbcc39ad 2529If you do not wish to use the proxy support at all, you may set:
d1a31ac6 2530
fbcc39ad 2531 MyApp->config->{ignore_frontend_proxy} = 1;
2532
2533=head1 THREAD SAFETY
2534
86418559 2535Catalyst has been tested under Apache 2's threading C<mpm_worker>,
2536C<mpm_winnt>, and the standalone forking HTTP server on Windows. We
2537believe the Catalyst core to be thread-safe.
fbcc39ad 2538
2539If you plan to operate in a threaded environment, remember that all other
3e705254 2540modules you are using must also be thread-safe. Some modules, most notably
2541L<DBD::SQLite>, are not thread-safe.
d1a31ac6 2542
3cb1db8c 2543=head1 SUPPORT
2544
2545IRC:
2546
4eaf7c88 2547 Join #catalyst on irc.perl.org.
3cb1db8c 2548
3e705254 2549Mailing Lists:
3cb1db8c 2550
6d4c3368 2551 http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
2552 http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
1985c30b 2553
432d507d 2554Web:
2555
2556 http://catalyst.perl.org
2557
0ef52a96 2558Wiki:
2559
2560 http://dev.catalyst.perl.org
2561
fc7ec1d9 2562=head1 SEE ALSO
2563
829a28ca 2564=head2 L<Task::Catalyst> - All you need to start with Catalyst
2565
b5ecfcf0 2566=head2 L<Catalyst::Manual> - The Catalyst Manual
e7f1cf73 2567
b5ecfcf0 2568=head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
61b1e958 2569
b5ecfcf0 2570=head2 L<Catalyst::Engine> - Core engine
61b1e958 2571
b5ecfcf0 2572=head2 L<Catalyst::Log> - Log class.
61b1e958 2573
b5ecfcf0 2574=head2 L<Catalyst::Request> - Request object
61b1e958 2575
b5ecfcf0 2576=head2 L<Catalyst::Response> - Response object
61b1e958 2577
b5ecfcf0 2578=head2 L<Catalyst::Test> - The test suite.
fc7ec1d9 2579
2f381252 2580=head1 PROJECT FOUNDER
2581
2582sri: Sebastian Riedel <sri@cpan.org>
fc7ec1d9 2583
2f381252 2584=head1 CONTRIBUTORS
15f0b5b7 2585
2f381252 2586abw: Andy Wardley
fbcc39ad 2587
2f381252 2588acme: Leon Brocard <leon@astray.com>
33108eaf 2589
f4a57de4 2590Andrew Bramble
2591
15f0b5b7 2592Andrew Ford
2593
2594Andrew Ruthven
2595
2f381252 2596andyg: Andy Grundman <andy@hybridized.org>
fbcc39ad 2597
2f381252 2598audreyt: Audrey Tang
15f0b5b7 2599
2f381252 2600bricas: Brian Cassidy <bricas@cpan.org>
0cf56dbc 2601
e31b525c 2602Caelum: Rafael Kitover <rkitover@io.com>
2603
2f381252 2604chansen: Christian Hansen
6aaa1c60 2605
2f381252 2606chicks: Christopher Hicks
15f0b5b7 2607
0fa676a7 2608David E. Wheeler
2609
2f381252 2610dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com>
15f0b5b7 2611
2f381252 2612Drew Taylor
15f0b5b7 2613
2f381252 2614esskar: Sascha Kiefer
0ef52a96 2615
2f381252 2616fireartist: Carl Franks <cfranks@cpan.org>
15f0b5b7 2617
2f381252 2618gabb: Danijel Milicevic
61bef238 2619
15f0b5b7 2620Gary Ashton Jones
2621
2622Geoff Richards
2623
e4cc83b2 2624ilmari: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
2625
2f381252 2626jcamacho: Juan Camacho
fbcc39ad 2627
108201b5 2628jhannah: Jay Hannah <jay@jays.net>
2629
15f0b5b7 2630Jody Belka
2631
2632Johan Lindstrom
2633
2f381252 2634jon: Jon Schutz <jjschutz@cpan.org>
15f0b5b7 2635
2f381252 2636marcus: Marcus Ramberg <mramberg@cpan.org>
15f0b5b7 2637
2f381252 2638miyagawa: Tatsuhiko Miyagawa <miyagawa@bulknews.net>
15f0b5b7 2639
2f381252 2640mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
15f0b5b7 2641
2f381252 2642mugwump: Sam Vilain
71c3bcc3 2643
2f381252 2644naughton: David Naughton
a727119f 2645
2f381252 2646ningu: David Kamholz <dkamholz@cpan.org>
1cf1c56a 2647
2f381252 2648nothingmuch: Yuval Kogman <nothingmuch@woobling.org>
9c71d51d 2649
2f381252 2650numa: Dan Sully <daniel@cpan.org>
fc7ec1d9 2651
2f381252 2652obra: Jesse Vincent
2653
2654omega: Andreas Marienborg
51f0308d 2655
39fc2ce1 2656Oleg Kostyuk <cub.uanic@gmail.com>
2657
2f381252 2658phaylon: Robert Sedlacek <phaylon@dunkelheit.at>
bdcb95ef 2659
6dae3eef 2660rafl: Florian Ragwitz <rafl@debian.org>
2661
2f381252 2662sky: Arthur Bergman
2663
2664the_jester: Jesse Sheidlower
2665
bb33cb06 2666t0m: Tomas Doran <bobtfish@bobtfish.net>
2667
2f381252 2668Ulf Edvinsson
51f0308d 2669
2f381252 2670willert: Sebastian Willert <willert@cpan.org>
51f0308d 2671
fc7ec1d9 2672=head1 LICENSE
2673
9ce5ab63 2674This library is free software, you can redistribute it and/or modify it under
41ca9ba7 2675the same terms as Perl itself.
fc7ec1d9 2676
2677=cut
2678
4090e3bb 2679no Moose;
2680
46d0346d 2681__PACKAGE__->meta->make_immutable;
2682
fc7ec1d9 26831;