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