Port kanes r9520 up to 5.80 trunk
[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
ae0e35ee 364=head2 $c->visit( $action [, \@arguments ] )
365
366=head2 $c->visit( $class, $method, [, \@arguments ] )
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
2f381252 390=head2 $c->go( $action [, \@arguments ] )
391
392=head2 $c->go( $class, $method, [, \@arguments ] )
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
c74d3f0c 851You can enable debug mode in several ways:
852(1) with the environment variables MYAPP_DEBUG, or CATALYST_DEBUG
853(2) the -Debug option in your MyApp.pm
854(3) by declaring "sub debug { 1 }" in your MyApp.pm.
855
856Calling $c->debug(1) has no effect.
e80e8542 857
af3ff00e 858=cut
859
b4b01a8a 860sub debug { 0 }
861
862=head2 $c->dispatcher
863
2887a7f1 864Returns the dispatcher instance. See L<Catalyst::Dispatcher>.
b4b01a8a 865
866=head2 $c->engine
867
2887a7f1 868Returns the engine instance. See L<Catalyst::Engine>.
b4b01a8a 869
870
f7b672ef 871=head2 UTILITY METHODS
66e28e3f 872
b5ecfcf0 873=head2 $c->path_to(@path)
01033d73 874
cc95842f 875Merges C<@path> with C<< $c->config->{home} >> and returns a
afbb9aa3 876L<Path::Class::Dir> object.
01033d73 877
878For example:
879
880 $c->path_to( 'db', 'sqlite.db' );
881
882=cut
883
884sub path_to {
885 my ( $c, @path ) = @_;
a738ab68 886 my $path = Path::Class::Dir->new( $c->config->{home}, @path );
01033d73 887 if ( -d $path ) { return $path }
a738ab68 888 else { return Path::Class::File->new( $c->config->{home}, @path ) }
01033d73 889}
890
b5ecfcf0 891=head2 $c->plugin( $name, $class, @args )
0ef52a96 892
10011c19 893Helper method for plugins. It creates a class data accessor/mutator and
ae1e6b59 894loads and instantiates the given class.
0ef52a96 895
896 MyApp->plugin( 'prototype', 'HTML::Prototype' );
897
898 $c->prototype->define_javascript_functions;
6b2a933b 899
900B<Note:> This method of adding plugins is deprecated. The ability
901to add plugins like this B<will be removed> in a Catalyst 5.9.
902Please do not use this functionality in new code.
0ef52a96 903
904=cut
905
906sub plugin {
907 my ( $class, $name, $plugin, @args ) = @_;
6b2a933b 908
909 # See block comment in t/unit_core_plugin.t
d6ce7d52 910 $class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in Catalyst 5.9/);
6b2a933b 911
97b58e17 912 $class->_register_plugin( $plugin, 1 );
0ef52a96 913
914 eval { $plugin->import };
915 $class->mk_classdata($name);
916 my $obj;
917 eval { $obj = $plugin->new(@args) };
918
919 if ($@) {
920 Catalyst::Exception->throw( message =>
921 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
922 }
923
924 $class->$name($obj);
925 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
926 if $class->debug;
927}
928
b5ecfcf0 929=head2 MyApp->setup
fbcc39ad 930
e7f1cf73 931Initializes the dispatcher and engine, loads any plugins, and loads the
ae1e6b59 932model, view, and controller components. You may also specify an array
933of plugins to load here, if you choose to not load them in the C<use
934Catalyst> line.
fbcc39ad 935
0ef52a96 936 MyApp->setup;
937 MyApp->setup( qw/-Debug/ );
fbcc39ad 938
939=cut
940
941sub setup {
0319a12c 942 my ( $class, @arguments ) = @_;
c2f3cc1b 943 croak('Running setup more than once')
944 if ( $class->setup_finished );
5168a5fc 945
fbcc39ad 946 unless ( $class->isa('Catalyst') ) {
953b0e15 947
fbcc39ad 948 Catalyst::Exception->throw(
949 message => qq/'$class' does not inherit from Catalyst/ );
1c99e125 950 }
0319a12c 951
fbcc39ad 952 if ( $class->arguments ) {
953 @arguments = ( @arguments, @{ $class->arguments } );
954 }
955
956 # Process options
957 my $flags = {};
958
959 foreach (@arguments) {
960
961 if (/^-Debug$/) {
962 $flags->{log} =
963 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
964 }
965 elsif (/^-(\w+)=?(.*)$/) {
966 $flags->{ lc $1 } = $2;
967 }
968 else {
969 push @{ $flags->{plugins} }, $_;
970 }
971 }
972
99f187d6 973 $class->setup_home( delete $flags->{home} );
974
fbcc39ad 975 $class->setup_log( delete $flags->{log} );
976 $class->setup_plugins( delete $flags->{plugins} );
977 $class->setup_dispatcher( delete $flags->{dispatcher} );
978 $class->setup_engine( delete $flags->{engine} );
dc5f035e 979 $class->setup_stats( delete $flags->{stats} );
fbcc39ad 980
981 for my $flag ( sort keys %{$flags} ) {
982
983 if ( my $code = $class->can( 'setup_' . $flag ) ) {
984 &$code( $class, delete $flags->{$flag} );
985 }
986 else {
987 $class->log->warn(qq/Unknown flag "$flag"/);
988 }
989 }
990
0eb4af72 991 eval { require Catalyst::Devel; };
992 if( !$@ && $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::Devel::CATALYST_SCRIPT_GEN ) ) {
993 $class->log->warn(<<"EOF");
4ff0d824 994You are running an old script!
995
34a83d89 996 Please update by running (this will overwrite existing files):
997 catalyst.pl -force -scripts $class
998
999 or (this will not overwrite existing files):
1000 catalyst.pl -scripts $class
1cf0345b 1001
4ff0d824 1002EOF
0eb4af72 1003 }
ac5c933b 1004
fbcc39ad 1005 if ( $class->debug ) {
6601f2ad 1006 my @plugins = map { "$_ " . ( $_->VERSION || '' ) } $class->registered_plugins;
fbcc39ad 1007
1008 if (@plugins) {
39fc2ce1 1009 my $column_width = Catalyst::Utils::term_width() - 6;
1010 my $t = Text::SimpleTable->new($column_width);
8c113188 1011 $t->row($_) for @plugins;
1cf0345b 1012 $class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" );
fbcc39ad 1013 }
1014
1015 my $dispatcher = $class->dispatcher;
1016 my $engine = $class->engine;
1017 my $home = $class->config->{home};
1018
01ce7075 1019 $class->log->debug(sprintf(q/Loaded dispatcher "%s"/, blessed($dispatcher)));
1020 $class->log->debug(sprintf(q/Loaded engine "%s"/, blessed($engine)));
fbcc39ad 1021
1022 $home
1023 ? ( -d $home )
1024 ? $class->log->debug(qq/Found home "$home"/)
1025 : $class->log->debug(qq/Home "$home" doesn't exist/)
1026 : $class->log->debug(q/Couldn't find home/);
1027 }
1028
54f4bfef 1029 # Call plugins setup, this is stupid and evil.
fbcc39ad 1030 {
1031 no warnings qw/redefine/;
1032 local *setup = sub { };
1033 $class->setup;
1034 }
1035
1036 # Initialize our data structure
1037 $class->components( {} );
1038
1039 $class->setup_components;
1040
1041 if ( $class->debug ) {
39fc2ce1 1042 my $column_width = Catalyst::Utils::term_width() - 8 - 9;
1043 my $t = Text::SimpleTable->new( [ $column_width, 'Class' ], [ 8, 'Type' ] );
684d10ed 1044 for my $comp ( sort keys %{ $class->components } ) {
1045 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
1046 $t->row( $comp, $type );
1047 }
1cf0345b 1048 $class->log->debug( "Loaded components:\n" . $t->draw . "\n" )
8c113188 1049 if ( keys %{ $class->components } );
fbcc39ad 1050 }
1051
1052 # Add our self to components, since we are also a component
96d8d513 1053 if( $class->isa('Catalyst::Controller') ){
1054 $class->components->{$class} = $class;
1055 }
fbcc39ad 1056
1057 $class->setup_actions;
1058
1059 if ( $class->debug ) {
1060 my $name = $class->config->{name} || 'Application';
1061 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
1062 }
1063 $class->log->_flush() if $class->log->can('_flush');
3643e890 1064
3d041c32 1065 # Make sure that the application class becomes immutable at this point,
1066 # which ensures that it gets an inlined constructor. This means that it
1067 # works even if the user has added a plugin which contains a new method.
1068 # Note however that we have to do the work on scope end, so that method
1069 # modifiers work correctly in MyApp (as you have to call setup _before_
1070 # applying modifiers).
edb20ed3 1071 Scope::Upper::reap(sub {
e106a59f 1072 my $meta = Class::MOP::get_metaclass_by_name($class);
3d041c32 1073 $meta->make_immutable unless $meta->is_immutable;
d134bcca 1074 }, Scope::Upper::SCOPE(1));
3d041c32 1075
a5d07d29 1076 $class->setup_finalize;
1077}
1078
23c63a17 1079
1080=head2 $app->setup_finalize
1081
1082A hook to attach modifiers to.
1083Using C< after setup => sub{}; > doesn't work, because of quirky things done for plugin setup.
1084Also better than C< setup_finished(); >, as that is a getter method.
1085
1086 sub setup_finalize {
1087
1088 my $app = shift;
1089
1090 ## do stuff, i.e., determine a primary key column for sessions stored in a DB
1091
1092 $app->next::method(@_);
1093
1094
1095 }
1096
1097=cut
1098
a5d07d29 1099sub setup_finalize {
1100 my ($class) = @_;
3643e890 1101 $class->setup_finished(1);
fbcc39ad 1102}
1103
8a27f860 1104=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values? )
1105
73664287 1106=head2 $c->uri_for( $path, @args?, \%query_values? )
fbcc39ad 1107
8a27f860 1108=over
fbcc39ad 1109
8a27f860 1110=item $action
8dc69021 1111
8a27f860 1112A Catalyst::Action object representing the Catalyst action you want to
1113create a URI for. To get one for an action in the current controller,
1114use C<< $c->action('someactionname') >>. To get one from different
1115controller, fetch the controller using C<< $c->controller() >>, then
1116call C<action_for> on it.
ea0e58d9 1117
9df7c5d9 1118You can maintain the arguments captured by an action (e.g.: Regex, Chained)
1119using C<< $c->req->captures >>.
1120
1121 # For the current action
1122 $c->uri_for($c->action, $c->req->captures);
1123
1124 # For the Foo action in the Bar controller
1125 $c->uri_for($c->controller->('Bar')->action_for('Foo'), $c->req->captures);
1126
d5e3d528 1127=back
1128
4cf1dd00 1129=cut
1130
fbcc39ad 1131sub uri_for {
00e6a2b7 1132 my ( $c, $path, @args ) = @_;
00e6a2b7 1133
7e95ba12 1134 if ( blessed($path) ) { # action object
ea0e58d9 1135 my $captures = ( scalar @args && ref $args[0] eq 'ARRAY'
1136 ? shift(@args)
1137 : [] );
1138 $path = $c->dispatcher->uri_for_action($path, $captures);
1139 return undef unless defined($path);
81e75875 1140 $path = '/' if $path eq '';
ea0e58d9 1141 }
1142
51674a63 1143 undef($path) if (defined $path && $path eq '');
00e6a2b7 1144
97b58e17 1145 my $params =
1146 ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
8327e2e2 1147
cbb93105 1148 carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
51674a63 1149 s/([^$URI::uric])/$URI::Escape::escapes{$1}/go for @args;
1150
1151 unshift(@args, $path);
1152
1153 unless (defined $path && $path =~ s!^/!!) { # in-place strip
1154 my $namespace = $c->namespace;
1155 if (defined $path) { # cheesy hack to handle path '../foo'
1156 $namespace =~ s{(?:^|/)[^/]+$}{} while $args[0] =~ s{^\.\./}{};
6601f2ad 1157 }
51674a63 1158 unshift(@args, $namespace || '');
1159 }
ac5c933b 1160
189e2a51 1161 # join args with '/', or a blank string
51674a63 1162 my $args = join('/', grep { defined($_) } @args);
1163 $args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
7a2295bc 1164 $args =~ s!^/+!!;
51674a63 1165 my $base = $c->req->base;
1166 my $class = ref($base);
1167 $base =~ s{(?<!/)$}{/};
1168
1169 my $query = '';
1170
1171 if (my @keys = keys %$params) {
1172 # somewhat lifted from URI::_query's query_form
1173 $query = '?'.join('&', map {
2f381252 1174 my $val = $params->{$_};
51674a63 1175 s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
1176 s/ /+/g;
1177 my $key = $_;
51674a63 1178 $val = '' unless defined $val;
1179 (map {
1180 $_ = "$_";
0ce485e9 1181 utf8::encode( $_ ) if utf8::is_utf8($_);
51674a63 1182 # using the URI::Escape pattern here so utf8 chars survive
1183 s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
1184 s/ /+/g;
1185 "${key}=$_"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
1186 } @keys);
1187 }
1188
1189 my $res = bless(\"${base}${args}${query}", $class);
d3e7a648 1190 $res;
fbcc39ad 1191}
1192
b5ecfcf0 1193=head2 $c->welcome_message
ab2374d3 1194
1195Returns the Catalyst welcome HTML page.
1196
1197=cut
1198
1199sub welcome_message {
bf1f2c60 1200 my $c = shift;
1201 my $name = $c->config->{name};
1202 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
1203 my $prefix = Catalyst::Utils::appprefix( ref $c );
80cdbbff 1204 $c->response->content_type('text/html; charset=utf-8');
ab2374d3 1205 return <<"EOF";
80cdbbff 1206<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1207 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1208<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
ab2374d3 1209 <head>
85d9fce6 1210 <meta http-equiv="Content-Language" content="en" />
1211 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
ab2374d3 1212 <title>$name on Catalyst $VERSION</title>
1213 <style type="text/css">
1214 body {
ab2374d3 1215 color: #000;
1216 background-color: #eee;
1217 }
1218 div#content {
1219 width: 640px;
80cdbbff 1220 margin-left: auto;
1221 margin-right: auto;
ab2374d3 1222 margin-top: 10px;
1223 margin-bottom: 10px;
1224 text-align: left;
1225 background-color: #ccc;
1226 border: 1px solid #aaa;
ab2374d3 1227 }
d84c4dab 1228 p, h1, h2 {
ab2374d3 1229 margin-left: 20px;
1230 margin-right: 20px;
16215972 1231 font-family: verdana, tahoma, sans-serif;
ab2374d3 1232 }
d84c4dab 1233 a {
1234 font-family: verdana, tahoma, sans-serif;
1235 }
d114e033 1236 :link, :visited {
1237 text-decoration: none;
1238 color: #b00;
1239 border-bottom: 1px dotted #bbb;
1240 }
1241 :link:hover, :visited:hover {
d114e033 1242 color: #555;
1243 }
ab2374d3 1244 div#topbar {
1245 margin: 0px;
1246 }
3e82a295 1247 pre {
3e82a295 1248 margin: 10px;
1249 padding: 8px;
1250 }
ab2374d3 1251 div#answers {
1252 padding: 8px;
1253 margin: 10px;
d114e033 1254 background-color: #fff;
ab2374d3 1255 border: 1px solid #aaa;
ab2374d3 1256 }
1257 h1 {
33108eaf 1258 font-size: 0.9em;
1259 font-weight: normal;
ab2374d3 1260 text-align: center;
1261 }
1262 h2 {
1263 font-size: 1.0em;
1264 }
1265 p {
1266 font-size: 0.9em;
1267 }
ae7c5252 1268 p img {
1269 float: right;
1270 margin-left: 10px;
1271 }
9619f23c 1272 span#appname {
1273 font-weight: bold;
33108eaf 1274 font-size: 1.6em;
ab2374d3 1275 }
1276 </style>
1277 </head>
1278 <body>
1279 <div id="content">
1280 <div id="topbar">
9619f23c 1281 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
d84c4dab 1282 $VERSION</h1>
ab2374d3 1283 </div>
1284 <div id="answers">
ae7c5252 1285 <p>
80cdbbff 1286 <img src="$logo" alt="Catalyst Logo" />
ae7c5252 1287 </p>
596aaffe 1288 <p>Welcome to the world of Catalyst.
f92fd545 1289 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
1290 framework will make web development something you had
60dd6e1d 1291 never expected it to be: Fun, rewarding, and quick.</p>
ab2374d3 1292 <h2>What to do now?</h2>
4b8cb778 1293 <p>That really depends on what <b>you</b> want to do.
ab2374d3 1294 We do, however, provide you with a few starting points.</p>
1295 <p>If you want to jump right into web development with Catalyst
2f381252 1296 you might want to start with a tutorial.</p>
b607f8a0 1297<pre>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
596aaffe 1298</pre>
1299<p>Afterwards you can go on to check out a more complete look at our features.</p>
1300<pre>
b607f8a0 1301<code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
1302<!-- Something else should go here, but the Catalyst::Manual link seems unhelpful -->
1303</code></pre>
ab2374d3 1304 <h2>What to do next?</h2>
f5681c92 1305 <p>Next it's time to write an actual application. Use the
80cdbbff 1306 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&amp;mode=all">controllers</a>,
60dd6e1d 1307 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&amp;mode=all">models</a>, and
1308 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&amp;mode=all">views</a>;
bf1f2c60 1309 they can save you a lot of work.</p>
1310 <pre><code>script/${prefix}_create.pl -help</code></pre>
1311 <p>Also, be sure to check out the vast and growing
802bf2cb 1312 collection of <a href="http://search.cpan.org/search?query=Catalyst">plugins for Catalyst on CPAN</a>;
bf1f2c60 1313 you are likely to find what you need there.
f5681c92 1314 </p>
1315
82245cc4 1316 <h2>Need help?</h2>
f5681c92 1317 <p>Catalyst has a very active community. Here are the main places to
1318 get in touch with us.</p>
16215972 1319 <ul>
1320 <li>
2b9a7d76 1321 <a href="http://dev.catalyst.perl.org">Wiki</a>
16215972 1322 </li>
1323 <li>
6d4c3368 1324 <a href="http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst">Mailing-List</a>
16215972 1325 </li>
1326 <li>
4eaf7c88 1327 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
16215972 1328 </li>
1329 </ul>
ab2374d3 1330 <h2>In conclusion</h2>
ac5c933b 1331 <p>The Catalyst team hopes you will enjoy using Catalyst as much
f5681c92 1332 as we enjoyed making it. Please contact us if you have ideas
1333 for improvement or other feedback.</p>
ab2374d3 1334 </div>
1335 </div>
1336 </body>
1337</html>
1338EOF
1339}
1340
fbcc39ad 1341=head1 INTERNAL METHODS
1342
ae1e6b59 1343These methods are not meant to be used by end users.
1344
b5ecfcf0 1345=head2 $c->components
fbcc39ad 1346
e7f1cf73 1347Returns a hash of components.
fbcc39ad 1348
b5ecfcf0 1349=head2 $c->context_class
1f9cb7c1 1350
e7f1cf73 1351Returns or sets the context class.
1f9cb7c1 1352
b5ecfcf0 1353=head2 $c->counter
fbcc39ad 1354
ae1e6b59 1355Returns a hashref containing coderefs and execution counts (needed for
1356deep recursion detection).
fbcc39ad 1357
b5ecfcf0 1358=head2 $c->depth
fbcc39ad 1359
e7f1cf73 1360Returns the number of actions on the current internal execution stack.
fbcc39ad 1361
b5ecfcf0 1362=head2 $c->dispatch
fbcc39ad 1363
e7f1cf73 1364Dispatches a request to actions.
fbcc39ad 1365
1366=cut
1367
1368sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
1369
b5ecfcf0 1370=head2 $c->dispatcher_class
1f9cb7c1 1371
e7f1cf73 1372Returns or sets the dispatcher class.
1f9cb7c1 1373
b5ecfcf0 1374=head2 $c->dump_these
7f92deef 1375
ae1e6b59 1376Returns a list of 2-element array references (name, structure) pairs
1377that will be dumped on the error page in debug mode.
7f92deef 1378
1379=cut
1380
1381sub dump_these {
1382 my $c = shift;
ac5c933b 1383 [ Request => $c->req ],
1384 [ Response => $c->res ],
052a2d89 1385 [ Stash => $c->stash ],
1386 [ Config => $c->config ];
7f92deef 1387}
1388
b5ecfcf0 1389=head2 $c->engine_class
1f9cb7c1 1390
e7f1cf73 1391Returns or sets the engine class.
1f9cb7c1 1392
b5ecfcf0 1393=head2 $c->execute( $class, $coderef )
fbcc39ad 1394
0ef52a96 1395Execute a coderef in given class and catch exceptions. Errors are available
1396via $c->error.
fbcc39ad 1397
1398=cut
1399
1400sub execute {
1401 my ( $c, $class, $code ) = @_;
858828dd 1402 $class = $c->component($class) || $class;
fbcc39ad 1403 $c->state(0);
a0eca838 1404
197bd788 1405 if ( $c->depth >= $RECURSION ) {
f3414019 1406 my $action = $code->reverse();
91d08727 1407 $action = "/$action" unless $action =~ /->/;
f3414019 1408 my $error = qq/Deep recursion detected calling "${action}"/;
1627551a 1409 $c->log->error($error);
1410 $c->error($error);
1411 $c->state(0);
1412 return $c->state;
1413 }
1414
dc5f035e 1415 my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats;
22247e54 1416
8767c5a3 1417 push( @{ $c->stack }, $code );
ac5c933b 1418
f3414019 1419 eval { $c->state( $code->execute( $class, $c, @{ $c->req->args } ) || 0 ) };
22247e54 1420
dc5f035e 1421 $c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info;
ac5c933b 1422
a6724a82 1423 my $last = pop( @{ $c->stack } );
fbcc39ad 1424
1425 if ( my $error = $@ ) {
2f381252 1426 if ( !ref($error) and $error eq $DETACH ) {
1427 die $DETACH if($c->depth > 1);
1428 }
55424863 1429 elsif ( !ref($error) and $error eq $GO ) {
1430 die $GO if($c->depth > 0);
1431 }
fbcc39ad 1432 else {
1433 unless ( ref $error ) {
91d08727 1434 no warnings 'uninitialized';
fbcc39ad 1435 chomp $error;
f59def82 1436 my $class = $last->class;
1437 my $name = $last->name;
1438 $error = qq/Caught exception in $class->$name "$error"/;
fbcc39ad 1439 }
fbcc39ad 1440 $c->error($error);
1441 $c->state(0);
1442 }
1443 }
1444 return $c->state;
1445}
1446
7a7d7af5 1447sub _stats_start_execute {
1448 my ( $c, $code ) = @_;
1449
a6724a82 1450 return if ( ( $code->name =~ /^_.*/ )
1451 && ( !$c->config->{show_internal_actions} ) );
7a7d7af5 1452
f3414019 1453 my $action_name = $code->reverse();
1454 $c->counter->{$action_name}++;
7a7d7af5 1455
f3414019 1456 my $action = $action_name;
a6724a82 1457 $action = "/$action" unless $action =~ /->/;
1458
7a7d7af5 1459 # determine if the call was the result of a forward
1460 # this is done by walking up the call stack and looking for a calling
1461 # sub of Catalyst::forward before the eval
1462 my $callsub = q{};
1463 for my $index ( 2 .. 11 ) {
1464 last
1465 if ( ( caller($index) )[0] eq 'Catalyst'
1466 && ( caller($index) )[3] eq '(eval)' );
1467
1468 if ( ( caller($index) )[3] =~ /forward$/ ) {
1469 $callsub = ( caller($index) )[3];
1470 $action = "-> $action";
1471 last;
1472 }
1473 }
1474
f3414019 1475 my $uid = $action_name . $c->counter->{$action_name};
74efc144 1476
a6724a82 1477 # is this a root-level call or a forwarded call?
1478 if ( $callsub =~ /forward$/ ) {
1479
1480 # forward, locate the caller
1481 if ( my $parent = $c->stack->[-1] ) {
69d8f33c 1482 $c->stats->profile(
ac5c933b 1483 begin => $action,
69d8f33c 1484 parent => "$parent" . $c->counter->{"$parent"},
1485 uid => $uid,
1486 );
7a7d7af5 1487 }
1488 else {
1489
a6724a82 1490 # forward with no caller may come from a plugin
69d8f33c 1491 $c->stats->profile(
1492 begin => $action,
1493 uid => $uid,
1494 );
7a7d7af5 1495 }
1496 }
a6724a82 1497 else {
ac5c933b 1498
a6724a82 1499 # root-level call
69d8f33c 1500 $c->stats->profile(
1501 begin => $action,
1502 uid => $uid,
1503 );
a6724a82 1504 }
dc5f035e 1505 return $action;
7a7d7af5 1506
7a7d7af5 1507}
1508
1509sub _stats_finish_execute {
1510 my ( $c, $info ) = @_;
69d8f33c 1511 $c->stats->profile( end => $info );
7a7d7af5 1512}
1513
3d0d6d21 1514=head2 $c->_localize_fields( sub { }, \%keys );
1515
1516=cut
1517
e63bdf38 1518#Why does this exist? This is no longer safe and WILL NOT WORK.
1519# it doesnt seem to be used anywhere. can we remove it?
3d0d6d21 1520sub _localize_fields {
1521 my ( $c, $localized, $code ) = ( @_ );
1522
1523 my $request = delete $localized->{request} || {};
1524 my $response = delete $localized->{response} || {};
ac5c933b 1525
3d0d6d21 1526 local @{ $c }{ keys %$localized } = values %$localized;
1527 local @{ $c->request }{ keys %$request } = values %$request;
1528 local @{ $c->response }{ keys %$response } = values %$response;
1529
1530 $code->();
1531}
1532
b5ecfcf0 1533=head2 $c->finalize
fbcc39ad 1534
e7f1cf73 1535Finalizes the request.
fbcc39ad 1536
1537=cut
1538
1539sub finalize {
1540 my $c = shift;
1541
369c09bc 1542 for my $error ( @{ $c->error } ) {
1543 $c->log->error($error);
1544 }
1545
5050d7a7 1546 # Allow engine to handle finalize flow (for POE)
e63bdf38 1547 my $engine = $c->engine;
1548 if ( my $code = $engine->can('finalize') ) {
1549 $engine->$code($c);
fbcc39ad 1550 }
5050d7a7 1551 else {
fbcc39ad 1552
5050d7a7 1553 $c->finalize_uploads;
fbcc39ad 1554
5050d7a7 1555 # Error
1556 if ( $#{ $c->error } >= 0 ) {
1557 $c->finalize_error;
1558 }
1559
1560 $c->finalize_headers;
fbcc39ad 1561
5050d7a7 1562 # HEAD request
1563 if ( $c->request->method eq 'HEAD' ) {
1564 $c->response->body('');
1565 }
1566
1567 $c->finalize_body;
1568 }
ac5c933b 1569
1570 if ($c->use_stats) {
596677b6 1571 my $elapsed = sprintf '%f', $c->stats->elapsed;
12bf12c0 1572 my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
908e3d9e 1573 $c->log->info(
ac5c933b 1574 "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
908e3d9e 1575 }
fbcc39ad 1576
1577 return $c->response->status;
1578}
1579
b5ecfcf0 1580=head2 $c->finalize_body
fbcc39ad 1581
e7f1cf73 1582Finalizes body.
fbcc39ad 1583
1584=cut
1585
1586sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1587
b5ecfcf0 1588=head2 $c->finalize_cookies
fbcc39ad 1589
e7f1cf73 1590Finalizes cookies.
fbcc39ad 1591
1592=cut
1593
147821ea 1594sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
fbcc39ad 1595
b5ecfcf0 1596=head2 $c->finalize_error
fbcc39ad 1597
e7f1cf73 1598Finalizes error.
fbcc39ad 1599
1600=cut
1601
1602sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1603
b5ecfcf0 1604=head2 $c->finalize_headers
fbcc39ad 1605
e7f1cf73 1606Finalizes headers.
fbcc39ad 1607
1608=cut
1609
1610sub finalize_headers {
1611 my $c = shift;
1612
e63bdf38 1613 my $response = $c->response; #accessor calls can add up?
1614
fbcc39ad 1615 # Check if we already finalized headers
6680c772 1616 return if $response->finalized_headers;
fbcc39ad 1617
1618 # Handle redirects
e63bdf38 1619 if ( my $location = $response->redirect ) {
fbcc39ad 1620 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
e63bdf38 1621 $response->header( Location => $location );
a7caa492 1622
02570318 1623 if ( !$response->has_body ) {
39655cdc 1624 # Add a default body if none is already present
e63bdf38 1625 $response->body(
e422816e 1626 qq{<html><body><p>This item has moved <a href="$location">here</a>.</p></body></html>}
39655cdc 1627 );
1628 }
fbcc39ad 1629 }
1630
1631 # Content-Length
e63bdf38 1632 if ( $response->body && !$response->content_length ) {
775878ac 1633
8f62c91a 1634 # get the length from a filehandle
e63bdf38 1635 if ( blessed( $response->body ) && $response->body->can('read') )
197bd788 1636 {
e63bdf38 1637 my $stat = stat $response->body;
3b6a1db1 1638 if ( $stat && $stat->size > 0 ) {
e63bdf38 1639 $response->content_length( $stat->size );
8f62c91a 1640 }
1641 else {
775878ac 1642 $c->log->warn('Serving filehandle without a content-length');
8f62c91a 1643 }
1644 }
1645 else {
b5d7a61f 1646 # everything should be bytes at this point, but just in case
e63bdf38 1647 $response->content_length( bytes::length( $response->body ) );
8f62c91a 1648 }
fbcc39ad 1649 }
1650
1651 # Errors
e63bdf38 1652 if ( $response->status =~ /^(1\d\d|[23]04)$/ ) {
1653 $response->headers->remove_header("Content-Length");
1654 $response->body('');
fbcc39ad 1655 }
1656
1657 $c->finalize_cookies;
1658
1659 $c->engine->finalize_headers( $c, @_ );
1660
1661 # Done
6680c772 1662 $response->finalized_headers(1);
fbcc39ad 1663}
1664
b5ecfcf0 1665=head2 $c->finalize_output
fbcc39ad 1666
1667An alias for finalize_body.
1668
b5ecfcf0 1669=head2 $c->finalize_read
fbcc39ad 1670
e7f1cf73 1671Finalizes the input after reading is complete.
fbcc39ad 1672
1673=cut
1674
1675sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1676
b5ecfcf0 1677=head2 $c->finalize_uploads
fbcc39ad 1678
ae1e6b59 1679Finalizes uploads. Cleans up any temporary files.
fbcc39ad 1680
1681=cut
1682
1683sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1684
b5ecfcf0 1685=head2 $c->get_action( $action, $namespace )
fbcc39ad 1686
e7f1cf73 1687Gets an action in a given namespace.
fbcc39ad 1688
1689=cut
1690
684d10ed 1691sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
fbcc39ad 1692
b5ecfcf0 1693=head2 $c->get_actions( $action, $namespace )
a9dc674c 1694
ae1e6b59 1695Gets all actions of a given name in a namespace and all parent
1696namespaces.
a9dc674c 1697
1698=cut
1699
1700sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1701
f7b672ef 1702=head2 $c->handle_request( $class, @arguments )
fbcc39ad 1703
e7f1cf73 1704Called to handle each HTTP request.
fbcc39ad 1705
1706=cut
1707
1708sub handle_request {
1709 my ( $class, @arguments ) = @_;
1710
1711 # Always expect worst case!
1712 my $status = -1;
1713 eval {
dea1884f 1714 if ($class->debug) {
908e3d9e 1715 my $secs = time - $START || 1;
1716 my $av = sprintf '%.3f', $COUNT / $secs;
1717 my $time = localtime time;
1718 $class->log->info("*** Request $COUNT ($av/s) [$$] [$time] ***");
dea1884f 1719 }
908e3d9e 1720
1721 my $c = $class->prepare(@arguments);
1722 $c->dispatch;
ac5c933b 1723 $status = $c->finalize;
fbcc39ad 1724 };
1725
1726 if ( my $error = $@ ) {
1727 chomp $error;
1728 $class->log->error(qq/Caught exception in engine "$error"/);
1729 }
1730
1731 $COUNT++;
6680c772 1732
1733 if(my $coderef = $class->log->can('_flush')){
1734 $class->log->$coderef();
1735 }
fbcc39ad 1736 return $status;
1737}
1738
b5ecfcf0 1739=head2 $c->prepare( @arguments )
fbcc39ad 1740
ae1e6b59 1741Creates a Catalyst context from an engine-specific request (Apache, CGI,
1742etc.).
fbcc39ad 1743
1744=cut
1745
1746sub prepare {
1747 my ( $class, @arguments ) = @_;
1748
6680c772 1749 # XXX
1750 # After the app/ctxt split, this should become an attribute based on something passed
1751 # into the application.
3cec521a 1752 $class->context_class( ref $class || $class ) unless $class->context_class;
6680c772 1753
1754 my $c = $class->context_class->new({});
1755
1756 # For on-demand data
1757 $c->request->_context($c);
1758 $c->response->_context($c);
fbcc39ad 1759
b6d4ee6e 1760 #surely this is not the most efficient way to do things...
dc5f035e 1761 $c->stats($class->stats_class->new)->enable($c->use_stats);
908e3d9e 1762 if ( $c->debug ) {
ac5c933b 1763 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
908e3d9e 1764 }
1765
e63bdf38 1766 #XXX reuse coderef from can
5050d7a7 1767 # Allow engine to direct the prepare flow (for POE)
1768 if ( $c->engine->can('prepare') ) {
1769 $c->engine->prepare( $c, @arguments );
1770 }
1771 else {
1772 $c->prepare_request(@arguments);
1773 $c->prepare_connection;
1774 $c->prepare_query_parameters;
1775 $c->prepare_headers;
1776 $c->prepare_cookies;
1777 $c->prepare_path;
1778
878b821c 1779 # Prepare the body for reading, either by prepare_body
1780 # or the user, if they are using $c->read
1781 $c->prepare_read;
ac5c933b 1782
878b821c 1783 # Parse the body unless the user wants it on-demand
1784 unless ( $c->config->{parse_on_demand} ) {
1785 $c->prepare_body;
1786 }
5050d7a7 1787 }
fbcc39ad 1788
fbcc39ad 1789 my $method = $c->req->method || '';
2f381252 1790 my $path = $c->req->path;
1791 $path = '/' unless length $path;
fbcc39ad 1792 my $address = $c->req->address || '';
1793
e3a13771 1794 $c->log->debug(qq/"$method" request for "$path" from "$address"/)
fbcc39ad 1795 if $c->debug;
1796
e3a13771 1797 $c->prepare_action;
1798
fbcc39ad 1799 return $c;
1800}
1801
b5ecfcf0 1802=head2 $c->prepare_action
fbcc39ad 1803
b4b01a8a 1804Prepares action. See L<Catalyst::Dispatcher>.
fbcc39ad 1805
1806=cut
1807
1808sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1809
b5ecfcf0 1810=head2 $c->prepare_body
fbcc39ad 1811
e7f1cf73 1812Prepares message body.
fbcc39ad 1813
1814=cut
1815
1816sub prepare_body {
1817 my $c = shift;
1818
0f56bbcf 1819 return if $c->request->_has_body;
fbcc39ad 1820
1821 # Initialize on-demand data
1822 $c->engine->prepare_body( $c, @_ );
1823 $c->prepare_parameters;
1824 $c->prepare_uploads;
1825
0584323b 1826 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1827 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1828 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1829 my $param = $c->req->body_parameters->{$key};
1830 my $value = defined($param) ? $param : '';
1831 $t->row( $key,
1832 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1833 }
1834 $c->log->debug( "Body Parameters are:\n" . $t->draw );
fbcc39ad 1835 }
1836}
1837
b5ecfcf0 1838=head2 $c->prepare_body_chunk( $chunk )
4bd82c41 1839
e7f1cf73 1840Prepares a chunk of data before sending it to L<HTTP::Body>.
4bd82c41 1841
b4b01a8a 1842See L<Catalyst::Engine>.
1843
4bd82c41 1844=cut
1845
4f5ebacd 1846sub prepare_body_chunk {
1847 my $c = shift;
4bd82c41 1848 $c->engine->prepare_body_chunk( $c, @_ );
1849}
1850
b5ecfcf0 1851=head2 $c->prepare_body_parameters
fbcc39ad 1852
e7f1cf73 1853Prepares body parameters.
fbcc39ad 1854
1855=cut
1856
1857sub prepare_body_parameters {
1858 my $c = shift;
1859 $c->engine->prepare_body_parameters( $c, @_ );
1860}
1861
b5ecfcf0 1862=head2 $c->prepare_connection
fbcc39ad 1863
e7f1cf73 1864Prepares connection.
fbcc39ad 1865
1866=cut
1867
1868sub prepare_connection {
1869 my $c = shift;
1870 $c->engine->prepare_connection( $c, @_ );
1871}
1872
b5ecfcf0 1873=head2 $c->prepare_cookies
fbcc39ad 1874
e7f1cf73 1875Prepares cookies.
fbcc39ad 1876
1877=cut
1878
1879sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1880
b5ecfcf0 1881=head2 $c->prepare_headers
fbcc39ad 1882
e7f1cf73 1883Prepares headers.
fbcc39ad 1884
1885=cut
1886
1887sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1888
b5ecfcf0 1889=head2 $c->prepare_parameters
fbcc39ad 1890
e7f1cf73 1891Prepares parameters.
fbcc39ad 1892
1893=cut
1894
1895sub prepare_parameters {
1896 my $c = shift;
1897 $c->prepare_body_parameters;
1898 $c->engine->prepare_parameters( $c, @_ );
1899}
1900
b5ecfcf0 1901=head2 $c->prepare_path
fbcc39ad 1902
e7f1cf73 1903Prepares path and base.
fbcc39ad 1904
1905=cut
1906
1907sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1908
b5ecfcf0 1909=head2 $c->prepare_query_parameters
fbcc39ad 1910
e7f1cf73 1911Prepares query parameters.
fbcc39ad 1912
1913=cut
1914
1915sub prepare_query_parameters {
1916 my $c = shift;
1917
1918 $c->engine->prepare_query_parameters( $c, @_ );
1919
0584323b 1920 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1921 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1922 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1923 my $param = $c->req->query_parameters->{$key};
fbcc39ad 1924 my $value = defined($param) ? $param : '';
8c113188 1925 $t->row( $key,
fbcc39ad 1926 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1927 }
0584323b 1928 $c->log->debug( "Query Parameters are:\n" . $t->draw );
fbcc39ad 1929 }
1930}
1931
b5ecfcf0 1932=head2 $c->prepare_read
fbcc39ad 1933
e7f1cf73 1934Prepares the input for reading.
fbcc39ad 1935
1936=cut
1937
1938sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1939
b5ecfcf0 1940=head2 $c->prepare_request
fbcc39ad 1941
e7f1cf73 1942Prepares the engine request.
fbcc39ad 1943
1944=cut
1945
1946sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1947
b5ecfcf0 1948=head2 $c->prepare_uploads
fbcc39ad 1949
e7f1cf73 1950Prepares uploads.
fbcc39ad 1951
1952=cut
1953
1954sub prepare_uploads {
1955 my $c = shift;
1956
1957 $c->engine->prepare_uploads( $c, @_ );
1958
1959 if ( $c->debug && keys %{ $c->request->uploads } ) {
8c113188 1960 my $t = Text::SimpleTable->new(
34d28dfd 1961 [ 12, 'Parameter' ],
1962 [ 26, 'Filename' ],
8c113188 1963 [ 18, 'Type' ],
1964 [ 9, 'Size' ]
1965 );
fbcc39ad 1966 for my $key ( sort keys %{ $c->request->uploads } ) {
1967 my $upload = $c->request->uploads->{$key};
1968 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
8c113188 1969 $t->row( $key, $u->filename, $u->type, $u->size );
fbcc39ad 1970 }
1971 }
1972 $c->log->debug( "File Uploads are:\n" . $t->draw );
1973 }
1974}
1975
b5ecfcf0 1976=head2 $c->prepare_write
fbcc39ad 1977
e7f1cf73 1978Prepares the output for writing.
fbcc39ad 1979
1980=cut
1981
1982sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1983
b5ecfcf0 1984=head2 $c->request_class
1f9cb7c1 1985
e7f1cf73 1986Returns or sets the request class.
1f9cb7c1 1987
b5ecfcf0 1988=head2 $c->response_class
1f9cb7c1 1989
e7f1cf73 1990Returns or sets the response class.
1f9cb7c1 1991
b5ecfcf0 1992=head2 $c->read( [$maxlength] )
fbcc39ad 1993
ae1e6b59 1994Reads a chunk of data from the request body. This method is designed to
1995be used in a while loop, reading C<$maxlength> bytes on every call.
1996C<$maxlength> defaults to the size of the request if not specified.
fbcc39ad 1997
cc95842f 1998You have to set C<< MyApp->config->{parse_on_demand} >> to use this
ae1e6b59 1999directly.
fbcc39ad 2000
878b821c 2001Warning: If you use read(), Catalyst will not process the body,
2002so you will not be able to access POST parameters or file uploads via
2003$c->request. You must handle all body parsing yourself.
2004
fbcc39ad 2005=cut
2006
2007sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
2008
b5ecfcf0 2009=head2 $c->run
fbcc39ad 2010
2011Starts the engine.
2012
2013=cut
2014
2015sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
2016
b5ecfcf0 2017=head2 $c->set_action( $action, $code, $namespace, $attrs )
fbcc39ad 2018
e7f1cf73 2019Sets an action in a given namespace.
fbcc39ad 2020
2021=cut
2022
2023sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
2024
b5ecfcf0 2025=head2 $c->setup_actions($component)
fbcc39ad 2026
e7f1cf73 2027Sets up actions for a component.
fbcc39ad 2028
2029=cut
2030
2031sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
2032
b5ecfcf0 2033=head2 $c->setup_components
fbcc39ad 2034
86418559 2035Sets up components. Specify a C<setup_components> config option to pass
2036additional options directly to L<Module::Pluggable>. To add additional
2037search paths, specify a key named C<search_extra> as an array
2038reference. Items in the array beginning with C<::> will have the
18de900e 2039application class name prepended to them.
fbcc39ad 2040
2f381252 2041All components found will also have any
2042L<Devel::InnerPackage|inner packages> loaded and set up as components.
2043Note, that modules which are B<not> an I<inner package> of the main
2044file namespace loaded will not be instantiated as components.
2045
fbcc39ad 2046=cut
2047
2048sub setup_components {
2049 my $class = shift;
2050
18de900e 2051 my @paths = qw( ::Controller ::C ::Model ::M ::View ::V );
2052 my $config = $class->config->{ setup_components };
2053 my $extra = delete $config->{ search_extra } || [];
ac5c933b 2054
18de900e 2055 push @paths, @$extra;
ac5c933b 2056
364d7324 2057 my $locator = Module::Pluggable::Object->new(
18de900e 2058 search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
2059 %$config
364d7324 2060 );
b94b200c 2061
2062 my @comps = sort { length $a <=> length $b } $locator->plugins;
2063 my %comps = map { $_ => 1 } @comps;
73e1183e 2064
2065 my $deprecated_component_names = grep { /::[CMV]::/ } @comps;
2066 $class->log->warn(qq{Your application is using the deprecated ::[MVC]:: type naming scheme.\n}.
2067 qq{Please switch your class names to ::Model::, ::View:: and ::Controller: as appropriate.\n}
19a24dbb 2068 ) if $deprecated_component_names;
73e1183e 2069
b94b200c 2070 for my $component ( @comps ) {
dd91afb5 2071
2072 # We pass ignore_loaded here so that overlay files for (e.g.)
2073 # Model::DBI::Schema sub-classes are loaded - if it's in @comps
2074 # we know M::P::O found a file on disk so this is safe
2075
f5a4863c 2076 Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } );
2077 #Class::MOP::load_class($component);
364d7324 2078
2079 my $module = $class->setup_component( $component );
2080 my %modules = (
2081 $component => $module,
2082 map {
2083 $_ => $class->setup_component( $_ )
ac5c933b 2084 } grep {
b94b200c 2085 not exists $comps{$_}
364d7324 2086 } Devel::InnerPackage::list_packages( $component )
2087 );
ac5c933b 2088
364d7324 2089 for my $key ( keys %modules ) {
2090 $class->components->{ $key } = $modules{ $key };
fbcc39ad 2091 }
364d7324 2092 }
2093}
fbcc39ad 2094
364d7324 2095=head2 $c->setup_component
fbcc39ad 2096
364d7324 2097=cut
fbcc39ad 2098
364d7324 2099sub setup_component {
2100 my( $class, $component ) = @_;
fbcc39ad 2101
364d7324 2102 unless ( $component->can( 'COMPONENT' ) ) {
2103 return $component;
2104 }
fbcc39ad 2105
364d7324 2106 my $suffix = Catalyst::Utils::class2classsuffix( $component );
2107 my $config = $class->config->{ $suffix } || {};
fbcc39ad 2108
364d7324 2109 my $instance = eval { $component->COMPONENT( $class, $config ); };
fbcc39ad 2110
2111 if ( my $error = $@ ) {
fbcc39ad 2112 chomp $error;
fbcc39ad 2113 Catalyst::Exception->throw(
364d7324 2114 message => qq/Couldn't instantiate component "$component", "$error"/
2115 );
fbcc39ad 2116 }
2117
364d7324 2118 Catalyst::Exception->throw(
2119 message =>
2120 qq/Couldn't instantiate component "$component", "COMPONENT() didn't return an object-like value"/
84ff88cf 2121 ) unless blessed($instance);
364d7324 2122
2123 return $instance;
fbcc39ad 2124}
2125
b5ecfcf0 2126=head2 $c->setup_dispatcher
fbcc39ad 2127
ae1e6b59 2128Sets up dispatcher.
2129
fbcc39ad 2130=cut
2131
2132sub setup_dispatcher {
2133 my ( $class, $dispatcher ) = @_;
2134
2135 if ($dispatcher) {
2136 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
2137 }
2138
cb69249e 2139 if ( my $env = Catalyst::Utils::env_value( $class, 'DISPATCHER' ) ) {
2140 $dispatcher = 'Catalyst::Dispatcher::' . $env;
fbcc39ad 2141 }
2142
2143 unless ($dispatcher) {
cb0354c6 2144 $dispatcher = $class->dispatcher_class;
fbcc39ad 2145 }
2146
e63bdf38 2147 Class::MOP::load_class($dispatcher);
fbcc39ad 2148
2149 # dispatcher instance
2150 $class->dispatcher( $dispatcher->new );
2151}
2152
b5ecfcf0 2153=head2 $c->setup_engine
fbcc39ad 2154
ae1e6b59 2155Sets up engine.
2156
fbcc39ad 2157=cut
2158
2159sub setup_engine {
2160 my ( $class, $engine ) = @_;
2161
2162 if ($engine) {
2163 $engine = 'Catalyst::Engine::' . $engine;
2164 }
2165
cb69249e 2166 if ( my $env = Catalyst::Utils::env_value( $class, 'ENGINE' ) ) {
2167 $engine = 'Catalyst::Engine::' . $env;
fbcc39ad 2168 }
2169
9b0a3e0f 2170 if ( $ENV{MOD_PERL} ) {
e106a59f 2171 my $meta = Class::MOP::get_metaclass_by_name($class);
74c89dea 2172
fbcc39ad 2173 # create the apache method
74c89dea 2174 $meta->add_method('apache' => sub { shift->engine->apache });
fbcc39ad 2175
2176 my ( $software, $version ) =
2177 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
2178
2179 $version =~ s/_//g;
2180 $version =~ s/(\.[^.]+)\./$1/g;
2181
2182 if ( $software eq 'mod_perl' ) {
2183
9b0a3e0f 2184 if ( !$engine ) {
22247e54 2185
9b0a3e0f 2186 if ( $version >= 1.99922 ) {
2187 $engine = 'Catalyst::Engine::Apache2::MP20';
2188 }
22247e54 2189
9b0a3e0f 2190 elsif ( $version >= 1.9901 ) {
2191 $engine = 'Catalyst::Engine::Apache2::MP19';
2192 }
22247e54 2193
9b0a3e0f 2194 elsif ( $version >= 1.24 ) {
2195 $engine = 'Catalyst::Engine::Apache::MP13';
2196 }
22247e54 2197
9b0a3e0f 2198 else {
2199 Catalyst::Exception->throw( message =>
2200 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
2201 }
fbcc39ad 2202
fbcc39ad 2203 }
2204
2205 # install the correct mod_perl handler
2206 if ( $version >= 1.9901 ) {
2207 *handler = sub : method {
2208 shift->handle_request(@_);
2209 };
2210 }
2211 else {
2212 *handler = sub ($$) { shift->handle_request(@_) };
2213 }
2214
2215 }
2216
2217 elsif ( $software eq 'Zeus-Perl' ) {
2218 $engine = 'Catalyst::Engine::Zeus';
2219 }
2220
2221 else {
2222 Catalyst::Exception->throw(
2223 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
2224 }
2225 }
2226
2227 unless ($engine) {
cb0354c6 2228 $engine = $class->engine_class;
fbcc39ad 2229 }
2230
e63bdf38 2231 Class::MOP::load_class($engine);
0e7f5826 2232
d54484bf 2233 # check for old engines that are no longer compatible
2234 my $old_engine;
0e7f5826 2235 if ( $engine->isa('Catalyst::Engine::Apache')
2236 && !Catalyst::Engine::Apache->VERSION )
d54484bf 2237 {
2238 $old_engine = 1;
2239 }
0e7f5826 2240
d54484bf 2241 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
0e7f5826 2242 && Catalyst::Engine::Server->VERSION le '0.02' )
d54484bf 2243 {
2244 $old_engine = 1;
2245 }
0e7f5826 2246
2247 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
2248 && $engine->VERSION eq '0.01' )
d54484bf 2249 {
2250 $old_engine = 1;
2251 }
0e7f5826 2252
2253 elsif ($engine->isa('Catalyst::Engine::Zeus')
2254 && $engine->VERSION eq '0.01' )
d54484bf 2255 {
2256 $old_engine = 1;
2257 }
fbcc39ad 2258
d54484bf 2259 if ($old_engine) {
2260 Catalyst::Exception->throw( message =>
0e7f5826 2261 qq/Engine "$engine" is not supported by this version of Catalyst/
d54484bf 2262 );
2263 }
0e7f5826 2264
fbcc39ad 2265 # engine instance
2266 $class->engine( $engine->new );
2267}
2268
b5ecfcf0 2269=head2 $c->setup_home
fbcc39ad 2270
ae1e6b59 2271Sets up the home directory.
2272
fbcc39ad 2273=cut
2274
2275sub setup_home {
2276 my ( $class, $home ) = @_;
2277
cb69249e 2278 if ( my $env = Catalyst::Utils::env_value( $class, 'HOME' ) ) {
2279 $home = $env;
fbcc39ad 2280 }
2281
b6d4ee6e 2282 $home ||= Catalyst::Utils::home($class);
fbcc39ad 2283
2284 if ($home) {
e63bdf38 2285 #I remember recently being scolded for assigning config values like this
fbcc39ad 2286 $class->config->{home} ||= $home;
a738ab68 2287 $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
fbcc39ad 2288 }
2289}
2290
b5ecfcf0 2291=head2 $c->setup_log
fbcc39ad 2292
0fa676a7 2293Sets up log by instantiating a L<Catalyst::Log|Catalyst::Log> object and
2294passing it to C<log()>. Pass in a comma-delimited list of levels to set the
2295log to.
2296
2297This method also installs a C<debug> method that returns a true value into the
2298catalyst subclass if the "debug" level is passed in the comma-delimited list,
2299or if the C<$CATALYST_DEBUG> environment variable is set to a true value.
2300
2301Note that if the log has already been setup, by either a previous call to
2302C<setup_log> or by a call such as C<< __PACKAGE__->log( MyLogger->new ) >>,
5baa3bbc 2303that this method won't actually set up the log object.
ae1e6b59 2304
fbcc39ad 2305=cut
2306
2307sub setup_log {
0fa676a7 2308 my ( $class, $levels ) = @_;
fbcc39ad 2309
5baa3bbc 2310 $levels ||= '';
2311 $levels =~ s/^\s+//;
2312 $levels =~ s/\s+$//;
2313 my %levels = map { $_ => 1 } split /\s*,\s*/, $levels || '';
2314
fbcc39ad 2315 unless ( $class->log ) {
0fa676a7 2316 $class->log( Catalyst::Log->new(keys %levels) );
fbcc39ad 2317 }
af3ff00e 2318
cb69249e 2319 my $env_debug = Catalyst::Utils::env_value( $class, 'DEBUG' );
0fa676a7 2320 if ( defined($env_debug) or $levels{debug} ) {
e106a59f 2321 Class::MOP::get_metaclass_by_name($class)->add_method('debug' => sub { 1 });
fbcc39ad 2322 $class->log->debug('Debug messages enabled');
2323 }
2324}
2325
b5ecfcf0 2326=head2 $c->setup_plugins
fbcc39ad 2327
ae1e6b59 2328Sets up plugins.
2329
fbcc39ad 2330=cut
2331
dc5f035e 2332=head2 $c->setup_stats
2333
2334Sets up timing statistics class.
2335
2336=cut
2337
2338sub setup_stats {
2339 my ( $class, $stats ) = @_;
2340
2341 Catalyst::Utils::ensure_class_loaded($class->stats_class);
2342
2343 my $env = Catalyst::Utils::env_value( $class, 'STATS' );
2344 if ( defined($env) ? $env : ($stats || $class->debug ) ) {
e106a59f 2345 Class::MOP::get_metaclass_by_name($class)->add_method('use_stats' => sub { 1 });
b01f0c69 2346 $class->log->debug('Statistics enabled');
dc5f035e 2347 }
2348}
2349
2350
ac5c933b 2351=head2 $c->registered_plugins
836e1134 2352
2353Returns a sorted list of the plugins which have either been stated in the
2354import list or which have been added via C<< MyApp->plugin(@args); >>.
2355
2356If passed a given plugin name, it will report a boolean value indicating
2357whether or not that plugin is loaded. A fully qualified name is required if
2358the plugin name does not begin with C<Catalyst::Plugin::>.
2359
2360 if ($c->registered_plugins('Some::Plugin')) {
2361 ...
2362 }
2363
2364=cut
fbcc39ad 2365
836e1134 2366{
97b58e17 2367
2368 sub registered_plugins {
836e1134 2369 my $proto = shift;
197bd788 2370 return sort keys %{ $proto->_plugins } unless @_;
836e1134 2371 my $plugin = shift;
d0d4d785 2372 return 1 if exists $proto->_plugins->{$plugin};
2373 return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
836e1134 2374 }
fbcc39ad 2375
836e1134 2376 sub _register_plugin {
2377 my ( $proto, $plugin, $instant ) = @_;
2378 my $class = ref $proto || $proto;
fbcc39ad 2379
dd91afb5 2380 # no ignore_loaded here, the plugin may already have been
2381 # defined in memory and we don't want to error on "no file" if so
2382
b6d4ee6e 2383 Class::MOP::load_class( $plugin );
fbcc39ad 2384
197bd788 2385 $proto->_plugins->{$plugin} = 1;
836e1134 2386 unless ($instant) {
fbcc39ad 2387 no strict 'refs';
e106a59f 2388 if ( my $meta = Class::MOP::get_metaclass_by_name($class) ) {
74c89dea 2389 my @superclasses = ($plugin, $meta->superclasses );
2390 $meta->superclasses(@superclasses);
5fb67d52 2391 } else {
2392 unshift @{"$class\::ISA"}, $plugin;
2393 }
fbcc39ad 2394 }
836e1134 2395 return $class;
2396 }
2397
2398 sub setup_plugins {
2399 my ( $class, $plugins ) = @_;
2400
d0d4d785 2401 $class->_plugins( {} ) unless $class->_plugins;
836e1134 2402 $plugins ||= [];
2403 for my $plugin ( reverse @$plugins ) {
2404
2405 unless ( $plugin =~ s/\A\+// ) {
2406 $plugin = "Catalyst::Plugin::$plugin";
2407 }
2408
2409 $class->_register_plugin($plugin);
2410 }
fbcc39ad 2411 }
2412}
2413
b5ecfcf0 2414=head2 $c->stack
8767c5a3 2415
86418559 2416Returns an arrayref of the internal execution stack (actions that are
2417currently executing).
8767c5a3 2418
dc5f035e 2419=head2 $c->stats_class
2420
2421Returns or sets the stats (timing statistics) class.
2422
2423=head2 $c->use_stats
2424
2425Returns 1 when stats collection is enabled. Stats collection is enabled
2426when the -Stats options is set, debug is on or when the <MYAPP>_STATS
2427environment variable is set.
2428
2429Note that this is a static method, not an accessor and should be overloaded
2430by declaring "sub use_stats { 1 }" in your MyApp.pm, not by calling $c->use_stats(1).
2431
2432=cut
2433
2434sub use_stats { 0 }
2435
2436
b5ecfcf0 2437=head2 $c->write( $data )
fbcc39ad 2438
ae1e6b59 2439Writes $data to the output stream. When using this method directly, you
2440will need to manually set the C<Content-Length> header to the length of
2441your output data, if known.
fbcc39ad 2442
2443=cut
2444
4f5ebacd 2445sub write {
2446 my $c = shift;
2447
2448 # Finalize headers if someone manually writes output
2449 $c->finalize_headers;
2450
2451 return $c->engine->write( $c, @_ );
2452}
fbcc39ad 2453
b5ecfcf0 2454=head2 version
bf88a181 2455
ae1e6b59 2456Returns the Catalyst version number. Mostly useful for "powered by"
2457messages in template systems.
bf88a181 2458
2459=cut
2460
2461sub version { return $Catalyst::VERSION }
2462
b0bb11ec 2463=head1 INTERNAL ACTIONS
2464
ae1e6b59 2465Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2466C<_ACTION>, and C<_END>. These are by default not shown in the private
3e705254 2467action table, but you can make them visible with a config parameter.
b0bb11ec 2468
2469 MyApp->config->{show_internal_actions} = 1;
2470
d2ee9760 2471=head1 CASE SENSITIVITY
2472
3e705254 2473By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
ae1e6b59 2474mapped to C</foo/bar>. You can activate case sensitivity with a config
3e705254 2475parameter.
d2ee9760 2476
2477 MyApp->config->{case_sensitive} = 1;
2478
3e705254 2479This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
fbcc39ad 2480
2481=head1 ON-DEMAND PARSER
2482
2483The request body is usually parsed at the beginning of a request,
878b821c 2484but if you want to handle input yourself, you can enable on-demand
2485parsing with a config parameter.
fbcc39ad 2486
2487 MyApp->config->{parse_on_demand} = 1;
ac5c933b 2488
fbcc39ad 2489=head1 PROXY SUPPORT
2490
ae1e6b59 2491Many production servers operate using the common double-server approach,
2492with a lightweight frontend web server passing requests to a larger
2493backend server. An application running on the backend server must deal
2494with two problems: the remote user always appears to be C<127.0.0.1> and
2495the server's hostname will appear to be C<localhost> regardless of the
2496virtual host that the user connected through.
fbcc39ad 2497
ae1e6b59 2498Catalyst will automatically detect this situation when you are running
2499the frontend and backend servers on the same machine. The following
2500changes are made to the request.
fbcc39ad 2501
ac5c933b 2502 $c->req->address is set to the user's real IP address, as read from
ae1e6b59 2503 the HTTP X-Forwarded-For header.
ac5c933b 2504
ae1e6b59 2505 The host value for $c->req->base and $c->req->uri is set to the real
2506 host, as read from the HTTP X-Forwarded-Host header.
fbcc39ad 2507
3e705254 2508Obviously, your web server must support these headers for this to work.
fbcc39ad 2509
ae1e6b59 2510In a more complex server farm environment where you may have your
2511frontend proxy server(s) on different machines, you will need to set a
2512configuration option to tell Catalyst to read the proxied data from the
2513headers.
fbcc39ad 2514
2515 MyApp->config->{using_frontend_proxy} = 1;
ac5c933b 2516
fbcc39ad 2517If you do not wish to use the proxy support at all, you may set:
d1a31ac6 2518
fbcc39ad 2519 MyApp->config->{ignore_frontend_proxy} = 1;
2520
2521=head1 THREAD SAFETY
2522
86418559 2523Catalyst has been tested under Apache 2's threading C<mpm_worker>,
2524C<mpm_winnt>, and the standalone forking HTTP server on Windows. We
2525believe the Catalyst core to be thread-safe.
fbcc39ad 2526
2527If you plan to operate in a threaded environment, remember that all other
3e705254 2528modules you are using must also be thread-safe. Some modules, most notably
2529L<DBD::SQLite>, are not thread-safe.
d1a31ac6 2530
3cb1db8c 2531=head1 SUPPORT
2532
2533IRC:
2534
4eaf7c88 2535 Join #catalyst on irc.perl.org.
3cb1db8c 2536
3e705254 2537Mailing Lists:
3cb1db8c 2538
6d4c3368 2539 http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
2540 http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
1985c30b 2541
432d507d 2542Web:
2543
2544 http://catalyst.perl.org
2545
0ef52a96 2546Wiki:
2547
2548 http://dev.catalyst.perl.org
2549
fc7ec1d9 2550=head1 SEE ALSO
2551
829a28ca 2552=head2 L<Task::Catalyst> - All you need to start with Catalyst
2553
b5ecfcf0 2554=head2 L<Catalyst::Manual> - The Catalyst Manual
e7f1cf73 2555
b5ecfcf0 2556=head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
61b1e958 2557
b5ecfcf0 2558=head2 L<Catalyst::Engine> - Core engine
61b1e958 2559
b5ecfcf0 2560=head2 L<Catalyst::Log> - Log class.
61b1e958 2561
b5ecfcf0 2562=head2 L<Catalyst::Request> - Request object
61b1e958 2563
b5ecfcf0 2564=head2 L<Catalyst::Response> - Response object
61b1e958 2565
b5ecfcf0 2566=head2 L<Catalyst::Test> - The test suite.
fc7ec1d9 2567
2f381252 2568=head1 PROJECT FOUNDER
2569
2570sri: Sebastian Riedel <sri@cpan.org>
fc7ec1d9 2571
2f381252 2572=head1 CONTRIBUTORS
15f0b5b7 2573
2f381252 2574abw: Andy Wardley
fbcc39ad 2575
2f381252 2576acme: Leon Brocard <leon@astray.com>
33108eaf 2577
f4a57de4 2578Andrew Bramble
2579
15f0b5b7 2580Andrew Ford
2581
2582Andrew Ruthven
2583
2f381252 2584andyg: Andy Grundman <andy@hybridized.org>
fbcc39ad 2585
2f381252 2586audreyt: Audrey Tang
15f0b5b7 2587
2f381252 2588bricas: Brian Cassidy <bricas@cpan.org>
0cf56dbc 2589
e31b525c 2590Caelum: Rafael Kitover <rkitover@io.com>
2591
2f381252 2592chansen: Christian Hansen
6aaa1c60 2593
2f381252 2594chicks: Christopher Hicks
15f0b5b7 2595
0fa676a7 2596David E. Wheeler
2597
2f381252 2598dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com>
15f0b5b7 2599
2f381252 2600Drew Taylor
15f0b5b7 2601
2f381252 2602esskar: Sascha Kiefer
0ef52a96 2603
2f381252 2604fireartist: Carl Franks <cfranks@cpan.org>
15f0b5b7 2605
2f381252 2606gabb: Danijel Milicevic
61bef238 2607
15f0b5b7 2608Gary Ashton Jones
2609
2610Geoff Richards
2611
e4cc83b2 2612ilmari: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
2613
2f381252 2614jcamacho: Juan Camacho
fbcc39ad 2615
108201b5 2616jhannah: Jay Hannah <jay@jays.net>
2617
15f0b5b7 2618Jody Belka
2619
2620Johan Lindstrom
2621
2f381252 2622jon: Jon Schutz <jjschutz@cpan.org>
15f0b5b7 2623
2f381252 2624marcus: Marcus Ramberg <mramberg@cpan.org>
15f0b5b7 2625
2f381252 2626miyagawa: Tatsuhiko Miyagawa <miyagawa@bulknews.net>
15f0b5b7 2627
2f381252 2628mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
15f0b5b7 2629
2f381252 2630mugwump: Sam Vilain
71c3bcc3 2631
2f381252 2632naughton: David Naughton
a727119f 2633
2f381252 2634ningu: David Kamholz <dkamholz@cpan.org>
1cf1c56a 2635
2f381252 2636nothingmuch: Yuval Kogman <nothingmuch@woobling.org>
9c71d51d 2637
2f381252 2638numa: Dan Sully <daniel@cpan.org>
fc7ec1d9 2639
2f381252 2640obra: Jesse Vincent
2641
2642omega: Andreas Marienborg
51f0308d 2643
39fc2ce1 2644Oleg Kostyuk <cub.uanic@gmail.com>
2645
2f381252 2646phaylon: Robert Sedlacek <phaylon@dunkelheit.at>
bdcb95ef 2647
6dae3eef 2648rafl: Florian Ragwitz <rafl@debian.org>
2649
2f381252 2650sky: Arthur Bergman
2651
2652the_jester: Jesse Sheidlower
2653
bb33cb06 2654t0m: Tomas Doran <bobtfish@bobtfish.net>
2655
2f381252 2656Ulf Edvinsson
51f0308d 2657
2f381252 2658willert: Sebastian Willert <willert@cpan.org>
51f0308d 2659
fc7ec1d9 2660=head1 LICENSE
2661
9ce5ab63 2662This library is free software, you can redistribute it and/or modify it under
41ca9ba7 2663the same terms as Perl itself.
fc7ec1d9 2664
2665=cut
2666
4090e3bb 2667no Moose;
2668
46d0346d 2669__PACKAGE__->meta->make_immutable;
2670
fc7ec1d9 26711;