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