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