Got rid of Path::Class imports
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
CommitLineData
fc7ec1d9 1package Catalyst;
2
3use strict;
31375184 4use base 'Catalyst::Component';
fbcc39ad 5use bytes;
fc7ec1d9 6use UNIVERSAL::require;
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;
8f62c91a 14use File::stat;
5d9a6d47 15use NEXT;
8c113188 16use Text::SimpleTable;
a738ab68 17use Path::Class::Dir;
18use Path::Class::File;
fbcc39ad 19use Time::HiRes qw/gettimeofday tv_interval/;
20use URI;
6a4a7002 21use Scalar::Util qw/weaken blessed/;
5513038d 22use Tree::Simple qw/use_weak_refs/;
23use Tree::Simple::Visitor::FindByUID;
261c571e 24use attributes;
fc7ec1d9 25
66e28e3f 26__PACKAGE__->mk_accessors(
28591cd7 27 qw/counter request response state action stack namespace/
66e28e3f 28);
10dd6896 29
684d10ed 30attributes->import( __PACKAGE__, \&namespace, 'lvalue' );
261c571e 31
8767c5a3 32sub depth { scalar @{ shift->stack || [] }; }
28591cd7 33
fbcc39ad 34# Laziness++
35*comp = \&component;
36*req = \&request;
37*res = \&response;
38
39# For backwards compatibility
40*finalize_output = \&finalize_body;
41
42# For statistics
43our $COUNT = 1;
44our $START = time;
45our $RECURSION = 1000;
46our $DETACH = "catalyst_detach\n";
47
48require Module::Pluggable::Fast;
49
50# Helper script generation
92ffbc90 51our $CATALYST_SCRIPT_GEN = 27;
fbcc39ad 52
53__PACKAGE__->mk_classdata($_)
3cec521a 54 for qw/components arguments dispatcher engine log dispatcher_class
3643e890 55 engine_class context_class request_class response_class setup_finished/;
cb0354c6 56
3cec521a 57__PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
58__PACKAGE__->engine_class('Catalyst::Engine::CGI');
59__PACKAGE__->request_class('Catalyst::Request');
60__PACKAGE__->response_class('Catalyst::Response');
fbcc39ad 61
97b58e17 62our $VERSION = '5.66';
189e2a51 63
fbcc39ad 64sub import {
65 my ( $class, @arguments ) = @_;
66
67 # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
68 # callers @ISA.
69 return unless $class eq 'Catalyst';
70
71 my $caller = caller(0);
72
73 unless ( $caller->isa('Catalyst') ) {
74 no strict 'refs';
31375184 75 push @{"$caller\::ISA"}, $class, 'Catalyst::Controller';
fbcc39ad 76 }
77
78 $caller->arguments( [@arguments] );
79 $caller->setup_home;
80}
fc7ec1d9 81
82=head1 NAME
83
84Catalyst - The Elegant MVC Web Application Framework
85
86=head1 SYNOPSIS
87
88 # use the helper to start a new application
91864987 89 catalyst.pl MyApp
fc7ec1d9 90
91 # add models, views, controllers
0ef52a96 92 script/myapp_create.pl model Database DBIC dbi:SQLite:/path/to/db
93 script/myapp_create.pl view TT TT
94 script/myapp_create.pl controller Search
fc7ec1d9 95
e7f1cf73 96 # built in testserver -- use -r to restart automatically on changes
ae4e40a7 97 script/myapp_server.pl
fc7ec1d9 98
0ef52a96 99 # command line testing interface
ae4e40a7 100 script/myapp_test.pl /yada
fc7ec1d9 101
0ef52a96 102 ### in MyApp.pm
103 use Catalyst qw/-Debug/; # include plugins here as well
104
105 sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
ae1e6b59 106 my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
107 $c->stash->{template} = 'foo.tt'; # set the template
0ef52a96 108 # lookup something from db -- stash vars are passed to TT
ae1e6b59 109 $c->stash->{data} =
110 MyApp::Model::Database::Foo->search( { country => $args[0] } );
0ef52a96 111 if ( $c->req->params->{bar} ) { # access GET or POST parameters
112 $c->forward( 'bar' ); # process another action
113 # do something else after forward returns
114 }
115 }
116
ae1e6b59 117 # The foo.tt TT template can use the stash data from the database
0ef52a96 118 [% WHILE (item = data.next) %]
119 [% item.foo %]
120 [% END %]
121
122 # called for /bar/of/soap, /bar/of/soap/10, etc.
123 sub bar : Path('/bar/of/soap') { ... }
fc7ec1d9 124
ae1e6b59 125 # called for all actions, from the top-most controller downwards
0ef52a96 126 sub auto : Private {
127 my ( $self, $c ) = @_;
128 if ( !$c->user ) {
129 $c->res->redirect( '/login' ); # require login
130 return 0; # abort request and go immediately to end()
131 }
ae1e6b59 132 return 1; # success; carry on to next action
0ef52a96 133 }
134
ae1e6b59 135 # called after all actions are finished
0ef52a96 136 sub end : Private {
5a8ed4fe 137 my ( $self, $c ) = @_;
0ef52a96 138 if ( scalar @{ $c->error } ) { ... } # handle errors
139 return if $c->res->body; # already have a response
140 $c->forward( 'MyApp::View::TT' ); # render template
5a8ed4fe 141 }
142
0ef52a96 143 ### in MyApp/Controller/Foo.pm
144 # called for /foo/bar
145 sub bar : Local { ... }
146
5400c668 147 # called for /blargle
148 sub blargle : Global { ... }
149
150 # an index action matches /foo, but not /foo/1, etc.
151 sub index : Private { ... }
0ef52a96 152
153 ### in MyApp/Controller/Foo/Bar.pm
154 # called for /foo/bar/baz
155 sub baz : Local { ... }
156
157 # first MyApp auto is called, then Foo auto, then this
158 sub auto : Private { ... }
159
160 # powerful regular expression paths are also possible
161 sub details : Regex('^product/(\w+)/details$') {
5a8ed4fe 162 my ( $self, $c ) = @_;
0ef52a96 163 # extract the (\w+) from the URI
164 my $product = $c->req->snippets->[0];
5a8ed4fe 165 }
fc7ec1d9 166
0ef52a96 167See L<Catalyst::Manual::Intro> for additional information.
3803e98f 168
fc7ec1d9 169=head1 DESCRIPTION
170
fc7ec1d9 171The key concept of Catalyst is DRY (Don't Repeat Yourself).
172
173See L<Catalyst::Manual> for more documentation.
174
ae1e6b59 175Catalyst plugins can be loaded by naming them as arguments to the "use
176Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the
177plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes
178C<My::Module>.
fc7ec1d9 179
0ef52a96 180 use Catalyst qw/My::Module/;
fc7ec1d9 181
836e1134 182If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
183fully qualify the name by using a unary plus:
184
185 use Catalyst qw/
186 My::Module
187 +Fully::Qualified::Plugin::Name
188 /;
189
ae1e6b59 190Special flags like C<-Debug> and C<-Engine> can also be specified as
191arguments when Catalyst is loaded:
fc7ec1d9 192
193 use Catalyst qw/-Debug My::Module/;
194
ae1e6b59 195The position of plugins and flags in the chain is important, because
196they are loaded in exactly the order in which they appear.
fc7ec1d9 197
23f9d934 198The following flags are supported:
199
b5ecfcf0 200=head2 -Debug
23f9d934 201
0ef52a96 202Enables debug output.
fc7ec1d9 203
b5ecfcf0 204=head2 -Engine
fc7ec1d9 205
ae1e6b59 206Forces Catalyst to use a specific engine. Omit the
207C<Catalyst::Engine::> prefix of the engine name, i.e.:
fc7ec1d9 208
0ef52a96 209 use Catalyst qw/-Engine=CGI/;
fc7ec1d9 210
b5ecfcf0 211=head2 -Home
fbcc39ad 212
ae1e6b59 213Forces Catalyst to use a specific home directory, e.g.:
214
215 use Catalyst qw[-Home=/usr/sri];
fbcc39ad 216
b5ecfcf0 217=head2 -Log
fbcc39ad 218
0ef52a96 219Specifies log level.
fbcc39ad 220
23f9d934 221=head1 METHODS
222
f7b672ef 223=head2 INFORMATION ABOUT THE CURRENT REQUEST
0ef52a96 224
b5ecfcf0 225=head2 $c->action
66e28e3f 226
ae1e6b59 227Returns a L<Catalyst::Action> object for the current action, which
228stringifies to the action name. See L<Catalyst::Action>.
0ef52a96 229
b5ecfcf0 230=head2 $c->namespace
0ef52a96 231
ae1e6b59 232Returns the namespace of the current action, i.e., the uri prefix
233corresponding to the controller of the current action. For example:
234
235 # in Controller::Foo::Bar
236 $c->namespace; # returns 'foo/bar';
0ef52a96 237
b5ecfcf0 238=head2 $c->request
0ef52a96 239
b5ecfcf0 240=head2 $c->req
0ef52a96 241
ae1e6b59 242Returns the current L<Catalyst::Request> object. See
243L<Catalyst::Request>.
0ef52a96 244
f7b672ef 245=head2 PROCESSING AND RESPONSE TO THE CURRENT REQUEST
0ef52a96 246
b5ecfcf0 247=head2 $c->forward( $action [, \@arguments ] )
0ef52a96 248
b5ecfcf0 249=head2 $c->forward( $class, $method, [, \@arguments ] )
0ef52a96 250
ae1e6b59 251Forwards processing to a private action. If you give a class name but no
252method, C<process()> is called. You may also optionally pass arguments
253in an arrayref. The action will receive the arguments in C<@_> and
254C<$c-E<gt>req-E<gt>args>. Upon returning from the function,
255C<$c-E<gt>req-E<gt>args> will be restored to the previous values.
0ef52a96 256
3b984c64 257Any data C<return>ed from the action forwarded to, will be returned by the
d759db1e 258call to forward.
3b984c64 259
260 my $foodata = $c->forward('/foo');
0ef52a96 261 $c->forward('index');
e112461a 262 $c->forward(qw/MyApp::Model::DBIC::Foo do_stuff/);
0ef52a96 263 $c->forward('MyApp::View::TT');
264
265=cut
266
267sub forward { my $c = shift; $c->dispatcher->forward( $c, @_ ) }
268
b5ecfcf0 269=head2 $c->detach( $action [, \@arguments ] )
0ef52a96 270
b5ecfcf0 271=head2 $c->detach( $class, $method, [, \@arguments ] )
0ef52a96 272
273The same as C<forward>, but doesn't return.
274
275=cut
276
277sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
278
b5ecfcf0 279=head2 $c->error
0ef52a96 280
b5ecfcf0 281=head2 $c->error($error, ...)
0ef52a96 282
b5ecfcf0 283=head2 $c->error($arrayref)
0ef52a96 284
83a8fcac 285Returns an arrayref containing error messages. If Catalyst encounters an
286error while processing a request, it stores the error in $c->error. This
287method should not be used to store non-fatal error messages.
0ef52a96 288
289 my @error = @{ $c->error };
290
291Add a new error.
292
293 $c->error('Something bad happened');
294
0ef52a96 295=cut
296
297sub error {
298 my $c = shift;
299 if ( $_[0] ) {
300 my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
301 push @{ $c->{error} }, @$error;
302 }
303 elsif ( defined $_[0] ) { $c->{error} = undef }
304 return $c->{error} || [];
305}
306
ca81eb67 307=head2 $c->clear_errors
308
309Clear errors. You probably don't want to clear the errors unless you are
310implementing a custom error screen.
311
312This is equivalent to running
313
314 $c->error(0);
315
316=cut
317
318sub clear_errors {
319 my $c = shift;
320 $c->error(0);
321}
322
b5ecfcf0 323=head2 $c->response
0ef52a96 324
b5ecfcf0 325=head2 $c->res
0ef52a96 326
327Returns the current L<Catalyst::Response> object.
328
b5ecfcf0 329=head2 $c->stash
0ef52a96 330
ae1e6b59 331Returns a hashref to the stash, which may be used to store data and pass
332it between components during a request. You can also set hash keys by
333passing arguments. The stash is automatically sent to the view. The
334stash is cleared at the end of a request; it cannot be used for
335persistent storage.
0ef52a96 336
337 $c->stash->{foo} = $bar;
338 $c->stash( { moose => 'majestic', qux => 0 } );
339 $c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref
340
341 # stash is automatically passed to the view for use in a template
342 $c->forward( 'MyApp::V::TT' );
343
344=cut
345
346sub stash {
347 my $c = shift;
348 if (@_) {
349 my $stash = @_ > 1 ? {@_} : $_[0];
350 while ( my ( $key, $val ) = each %$stash ) {
351 $c->{stash}->{$key} = $val;
352 }
353 }
354 return $c->{stash};
355}
356
b5ecfcf0 357=head2 $c->state
0ef52a96 358
359Contains the return value of the last executed action.
360
0756fe3b 361=cut
362
363# search via regex
364sub _comp_search {
365 my ($c, @names) = @_;
366
367 foreach my $name (@names) {
368 foreach my $component ( keys %{ $c->components } ) {
369 my $comp = $c->components->{$component} if $component =~ /$name/i;
370 if ($comp) {
371 if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
372 return $comp->ACCEPT_CONTEXT($c);
373 }
374 else { return $comp }
375 }
376 }
377 }
378
379 return undef;
380}
381
382# try explicit component names
383sub _comp_explicit {
384 my ($c, @names) = @_;
385
386 foreach my $try (@names) {
387 if ( exists $c->components->{$try} ) {
388 my $comp = $c->components->{$try};
389 if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
390 return $comp->ACCEPT_CONTEXT($c);
391 }
392 else { return $comp }
393 }
394 }
395
396 return undef;
397}
398
399# like component, but try just these prefixes before regex searching,
400# and do not try to return "sort keys %{ $c->components }"
401sub _comp_prefixes {
402 my ($c, $name, @prefixes) = @_;
403
404 my $appclass = ref $c || $c;
405
406 my @names = map { "${appclass}::${_}::${name}" } @prefixes;
407
408 my $comp = $c->_comp_explicit(@names);
409 return $comp if defined($comp);
410 $comp = $c->_comp_search($name);
411 return $comp;
412}
413
649fd1fa 414# Return a component if only one matches.
415sub _comp_singular {
416 my ($c, @prefixes) = @_;
417
418 my $appclass = ref $c || $c;
419
420 my ($comp,$rest) = map { $c->_comp_search("^${appclass}::${_}::") }
421 @prefixes;
422 return $comp unless $rest;
423}
424
f7b672ef 425=head2 COMPONENT ACCESSORS
0ef52a96 426
b5ecfcf0 427=head2 $c->comp($name)
66e28e3f 428
b5ecfcf0 429=head2 $c->component($name)
fbcc39ad 430
ae1e6b59 431Gets a component object by name. This method is no longer recommended,
432unless you want to get a specific component by full
433class. C<$c-E<gt>controller>, C<$c-E<gt>model>, and C<$c-E<gt>view>
434should be used instead.
fbcc39ad 435
436=cut
437
438sub component {
439 my $c = shift;
440
441 if (@_) {
442
443 my $name = shift;
444
445 my $appclass = ref $c || $c;
446
447 my @names = (
448 $name, "${appclass}::${name}",
e3a13771 449 map { "${appclass}::${_}::${name}" }
450 qw/Model M Controller C View V/
fbcc39ad 451 );
452
0756fe3b 453 my $comp = $c->_comp_explicit(@names);
454 return $comp if defined($comp);
fbcc39ad 455
0756fe3b 456 $comp = $c->_comp_search($name);
457 return $comp if defined($comp);
fbcc39ad 458 }
459
460 return sort keys %{ $c->components };
461}
462
b5ecfcf0 463=head2 $c->controller($name)
af3ff00e 464
0ef52a96 465Gets a L<Catalyst::Controller> instance by name.
af3ff00e 466
467 $c->controller('Foo')->do_stuff;
468
649fd1fa 469If name is omitted, will return the controller for the dispatched action.
470
af3ff00e 471=cut
472
473sub controller {
474 my ( $c, $name ) = @_;
649fd1fa 475 return $c->_comp_prefixes($name, qw/Controller C/)
476 if ($name);
477 return $c->component($c->action->class);
af3ff00e 478}
479
b5ecfcf0 480=head2 $c->model($name)
fc7ec1d9 481
0ef52a96 482Gets a L<Catalyst::Model> instance by name.
483
484 $c->model('Foo')->do_stuff;
fc7ec1d9 485
649fd1fa 486If the name is omitted, it will look for a config setting 'default_model',
487or check if there is only one model, and forward to it if that's the case.
488
fc7ec1d9 489=cut
490
0ef52a96 491sub model {
492 my ( $c, $name ) = @_;
649fd1fa 493 return $c->_comp_prefixes($name, qw/Model M/)
494 if $name;
495 return $c->comp($c->config->{default_model})
496 if $c->config->{default_model};
497 return $c->_comp_singular(qw/Model M/);
498
0ef52a96 499}
fc7ec1d9 500
b5ecfcf0 501=head2 $c->view($name)
0ef52a96 502
503Gets a L<Catalyst::View> instance by name.
fc7ec1d9 504
0ef52a96 505 $c->view('Foo')->do_stuff;
fc7ec1d9 506
649fd1fa 507If the name is omitted, it will look for a config setting 'default_view',
508or check if there is only one view, and forward to it if that's the case.
509
fc7ec1d9 510=cut
511
0ef52a96 512sub view {
513 my ( $c, $name ) = @_;
649fd1fa 514 return $c->_comp_prefixes($name, qw/View V/)
515 if $name;
516 return $c->comp($c->config->{default_view})
517 if $c->config->{default_view};
518 return $c->_comp_singular(qw/View V/);
0ef52a96 519}
fbcc39ad 520
0ef52a96 521=head2 Class data and helper classes
fbcc39ad 522
b5ecfcf0 523=head2 $c->config
fbcc39ad 524
0ef52a96 525Returns or takes a hashref containing the application's configuration.
526
61b1d329 527 __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } );
81557adf 528
a6ad13b6 529You can also use a L<YAML> config file like myapp.yml in your
530applications home directory.
531
532 ---
533 db: dsn:SQLite:foo.db
534
3643e890 535=cut
536
537sub config {
538 my $c = shift;
539
540 $c->log->warn("Setting config after setup has been run is not a good idea.")
541 if ( @_ and $c->setup_finished );
542
543 $c->NEXT::config(@_);
544}
545
b5ecfcf0 546=head2 $c->debug
0ef52a96 547
548Overload to enable debug messages (same as -Debug option).
fbcc39ad 549
550=cut
551
0ef52a96 552sub debug { 0 }
fbcc39ad 553
b5ecfcf0 554=head2 $c->dispatcher
af3ff00e 555
ae1e6b59 556Returns the dispatcher instance. Stringifies to class name. See
557L<Catalyst::Dispatcher>.
af3ff00e 558
b5ecfcf0 559=head2 $c->engine
0ef52a96 560
ae1e6b59 561Returns the engine instance. Stringifies to the class name. See
562L<Catalyst::Engine>.
0ef52a96 563
b5ecfcf0 564=head2 $c->log
0ef52a96 565
9e7673af 566Returns the logging object instance. Unless it is already set, Catalyst sets
567this up with a L<Catalyst::Log> object. To use your own log class, set the
568logger with the C<< __PACKAGE__->log >> method prior to calling
569C<< __PACKAGE__->setup >>.
570
571 __PACKAGE__->log( MyLogger->new );
572 __PACKAGE__->setup;
573
574And later:
0ef52a96 575
ae1e6b59 576 $c->log->info( 'Now logging with my own logger!' );
0ef52a96 577
ae1e6b59 578Your log class should implement the methods described in the
579L<Catalyst::Log> man page.
af3ff00e 580
581=cut
582
f7b672ef 583=head2 UTILITY METHODS
66e28e3f 584
b5ecfcf0 585=head2 $c->path_to(@path)
01033d73 586
ae1e6b59 587Merges C<@path> with C<$c-E<gt>config-E<gt>{home}> and returns a
588L<Path::Class> object.
01033d73 589
590For example:
591
592 $c->path_to( 'db', 'sqlite.db' );
593
594=cut
595
596sub path_to {
597 my ( $c, @path ) = @_;
a738ab68 598 my $path = Path::Class::Dir->new( $c->config->{home}, @path );
01033d73 599 if ( -d $path ) { return $path }
a738ab68 600 else { return Path::Class::File->new( $c->config->{home}, @path ) }
01033d73 601}
602
b5ecfcf0 603=head2 $c->plugin( $name, $class, @args )
0ef52a96 604
ae1e6b59 605Helper method for plugins. It creates a classdata accessor/mutator and
606loads and instantiates the given class.
0ef52a96 607
608 MyApp->plugin( 'prototype', 'HTML::Prototype' );
609
610 $c->prototype->define_javascript_functions;
611
612=cut
613
614sub plugin {
615 my ( $class, $name, $plugin, @args ) = @_;
97b58e17 616 $class->_register_plugin( $plugin, 1 );
0ef52a96 617
618 eval { $plugin->import };
619 $class->mk_classdata($name);
620 my $obj;
621 eval { $obj = $plugin->new(@args) };
622
623 if ($@) {
624 Catalyst::Exception->throw( message =>
625 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
626 }
627
628 $class->$name($obj);
629 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
630 if $class->debug;
631}
632
b5ecfcf0 633=head2 MyApp->setup
fbcc39ad 634
e7f1cf73 635Initializes the dispatcher and engine, loads any plugins, and loads the
ae1e6b59 636model, view, and controller components. You may also specify an array
637of plugins to load here, if you choose to not load them in the C<use
638Catalyst> line.
fbcc39ad 639
0ef52a96 640 MyApp->setup;
641 MyApp->setup( qw/-Debug/ );
fbcc39ad 642
643=cut
644
645sub setup {
0319a12c 646 my ( $class, @arguments ) = @_;
599b5295 647
fbcc39ad 648 unless ( $class->isa('Catalyst') ) {
953b0e15 649
fbcc39ad 650 Catalyst::Exception->throw(
651 message => qq/'$class' does not inherit from Catalyst/ );
1c99e125 652 }
0319a12c 653
fbcc39ad 654 if ( $class->arguments ) {
655 @arguments = ( @arguments, @{ $class->arguments } );
656 }
657
658 # Process options
659 my $flags = {};
660
661 foreach (@arguments) {
662
663 if (/^-Debug$/) {
664 $flags->{log} =
665 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
666 }
667 elsif (/^-(\w+)=?(.*)$/) {
668 $flags->{ lc $1 } = $2;
669 }
670 else {
671 push @{ $flags->{plugins} }, $_;
672 }
673 }
674
99f187d6 675 $class->setup_home( delete $flags->{home} );
676
fbcc39ad 677 $class->setup_log( delete $flags->{log} );
678 $class->setup_plugins( delete $flags->{plugins} );
679 $class->setup_dispatcher( delete $flags->{dispatcher} );
680 $class->setup_engine( delete $flags->{engine} );
fbcc39ad 681
682 for my $flag ( sort keys %{$flags} ) {
683
684 if ( my $code = $class->can( 'setup_' . $flag ) ) {
685 &$code( $class, delete $flags->{$flag} );
686 }
687 else {
688 $class->log->warn(qq/Unknown flag "$flag"/);
689 }
690 }
691
4ff0d824 692 $class->log->warn(
693 <<"EOF") if ( $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::CATALYST_SCRIPT_GEN ) );
694You are running an old script!
695
34a83d89 696 Please update by running (this will overwrite existing files):
697 catalyst.pl -force -scripts $class
698
699 or (this will not overwrite existing files):
700 catalyst.pl -scripts $class
4ff0d824 701EOF
fbcc39ad 702
703 if ( $class->debug ) {
704
705 my @plugins = ();
706
707 {
708 no strict 'refs';
22247e54 709 @plugins =
710 map { $_ . ' ' . ( $_->VERSION || '' ) }
711 grep { /^Catalyst::Plugin/ } @{"$class\::ISA"};
fbcc39ad 712 }
713
714 if (@plugins) {
8c113188 715 my $t = Text::SimpleTable->new(76);
716 $t->row($_) for @plugins;
fbcc39ad 717 $class->log->debug( "Loaded plugins:\n" . $t->draw );
718 }
719
720 my $dispatcher = $class->dispatcher;
721 my $engine = $class->engine;
722 my $home = $class->config->{home};
723
724 $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
725 $class->log->debug(qq/Loaded engine "$engine"/);
726
727 $home
728 ? ( -d $home )
729 ? $class->log->debug(qq/Found home "$home"/)
730 : $class->log->debug(qq/Home "$home" doesn't exist/)
731 : $class->log->debug(q/Couldn't find home/);
732 }
733
734 # Call plugins setup
735 {
736 no warnings qw/redefine/;
737 local *setup = sub { };
738 $class->setup;
739 }
740
741 # Initialize our data structure
742 $class->components( {} );
743
744 $class->setup_components;
745
746 if ( $class->debug ) {
9d3e016e 747 my $t = Text::SimpleTable->new( [ 65, 'Class' ], [ 8, 'Type' ] );
684d10ed 748 for my $comp ( sort keys %{ $class->components } ) {
749 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
750 $t->row( $comp, $type );
751 }
fbcc39ad 752 $class->log->debug( "Loaded components:\n" . $t->draw )
8c113188 753 if ( keys %{ $class->components } );
fbcc39ad 754 }
755
756 # Add our self to components, since we are also a component
757 $class->components->{$class} = $class;
758
759 $class->setup_actions;
760
761 if ( $class->debug ) {
762 my $name = $class->config->{name} || 'Application';
763 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
764 }
765 $class->log->_flush() if $class->log->can('_flush');
3643e890 766
767 $class->setup_finished(1);
fbcc39ad 768}
769
b5ecfcf0 770=head2 $c->uri_for( $path, [ @args ] )
fbcc39ad 771
ae1e6b59 772Merges path with C<$c-E<gt>request-E<gt>base> for absolute uri's and
ccc9f8aa 773with C<$c-E<gt>namespace> for relative uri's, then returns a
ae1e6b59 774normalized L<URI> object. If any args are passed, they are added at the
4f67eddf 775end of the path. If the last argument to uri_for is a hash reference,
776it is assumed to contain GET parameter key/value pairs, which will be
777appended to the URI in standard fashion.
fbcc39ad 778
779=cut
780
781sub uri_for {
00e6a2b7 782 my ( $c, $path, @args ) = @_;
fbcc39ad 783 my $base = $c->request->base->clone;
784 my $basepath = $base->path;
785 $basepath =~ s/\/$//;
fdba7a9d 786 $basepath .= '/';
ccc9f8aa 787 my $namespace = $c->namespace;
00e6a2b7 788
ccc9f8aa 789 # massage namespace, empty if absolute path
790 $namespace =~ s/^\///;
791 $namespace .= '/' if $namespace;
6e0c45c9 792 $path ||= '';
ccc9f8aa 793 $namespace = '' if $path =~ /^\//;
fbcc39ad 794 $path =~ s/^\///;
00e6a2b7 795
97b58e17 796 my $params =
797 ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
8327e2e2 798
189e2a51 799 # join args with '/', or a blank string
00e6a2b7 800 my $args = ( scalar @args ? '/' . join( '/', @args ) : '' );
d3e7a648 801 $args =~ s/^\/// unless $path;
802 my $res =
803 URI->new_abs( URI->new_abs( "$path$args", "$basepath$namespace" ), $base )
804 ->canonical;
8327e2e2 805 $res->query_form(%$params);
d3e7a648 806 $res;
fbcc39ad 807}
808
b5ecfcf0 809=head2 $c->welcome_message
ab2374d3 810
811Returns the Catalyst welcome HTML page.
812
813=cut
814
815sub welcome_message {
bf1f2c60 816 my $c = shift;
817 my $name = $c->config->{name};
818 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
819 my $prefix = Catalyst::Utils::appprefix( ref $c );
80cdbbff 820 $c->response->content_type('text/html; charset=utf-8');
ab2374d3 821 return <<"EOF";
80cdbbff 822<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
823 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
824<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
ab2374d3 825 <head>
80cdbbff 826 <meta http-equiv="Content-Language" content="en" />
827 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
ab2374d3 828 <title>$name on Catalyst $VERSION</title>
829 <style type="text/css">
830 body {
ab2374d3 831 color: #000;
832 background-color: #eee;
833 }
834 div#content {
835 width: 640px;
80cdbbff 836 margin-left: auto;
837 margin-right: auto;
ab2374d3 838 margin-top: 10px;
839 margin-bottom: 10px;
840 text-align: left;
841 background-color: #ccc;
842 border: 1px solid #aaa;
843 -moz-border-radius: 10px;
844 }
d84c4dab 845 p, h1, h2 {
ab2374d3 846 margin-left: 20px;
847 margin-right: 20px;
16215972 848 font-family: verdana, tahoma, sans-serif;
ab2374d3 849 }
d84c4dab 850 a {
851 font-family: verdana, tahoma, sans-serif;
852 }
d114e033 853 :link, :visited {
854 text-decoration: none;
855 color: #b00;
856 border-bottom: 1px dotted #bbb;
857 }
858 :link:hover, :visited:hover {
d114e033 859 color: #555;
860 }
ab2374d3 861 div#topbar {
862 margin: 0px;
863 }
3e82a295 864 pre {
3e82a295 865 margin: 10px;
866 padding: 8px;
867 }
ab2374d3 868 div#answers {
869 padding: 8px;
870 margin: 10px;
d114e033 871 background-color: #fff;
ab2374d3 872 border: 1px solid #aaa;
873 -moz-border-radius: 10px;
874 }
875 h1 {
33108eaf 876 font-size: 0.9em;
877 font-weight: normal;
ab2374d3 878 text-align: center;
879 }
880 h2 {
881 font-size: 1.0em;
882 }
883 p {
884 font-size: 0.9em;
885 }
ae7c5252 886 p img {
887 float: right;
888 margin-left: 10px;
889 }
9619f23c 890 span#appname {
891 font-weight: bold;
33108eaf 892 font-size: 1.6em;
ab2374d3 893 }
894 </style>
895 </head>
896 <body>
897 <div id="content">
898 <div id="topbar">
9619f23c 899 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
d84c4dab 900 $VERSION</h1>
ab2374d3 901 </div>
902 <div id="answers">
ae7c5252 903 <p>
80cdbbff 904 <img src="$logo" alt="Catalyst Logo" />
ae7c5252 905 </p>
4b8cb778 906 <p>Welcome to the wonderful world of Catalyst.
f92fd545 907 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
908 framework will make web development something you had
60dd6e1d 909 never expected it to be: Fun, rewarding, and quick.</p>
ab2374d3 910 <h2>What to do now?</h2>
4b8cb778 911 <p>That really depends on what <b>you</b> want to do.
ab2374d3 912 We do, however, provide you with a few starting points.</p>
913 <p>If you want to jump right into web development with Catalyst
5db7f9a1 914 you might want to check out the documentation.</p>
bf1f2c60 915 <pre><code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
1667d231 916perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
bf1f2c60 917perldoc <a href="http://cpansearch.perl.org/dist/Catalyst/lib/Catalyst/Manual.pod">Catalyst::Manual</a></code></pre>
ab2374d3 918 <h2>What to do next?</h2>
f5681c92 919 <p>Next it's time to write an actual application. Use the
80cdbbff 920 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&amp;mode=all">controllers</a>,
60dd6e1d 921 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&amp;mode=all">models</a>, and
922 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&amp;mode=all">views</a>;
bf1f2c60 923 they can save you a lot of work.</p>
924 <pre><code>script/${prefix}_create.pl -help</code></pre>
925 <p>Also, be sure to check out the vast and growing
60dd6e1d 926 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 927 you are likely to find what you need there.
f5681c92 928 </p>
929
82245cc4 930 <h2>Need help?</h2>
f5681c92 931 <p>Catalyst has a very active community. Here are the main places to
932 get in touch with us.</p>
16215972 933 <ul>
934 <li>
2b9a7d76 935 <a href="http://dev.catalyst.perl.org">Wiki</a>
16215972 936 </li>
937 <li>
938 <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
939 </li>
940 <li>
ea7cd80d 941 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
16215972 942 </li>
943 </ul>
ab2374d3 944 <h2>In conclusion</h2>
4e7aa2ea 945 <p>The Catalyst team hopes you will enjoy using Catalyst as much
f5681c92 946 as we enjoyed making it. Please contact us if you have ideas
947 for improvement or other feedback.</p>
ab2374d3 948 </div>
949 </div>
950 </body>
951</html>
952EOF
953}
954
fbcc39ad 955=head1 INTERNAL METHODS
956
ae1e6b59 957These methods are not meant to be used by end users.
958
b5ecfcf0 959=head2 $c->components
fbcc39ad 960
e7f1cf73 961Returns a hash of components.
fbcc39ad 962
b5ecfcf0 963=head2 $c->context_class
1f9cb7c1 964
e7f1cf73 965Returns or sets the context class.
1f9cb7c1 966
b5ecfcf0 967=head2 $c->counter
fbcc39ad 968
ae1e6b59 969Returns a hashref containing coderefs and execution counts (needed for
970deep recursion detection).
fbcc39ad 971
b5ecfcf0 972=head2 $c->depth
fbcc39ad 973
e7f1cf73 974Returns the number of actions on the current internal execution stack.
fbcc39ad 975
b5ecfcf0 976=head2 $c->dispatch
fbcc39ad 977
e7f1cf73 978Dispatches a request to actions.
fbcc39ad 979
980=cut
981
982sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
983
b5ecfcf0 984=head2 $c->dispatcher_class
1f9cb7c1 985
e7f1cf73 986Returns or sets the dispatcher class.
1f9cb7c1 987
b5ecfcf0 988=head2 $c->dump_these
7f92deef 989
ae1e6b59 990Returns a list of 2-element array references (name, structure) pairs
991that will be dumped on the error page in debug mode.
7f92deef 992
993=cut
994
995sub dump_these {
996 my $c = shift;
997 [ Request => $c->req ], [ Response => $c->res ], [ Stash => $c->stash ],;
998}
999
b5ecfcf0 1000=head2 $c->engine_class
1f9cb7c1 1001
e7f1cf73 1002Returns or sets the engine class.
1f9cb7c1 1003
b5ecfcf0 1004=head2 $c->execute( $class, $coderef )
fbcc39ad 1005
0ef52a96 1006Execute a coderef in given class and catch exceptions. Errors are available
1007via $c->error.
fbcc39ad 1008
1009=cut
1010
1011sub execute {
1012 my ( $c, $class, $code ) = @_;
858828dd 1013 $class = $c->component($class) || $class;
fbcc39ad 1014 $c->state(0);
a0eca838 1015
1627551a 1016 if ($c->depth >= $RECURSION) {
1017 my $action = "$code";
1018 $action = "/$action" unless $action =~ /\-\>/;
1019 my $error = qq/Deep recursion detected calling "$action"/;
1020 $c->log->error($error);
1021 $c->error($error);
1022 $c->state(0);
1023 return $c->state;
1024 }
1025
1026
fbcc39ad 1027 if ( $c->debug ) {
02d2619e 1028 my $action = "$code";
fbcc39ad 1029 $action = "/$action" unless $action =~ /\-\>/;
1030 $c->counter->{"$code"}++;
1031
02d2619e 1032 # determine if the call was the result of a forward
9d17368e 1033 # this is done by walking up the call stack and looking for a calling
1034 # sub of Catalyst::forward before the eval
1035 my $callsub = q{};
b710ca30 1036 for my $index ( 1 .. 10 ) {
1037 last
1038 if ( ( caller($index) )[0] eq 'Catalyst'
9d17368e 1039 && ( caller($index) )[3] eq '(eval)' );
b710ca30 1040
1041 if ( ( caller($index) )[3] =~ /forward$/ ) {
1042 $callsub = ( caller($index) )[3];
1043 $action = "-> $action";
9d17368e 1044 last;
1045 }
02d2619e 1046 }
5513038d 1047
22247e54 1048 my $node = Tree::Simple->new(
1049 {
1050 action => $action,
1051 elapsed => undef, # to be filled in later
1052 }
1053 );
5513038d 1054 $node->setUID( "$code" . $c->counter->{"$code"} );
22247e54 1055
5513038d 1056 unless ( ( $code->name =~ /^_.*/ )
1057 && ( !$c->config->{show_internal_actions} ) )
22247e54 1058 {
1059
5513038d 1060 # is this a root-level call or a forwarded call?
1061 if ( $callsub =~ /forward$/ ) {
22247e54 1062
5513038d 1063 # forward, locate the caller
1064 if ( my $parent = $c->stack->[-1] ) {
1065 my $visitor = Tree::Simple::Visitor::FindByUID->new;
22247e54 1066 $visitor->searchForUID(
5513038d 1067 "$parent" . $c->counter->{"$parent"} );
22247e54 1068 $c->{stats}->accept($visitor);
5513038d 1069 if ( my $result = $visitor->getResult ) {
22247e54 1070 $result->addChild($node);
5513038d 1071 }
1072 }
1073 else {
22247e54 1074
5513038d 1075 # forward with no caller may come from a plugin
22247e54 1076 $c->{stats}->addChild($node);
5513038d 1077 }
1078 }
1079 else {
22247e54 1080
5513038d 1081 # root-level call
22247e54 1082 $c->{stats}->addChild($node);
5513038d 1083 }
1084 }
fbcc39ad 1085 }
22247e54 1086
8767c5a3 1087 push( @{ $c->stack }, $code );
245ae014 1088 my $elapsed = 0;
1089 my $start = 0;
1090 $start = [gettimeofday] if $c->debug;
1091 eval { $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 ) };
1092 $elapsed = tv_interval($start) if $c->debug;
1093
1094 if ( $c->debug ) {
1095 unless ( ( $code->name =~ /^_.*/ )
1096 && ( !$c->config->{show_internal_actions} ) )
00e6a2b7 1097 {
22247e54 1098
5513038d 1099 # FindByUID uses an internal die, so we save the existing error
1100 my $error = $@;
22247e54 1101
5513038d 1102 # locate the node in the tree and update the elapsed time
1103 my $visitor = Tree::Simple::Visitor::FindByUID->new;
1104 $visitor->searchForUID( "$code" . $c->counter->{"$code"} );
22247e54 1105 $c->{stats}->accept($visitor);
5513038d 1106 if ( my $result = $visitor->getResult ) {
1107 my $value = $result->getNodeValue;
1108 $value->{elapsed} = sprintf( '%fs', $elapsed );
22247e54 1109 $result->setNodeValue($value);
5513038d 1110 }
22247e54 1111
5513038d 1112 # restore error
1113 $@ = $error || undef;
fbcc39ad 1114 }
245ae014 1115 }
f59def82 1116 my $last = ${ $c->stack }[-1];
8767c5a3 1117 pop( @{ $c->stack } );
fbcc39ad 1118
1119 if ( my $error = $@ ) {
28591cd7 1120 if ( $error eq $DETACH ) { die $DETACH if $c->depth > 1 }
fbcc39ad 1121 else {
1122 unless ( ref $error ) {
1123 chomp $error;
f59def82 1124 my $class = $last->class;
1125 my $name = $last->name;
1126 $error = qq/Caught exception in $class->$name "$error"/;
fbcc39ad 1127 }
fbcc39ad 1128 $c->error($error);
1129 $c->state(0);
1130 }
1131 }
1132 return $c->state;
1133}
1134
b5ecfcf0 1135=head2 $c->finalize
fbcc39ad 1136
e7f1cf73 1137Finalizes the request.
fbcc39ad 1138
1139=cut
1140
1141sub finalize {
1142 my $c = shift;
1143
369c09bc 1144 for my $error ( @{ $c->error } ) {
1145 $c->log->error($error);
1146 }
1147
fbcc39ad 1148 $c->finalize_uploads;
1149
1150 # Error
1151 if ( $#{ $c->error } >= 0 ) {
1152 $c->finalize_error;
1153 }
1154
1155 $c->finalize_headers;
1156
1157 # HEAD request
1158 if ( $c->request->method eq 'HEAD' ) {
1159 $c->response->body('');
1160 }
1161
1162 $c->finalize_body;
1163
1164 return $c->response->status;
1165}
1166
b5ecfcf0 1167=head2 $c->finalize_body
fbcc39ad 1168
e7f1cf73 1169Finalizes body.
fbcc39ad 1170
1171=cut
1172
1173sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1174
b5ecfcf0 1175=head2 $c->finalize_cookies
fbcc39ad 1176
e7f1cf73 1177Finalizes cookies.
fbcc39ad 1178
1179=cut
1180
147821ea 1181sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
fbcc39ad 1182
b5ecfcf0 1183=head2 $c->finalize_error
fbcc39ad 1184
e7f1cf73 1185Finalizes error.
fbcc39ad 1186
1187=cut
1188
1189sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1190
b5ecfcf0 1191=head2 $c->finalize_headers
fbcc39ad 1192
e7f1cf73 1193Finalizes headers.
fbcc39ad 1194
1195=cut
1196
1197sub finalize_headers {
1198 my $c = shift;
1199
1200 # Check if we already finalized headers
1201 return if $c->response->{_finalized_headers};
1202
1203 # Handle redirects
1204 if ( my $location = $c->response->redirect ) {
1205 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
1206 $c->response->header( Location => $location );
1207 }
1208
1209 # Content-Length
1210 if ( $c->response->body && !$c->response->content_length ) {
775878ac 1211
8f62c91a 1212 # get the length from a filehandle
6a4a7002 1213 if ( blessed($c->response->body) && $c->response->body->can('read') ) {
8f62c91a 1214 if ( my $stat = stat $c->response->body ) {
1215 $c->response->content_length( $stat->size );
1216 }
1217 else {
775878ac 1218 $c->log->warn('Serving filehandle without a content-length');
8f62c91a 1219 }
1220 }
1221 else {
775878ac 1222 $c->response->content_length( bytes::length( $c->response->body ) );
8f62c91a 1223 }
fbcc39ad 1224 }
1225
1226 # Errors
1227 if ( $c->response->status =~ /^(1\d\d|[23]04)$/ ) {
1228 $c->response->headers->remove_header("Content-Length");
1229 $c->response->body('');
1230 }
1231
1232 $c->finalize_cookies;
1233
1234 $c->engine->finalize_headers( $c, @_ );
1235
1236 # Done
1237 $c->response->{_finalized_headers} = 1;
1238}
1239
b5ecfcf0 1240=head2 $c->finalize_output
fbcc39ad 1241
1242An alias for finalize_body.
1243
b5ecfcf0 1244=head2 $c->finalize_read
fbcc39ad 1245
e7f1cf73 1246Finalizes the input after reading is complete.
fbcc39ad 1247
1248=cut
1249
1250sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1251
b5ecfcf0 1252=head2 $c->finalize_uploads
fbcc39ad 1253
ae1e6b59 1254Finalizes uploads. Cleans up any temporary files.
fbcc39ad 1255
1256=cut
1257
1258sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1259
b5ecfcf0 1260=head2 $c->get_action( $action, $namespace )
fbcc39ad 1261
e7f1cf73 1262Gets an action in a given namespace.
fbcc39ad 1263
1264=cut
1265
684d10ed 1266sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
fbcc39ad 1267
b5ecfcf0 1268=head2 $c->get_actions( $action, $namespace )
a9dc674c 1269
ae1e6b59 1270Gets all actions of a given name in a namespace and all parent
1271namespaces.
a9dc674c 1272
1273=cut
1274
1275sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1276
f7b672ef 1277=head2 $c->handle_request( $class, @arguments )
fbcc39ad 1278
e7f1cf73 1279Called to handle each HTTP request.
fbcc39ad 1280
1281=cut
1282
1283sub handle_request {
1284 my ( $class, @arguments ) = @_;
1285
1286 # Always expect worst case!
1287 my $status = -1;
1288 eval {
22247e54 1289 my $stats = ( $class->debug ) ? Tree::Simple->new: q{};
fbcc39ad 1290
1291 my $handler = sub {
1292 my $c = $class->prepare(@arguments);
5513038d 1293 $c->{stats} = $stats;
fbcc39ad 1294 $c->dispatch;
1295 return $c->finalize;
1296 };
1297
1298 if ( $class->debug ) {
245ae014 1299 my $start = [gettimeofday];
1300 $status = &$handler;
1301 my $elapsed = tv_interval $start;
fbcc39ad 1302 $elapsed = sprintf '%f', $elapsed;
1303 my $av = sprintf '%.3f',
1304 ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) );
8c113188 1305 my $t = Text::SimpleTable->new( [ 64, 'Action' ], [ 9, 'Time' ] );
22247e54 1306
1307 $stats->traverse(
1308 sub {
1309 my $action = shift;
1310 my $stat = $action->getNodeValue;
1311 $t->row( ( q{ } x $action->getDepth ) . $stat->{action},
1312 $stat->{elapsed} || '??' );
1313 }
1314 );
1315
fbcc39ad 1316 $class->log->info(
1317 "Request took ${elapsed}s ($av/s)\n" . $t->draw );
1318 }
1319 else { $status = &$handler }
1320
1321 };
1322
1323 if ( my $error = $@ ) {
1324 chomp $error;
1325 $class->log->error(qq/Caught exception in engine "$error"/);
1326 }
1327
1328 $COUNT++;
1329 $class->log->_flush() if $class->log->can('_flush');
1330 return $status;
1331}
1332
b5ecfcf0 1333=head2 $c->prepare( @arguments )
fbcc39ad 1334
ae1e6b59 1335Creates a Catalyst context from an engine-specific request (Apache, CGI,
1336etc.).
fbcc39ad 1337
1338=cut
1339
1340sub prepare {
1341 my ( $class, @arguments ) = @_;
1342
3cec521a 1343 $class->context_class( ref $class || $class ) unless $class->context_class;
1344 my $c = $class->context_class->new(
1345 {
1346 counter => {},
28591cd7 1347 stack => [],
3cec521a 1348 request => $class->request_class->new(
1349 {
1350 arguments => [],
1351 body_parameters => {},
1352 cookies => {},
1353 headers => HTTP::Headers->new,
1354 parameters => {},
1355 query_parameters => {},
1356 secure => 0,
1357 snippets => [],
1358 uploads => {}
1359 }
1360 ),
1361 response => $class->response_class->new(
1362 {
1363 body => '',
1364 cookies => {},
1365 headers => HTTP::Headers->new(),
1366 status => 200
1367 }
1368 ),
1369 stash => {},
1370 state => 0
1371 }
1372 );
fbcc39ad 1373
1374 # For on-demand data
1375 $c->request->{_context} = $c;
1376 $c->response->{_context} = $c;
1377 weaken( $c->request->{_context} );
1378 weaken( $c->response->{_context} );
1379
1380 if ( $c->debug ) {
1381 my $secs = time - $START || 1;
1382 my $av = sprintf '%.3f', $COUNT / $secs;
1383 $c->log->debug('**********************************');
1384 $c->log->debug("* Request $COUNT ($av/s) [$$]");
1385 $c->log->debug('**********************************');
1386 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
1387 }
1388
1389 $c->prepare_request(@arguments);
1390 $c->prepare_connection;
1391 $c->prepare_query_parameters;
1392 $c->prepare_headers;
1393 $c->prepare_cookies;
1394 $c->prepare_path;
1395
1396 # On-demand parsing
1397 $c->prepare_body unless $c->config->{parse_on_demand};
1398
fbcc39ad 1399 my $method = $c->req->method || '';
1400 my $path = $c->req->path || '';
1401 my $address = $c->req->address || '';
1402
e3a13771 1403 $c->log->debug(qq/"$method" request for "$path" from "$address"/)
fbcc39ad 1404 if $c->debug;
1405
e3a13771 1406 $c->prepare_action;
1407
fbcc39ad 1408 return $c;
1409}
1410
b5ecfcf0 1411=head2 $c->prepare_action
fbcc39ad 1412
e7f1cf73 1413Prepares action.
fbcc39ad 1414
1415=cut
1416
1417sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1418
b5ecfcf0 1419=head2 $c->prepare_body
fbcc39ad 1420
e7f1cf73 1421Prepares message body.
fbcc39ad 1422
1423=cut
1424
1425sub prepare_body {
1426 my $c = shift;
1427
1428 # Do we run for the first time?
1429 return if defined $c->request->{_body};
1430
1431 # Initialize on-demand data
1432 $c->engine->prepare_body( $c, @_ );
1433 $c->prepare_parameters;
1434 $c->prepare_uploads;
1435
1436 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
8c113188 1437 my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
fbcc39ad 1438 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1439 my $param = $c->req->body_parameters->{$key};
1440 my $value = defined($param) ? $param : '';
8c113188 1441 $t->row( $key,
fbcc39ad 1442 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1443 }
1444 $c->log->debug( "Body Parameters are:\n" . $t->draw );
1445 }
1446}
1447
b5ecfcf0 1448=head2 $c->prepare_body_chunk( $chunk )
4bd82c41 1449
e7f1cf73 1450Prepares a chunk of data before sending it to L<HTTP::Body>.
4bd82c41 1451
1452=cut
1453
4f5ebacd 1454sub prepare_body_chunk {
1455 my $c = shift;
4bd82c41 1456 $c->engine->prepare_body_chunk( $c, @_ );
1457}
1458
b5ecfcf0 1459=head2 $c->prepare_body_parameters
fbcc39ad 1460
e7f1cf73 1461Prepares body parameters.
fbcc39ad 1462
1463=cut
1464
1465sub prepare_body_parameters {
1466 my $c = shift;
1467 $c->engine->prepare_body_parameters( $c, @_ );
1468}
1469
b5ecfcf0 1470=head2 $c->prepare_connection
fbcc39ad 1471
e7f1cf73 1472Prepares connection.
fbcc39ad 1473
1474=cut
1475
1476sub prepare_connection {
1477 my $c = shift;
1478 $c->engine->prepare_connection( $c, @_ );
1479}
1480
b5ecfcf0 1481=head2 $c->prepare_cookies
fbcc39ad 1482
e7f1cf73 1483Prepares cookies.
fbcc39ad 1484
1485=cut
1486
1487sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1488
b5ecfcf0 1489=head2 $c->prepare_headers
fbcc39ad 1490
e7f1cf73 1491Prepares headers.
fbcc39ad 1492
1493=cut
1494
1495sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1496
b5ecfcf0 1497=head2 $c->prepare_parameters
fbcc39ad 1498
e7f1cf73 1499Prepares parameters.
fbcc39ad 1500
1501=cut
1502
1503sub prepare_parameters {
1504 my $c = shift;
1505 $c->prepare_body_parameters;
1506 $c->engine->prepare_parameters( $c, @_ );
1507}
1508
b5ecfcf0 1509=head2 $c->prepare_path
fbcc39ad 1510
e7f1cf73 1511Prepares path and base.
fbcc39ad 1512
1513=cut
1514
1515sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1516
b5ecfcf0 1517=head2 $c->prepare_query_parameters
fbcc39ad 1518
e7f1cf73 1519Prepares query parameters.
fbcc39ad 1520
1521=cut
1522
1523sub prepare_query_parameters {
1524 my $c = shift;
1525
1526 $c->engine->prepare_query_parameters( $c, @_ );
1527
1528 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
8c113188 1529 my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
fbcc39ad 1530 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1531 my $param = $c->req->query_parameters->{$key};
1532 my $value = defined($param) ? $param : '';
8c113188 1533 $t->row( $key,
fbcc39ad 1534 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1535 }
1536 $c->log->debug( "Query Parameters are:\n" . $t->draw );
1537 }
1538}
1539
b5ecfcf0 1540=head2 $c->prepare_read
fbcc39ad 1541
e7f1cf73 1542Prepares the input for reading.
fbcc39ad 1543
1544=cut
1545
1546sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1547
b5ecfcf0 1548=head2 $c->prepare_request
fbcc39ad 1549
e7f1cf73 1550Prepares the engine request.
fbcc39ad 1551
1552=cut
1553
1554sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1555
b5ecfcf0 1556=head2 $c->prepare_uploads
fbcc39ad 1557
e7f1cf73 1558Prepares uploads.
fbcc39ad 1559
1560=cut
1561
1562sub prepare_uploads {
1563 my $c = shift;
1564
1565 $c->engine->prepare_uploads( $c, @_ );
1566
1567 if ( $c->debug && keys %{ $c->request->uploads } ) {
8c113188 1568 my $t = Text::SimpleTable->new(
1569 [ 12, 'Key' ],
1570 [ 28, 'Filename' ],
1571 [ 18, 'Type' ],
1572 [ 9, 'Size' ]
1573 );
fbcc39ad 1574 for my $key ( sort keys %{ $c->request->uploads } ) {
1575 my $upload = $c->request->uploads->{$key};
1576 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
8c113188 1577 $t->row( $key, $u->filename, $u->type, $u->size );
fbcc39ad 1578 }
1579 }
1580 $c->log->debug( "File Uploads are:\n" . $t->draw );
1581 }
1582}
1583
b5ecfcf0 1584=head2 $c->prepare_write
fbcc39ad 1585
e7f1cf73 1586Prepares the output for writing.
fbcc39ad 1587
1588=cut
1589
1590sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1591
b5ecfcf0 1592=head2 $c->request_class
1f9cb7c1 1593
e7f1cf73 1594Returns or sets the request class.
1f9cb7c1 1595
b5ecfcf0 1596=head2 $c->response_class
1f9cb7c1 1597
e7f1cf73 1598Returns or sets the response class.
1f9cb7c1 1599
b5ecfcf0 1600=head2 $c->read( [$maxlength] )
fbcc39ad 1601
ae1e6b59 1602Reads a chunk of data from the request body. This method is designed to
1603be used in a while loop, reading C<$maxlength> bytes on every call.
1604C<$maxlength> defaults to the size of the request if not specified.
fbcc39ad 1605
ae1e6b59 1606You have to set C<MyApp-E<gt>config-E<gt>{parse_on_demand}> to use this
1607directly.
fbcc39ad 1608
1609=cut
1610
1611sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1612
b5ecfcf0 1613=head2 $c->run
fbcc39ad 1614
1615Starts the engine.
1616
1617=cut
1618
1619sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1620
b5ecfcf0 1621=head2 $c->set_action( $action, $code, $namespace, $attrs )
fbcc39ad 1622
e7f1cf73 1623Sets an action in a given namespace.
fbcc39ad 1624
1625=cut
1626
1627sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1628
b5ecfcf0 1629=head2 $c->setup_actions($component)
fbcc39ad 1630
e7f1cf73 1631Sets up actions for a component.
fbcc39ad 1632
1633=cut
1634
1635sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1636
b5ecfcf0 1637=head2 $c->setup_components
fbcc39ad 1638
e7f1cf73 1639Sets up components.
fbcc39ad 1640
1641=cut
1642
1643sub setup_components {
1644 my $class = shift;
1645
1646 my $callback = sub {
1647 my ( $component, $context ) = @_;
1648
31375184 1649 unless ( $component->can('COMPONENT') ) {
fbcc39ad 1650 return $component;
1651 }
1652
76cb6276 1653 my $suffix = Catalyst::Utils::class2classsuffix($component);
fbcc39ad 1654 my $config = $class->config->{$suffix} || {};
1655
1656 my $instance;
1657
22247e54 1658 eval { $instance = $component->COMPONENT( $context, $config ); };
fbcc39ad 1659
1660 if ( my $error = $@ ) {
1661
1662 chomp $error;
1663
1664 Catalyst::Exception->throw( message =>
1665 qq/Couldn't instantiate component "$component", "$error"/ );
1666 }
1667
1668 Catalyst::Exception->throw( message =>
6c5033cb 1669qq/Couldn't instantiate component "$component", "COMPONENT() didn't return a object"/
fbcc39ad 1670 )
1671 unless ref $instance;
1672 return $instance;
1673 };
1674
6f006bd6 1675 eval "package $class;\n" . q!Module::Pluggable::Fast->import(
fbcc39ad 1676 name => '_catalyst_components',
1677 search => [
1678 "$class\::Controller", "$class\::C",
1679 "$class\::Model", "$class\::M",
1680 "$class\::View", "$class\::V"
1681 ],
1682 callback => $callback
1683 );
4289f674 1684 !;
fbcc39ad 1685
1686 if ( my $error = $@ ) {
1687
1688 chomp $error;
1689
1690 Catalyst::Exception->throw(
1691 message => qq/Couldn't load components "$error"/ );
1692 }
1693
1694 for my $component ( $class->_catalyst_components($class) ) {
1695 $class->components->{ ref $component || $component } = $component;
1696 }
1697}
1698
b5ecfcf0 1699=head2 $c->setup_dispatcher
fbcc39ad 1700
ae1e6b59 1701Sets up dispatcher.
1702
fbcc39ad 1703=cut
1704
1705sub setup_dispatcher {
1706 my ( $class, $dispatcher ) = @_;
1707
1708 if ($dispatcher) {
1709 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1710 }
1711
1712 if ( $ENV{CATALYST_DISPATCHER} ) {
1713 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
1714 }
1715
1716 if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
1717 $dispatcher =
1718 'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
1719 }
1720
1721 unless ($dispatcher) {
cb0354c6 1722 $dispatcher = $class->dispatcher_class;
fbcc39ad 1723 }
1724
1725 $dispatcher->require;
1726
1727 if ($@) {
1728 Catalyst::Exception->throw(
1729 message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
1730 }
1731
1732 # dispatcher instance
1733 $class->dispatcher( $dispatcher->new );
1734}
1735
b5ecfcf0 1736=head2 $c->setup_engine
fbcc39ad 1737
ae1e6b59 1738Sets up engine.
1739
fbcc39ad 1740=cut
1741
1742sub setup_engine {
1743 my ( $class, $engine ) = @_;
1744
1745 if ($engine) {
1746 $engine = 'Catalyst::Engine::' . $engine;
1747 }
1748
1749 if ( $ENV{CATALYST_ENGINE} ) {
1750 $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
1751 }
1752
1753 if ( $ENV{ uc($class) . '_ENGINE' } ) {
1754 $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
1755 }
1756
9b0a3e0f 1757 if ( $ENV{MOD_PERL} ) {
fbcc39ad 1758
1759 # create the apache method
1760 {
1761 no strict 'refs';
1762 *{"$class\::apache"} = sub { shift->engine->apache };
1763 }
1764
1765 my ( $software, $version ) =
1766 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
1767
1768 $version =~ s/_//g;
1769 $version =~ s/(\.[^.]+)\./$1/g;
1770
1771 if ( $software eq 'mod_perl' ) {
1772
9b0a3e0f 1773 if ( !$engine ) {
22247e54 1774
9b0a3e0f 1775 if ( $version >= 1.99922 ) {
1776 $engine = 'Catalyst::Engine::Apache2::MP20';
1777 }
22247e54 1778
9b0a3e0f 1779 elsif ( $version >= 1.9901 ) {
1780 $engine = 'Catalyst::Engine::Apache2::MP19';
1781 }
22247e54 1782
9b0a3e0f 1783 elsif ( $version >= 1.24 ) {
1784 $engine = 'Catalyst::Engine::Apache::MP13';
1785 }
22247e54 1786
9b0a3e0f 1787 else {
1788 Catalyst::Exception->throw( message =>
1789 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
1790 }
fbcc39ad 1791
fbcc39ad 1792 }
1793
1794 # install the correct mod_perl handler
1795 if ( $version >= 1.9901 ) {
1796 *handler = sub : method {
1797 shift->handle_request(@_);
1798 };
1799 }
1800 else {
1801 *handler = sub ($$) { shift->handle_request(@_) };
1802 }
1803
1804 }
1805
1806 elsif ( $software eq 'Zeus-Perl' ) {
1807 $engine = 'Catalyst::Engine::Zeus';
1808 }
1809
1810 else {
1811 Catalyst::Exception->throw(
1812 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
1813 }
1814 }
1815
1816 unless ($engine) {
cb0354c6 1817 $engine = $class->engine_class;
fbcc39ad 1818 }
1819
1820 $engine->require;
1821
1822 if ($@) {
1823 Catalyst::Exception->throw( message =>
1824qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
1825 );
1826 }
0e7f5826 1827
d54484bf 1828 # check for old engines that are no longer compatible
1829 my $old_engine;
0e7f5826 1830 if ( $engine->isa('Catalyst::Engine::Apache')
1831 && !Catalyst::Engine::Apache->VERSION )
d54484bf 1832 {
1833 $old_engine = 1;
1834 }
0e7f5826 1835
d54484bf 1836 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
0e7f5826 1837 && Catalyst::Engine::Server->VERSION le '0.02' )
d54484bf 1838 {
1839 $old_engine = 1;
1840 }
0e7f5826 1841
1842 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
1843 && $engine->VERSION eq '0.01' )
d54484bf 1844 {
1845 $old_engine = 1;
1846 }
0e7f5826 1847
1848 elsif ($engine->isa('Catalyst::Engine::Zeus')
1849 && $engine->VERSION eq '0.01' )
d54484bf 1850 {
1851 $old_engine = 1;
1852 }
fbcc39ad 1853
d54484bf 1854 if ($old_engine) {
1855 Catalyst::Exception->throw( message =>
0e7f5826 1856 qq/Engine "$engine" is not supported by this version of Catalyst/
d54484bf 1857 );
1858 }
0e7f5826 1859
fbcc39ad 1860 # engine instance
1861 $class->engine( $engine->new );
1862}
1863
b5ecfcf0 1864=head2 $c->setup_home
fbcc39ad 1865
ae1e6b59 1866Sets up the home directory.
1867
fbcc39ad 1868=cut
1869
1870sub setup_home {
1871 my ( $class, $home ) = @_;
1872
1873 if ( $ENV{CATALYST_HOME} ) {
1874 $home = $ENV{CATALYST_HOME};
1875 }
1876
1877 if ( $ENV{ uc($class) . '_HOME' } ) {
1878 $home = $ENV{ uc($class) . '_HOME' };
1879 }
1880
1881 unless ($home) {
1882 $home = Catalyst::Utils::home($class);
1883 }
1884
1885 if ($home) {
1886 $class->config->{home} ||= $home;
a738ab68 1887 $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
fbcc39ad 1888 }
1889}
1890
b5ecfcf0 1891=head2 $c->setup_log
fbcc39ad 1892
ae1e6b59 1893Sets up log.
1894
fbcc39ad 1895=cut
1896
1897sub setup_log {
1898 my ( $class, $debug ) = @_;
1899
1900 unless ( $class->log ) {
1901 $class->log( Catalyst::Log->new );
1902 }
af3ff00e 1903
71f074a9 1904 my $app_flag = Catalyst::Utils::class2env($class) . '_DEBUG';
71f074a9 1905
af3ff00e 1906 if (
1907 ( defined( $ENV{CATALYST_DEBUG} ) || defined( $ENV{$app_flag} ) )
1908 ? ( $ENV{CATALYST_DEBUG} || $ENV{$app_flag} )
1909 : $debug
1910 )
1911 {
fbcc39ad 1912 no strict 'refs';
1913 *{"$class\::debug"} = sub { 1 };
1914 $class->log->debug('Debug messages enabled');
1915 }
1916}
1917
b5ecfcf0 1918=head2 $c->setup_plugins
fbcc39ad 1919
ae1e6b59 1920Sets up plugins.
1921
fbcc39ad 1922=cut
1923
836e1134 1924=head2 $c->registered_plugins
1925
1926Returns a sorted list of the plugins which have either been stated in the
1927import list or which have been added via C<< MyApp->plugin(@args); >>.
1928
1929If passed a given plugin name, it will report a boolean value indicating
1930whether or not that plugin is loaded. A fully qualified name is required if
1931the plugin name does not begin with C<Catalyst::Plugin::>.
1932
1933 if ($c->registered_plugins('Some::Plugin')) {
1934 ...
1935 }
1936
1937=cut
fbcc39ad 1938
836e1134 1939{
97b58e17 1940
1941 sub registered_plugins {
836e1134 1942 my $proto = shift;
d0d4d785 1943 return sort keys %{$proto->_plugins} unless @_;
836e1134 1944 my $plugin = shift;
d0d4d785 1945 return 1 if exists $proto->_plugins->{$plugin};
1946 return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
836e1134 1947 }
fbcc39ad 1948
836e1134 1949 sub _register_plugin {
1950 my ( $proto, $plugin, $instant ) = @_;
1951 my $class = ref $proto || $proto;
fbcc39ad 1952
1953 $plugin->require;
1954
836e1134 1955 if ( my $error = $@ ) {
1956 my $type = $instant ? "instant " : '';
fbcc39ad 1957 Catalyst::Exception->throw(
836e1134 1958 message => qq/Couldn't load ${type}plugin "$plugin", $error/ );
fbcc39ad 1959 }
1960
d0d4d785 1961 $proto->_plugins->{$plugin} = 1;
836e1134 1962 unless ($instant) {
fbcc39ad 1963 no strict 'refs';
1964 unshift @{"$class\::ISA"}, $plugin;
1965 }
836e1134 1966 return $class;
1967 }
1968
1969 sub setup_plugins {
1970 my ( $class, $plugins ) = @_;
1971
d0d4d785 1972 $class->_plugins( {} ) unless $class->_plugins;
836e1134 1973 $plugins ||= [];
1974 for my $plugin ( reverse @$plugins ) {
1975
1976 unless ( $plugin =~ s/\A\+// ) {
1977 $plugin = "Catalyst::Plugin::$plugin";
1978 }
1979
1980 $class->_register_plugin($plugin);
1981 }
fbcc39ad 1982 }
1983}
1984
b5ecfcf0 1985=head2 $c->stack
8767c5a3 1986
f7b672ef 1987Returns an arrayref of the internal execution stack (actions that are currently
1988executing).
8767c5a3 1989
b5ecfcf0 1990=head2 $c->write( $data )
fbcc39ad 1991
ae1e6b59 1992Writes $data to the output stream. When using this method directly, you
1993will need to manually set the C<Content-Length> header to the length of
1994your output data, if known.
fbcc39ad 1995
1996=cut
1997
4f5ebacd 1998sub write {
1999 my $c = shift;
2000
2001 # Finalize headers if someone manually writes output
2002 $c->finalize_headers;
2003
2004 return $c->engine->write( $c, @_ );
2005}
fbcc39ad 2006
b5ecfcf0 2007=head2 version
bf88a181 2008
ae1e6b59 2009Returns the Catalyst version number. Mostly useful for "powered by"
2010messages in template systems.
bf88a181 2011
2012=cut
2013
2014sub version { return $Catalyst::VERSION }
2015
b0bb11ec 2016=head1 INTERNAL ACTIONS
2017
ae1e6b59 2018Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2019C<_ACTION>, and C<_END>. These are by default not shown in the private
3e705254 2020action table, but you can make them visible with a config parameter.
b0bb11ec 2021
2022 MyApp->config->{show_internal_actions} = 1;
2023
d2ee9760 2024=head1 CASE SENSITIVITY
2025
3e705254 2026By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
ae1e6b59 2027mapped to C</foo/bar>. You can activate case sensitivity with a config
3e705254 2028parameter.
d2ee9760 2029
2030 MyApp->config->{case_sensitive} = 1;
2031
3e705254 2032This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
fbcc39ad 2033
2034=head1 ON-DEMAND PARSER
2035
2036The request body is usually parsed at the beginning of a request,
3e705254 2037but if you want to handle input yourself or speed things up a bit,
fbcc39ad 2038you can enable on-demand parsing with a config parameter.
2039
2040 MyApp->config->{parse_on_demand} = 1;
2041
2042=head1 PROXY SUPPORT
2043
ae1e6b59 2044Many production servers operate using the common double-server approach,
2045with a lightweight frontend web server passing requests to a larger
2046backend server. An application running on the backend server must deal
2047with two problems: the remote user always appears to be C<127.0.0.1> and
2048the server's hostname will appear to be C<localhost> regardless of the
2049virtual host that the user connected through.
fbcc39ad 2050
ae1e6b59 2051Catalyst will automatically detect this situation when you are running
2052the frontend and backend servers on the same machine. The following
2053changes are made to the request.
fbcc39ad 2054
ae1e6b59 2055 $c->req->address is set to the user's real IP address, as read from
2056 the HTTP X-Forwarded-For header.
fbcc39ad 2057
ae1e6b59 2058 The host value for $c->req->base and $c->req->uri is set to the real
2059 host, as read from the HTTP X-Forwarded-Host header.
fbcc39ad 2060
3e705254 2061Obviously, your web server must support these headers for this to work.
fbcc39ad 2062
ae1e6b59 2063In a more complex server farm environment where you may have your
2064frontend proxy server(s) on different machines, you will need to set a
2065configuration option to tell Catalyst to read the proxied data from the
2066headers.
fbcc39ad 2067
2068 MyApp->config->{using_frontend_proxy} = 1;
2069
2070If you do not wish to use the proxy support at all, you may set:
d1a31ac6 2071
fbcc39ad 2072 MyApp->config->{ignore_frontend_proxy} = 1;
2073
2074=head1 THREAD SAFETY
2075
2076Catalyst has been tested under Apache 2's threading mpm_worker, mpm_winnt,
3e705254 2077and the standalone forking HTTP server on Windows. We believe the Catalyst
fbcc39ad 2078core to be thread-safe.
2079
2080If you plan to operate in a threaded environment, remember that all other
3e705254 2081modules you are using must also be thread-safe. Some modules, most notably
2082L<DBD::SQLite>, are not thread-safe.
d1a31ac6 2083
3cb1db8c 2084=head1 SUPPORT
2085
2086IRC:
2087
2088 Join #catalyst on irc.perl.org.
2089
3e705254 2090Mailing Lists:
3cb1db8c 2091
2092 http://lists.rawmode.org/mailman/listinfo/catalyst
2093 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1985c30b 2094
432d507d 2095Web:
2096
2097 http://catalyst.perl.org
2098
0ef52a96 2099Wiki:
2100
2101 http://dev.catalyst.perl.org
2102
fc7ec1d9 2103=head1 SEE ALSO
2104
829a28ca 2105=head2 L<Task::Catalyst> - All you need to start with Catalyst
2106
b5ecfcf0 2107=head2 L<Catalyst::Manual> - The Catalyst Manual
e7f1cf73 2108
b5ecfcf0 2109=head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
61b1e958 2110
b5ecfcf0 2111=head2 L<Catalyst::Engine> - Core engine
61b1e958 2112
b5ecfcf0 2113=head2 L<Catalyst::Log> - Log class.
61b1e958 2114
b5ecfcf0 2115=head2 L<Catalyst::Request> - Request object
61b1e958 2116
b5ecfcf0 2117=head2 L<Catalyst::Response> - Response object
61b1e958 2118
b5ecfcf0 2119=head2 L<Catalyst::Test> - The test suite.
fc7ec1d9 2120
15f0b5b7 2121=head1 CREDITS
fc7ec1d9 2122
15f0b5b7 2123Andy Grundman
2124
fbcc39ad 2125Andy Wardley
2126
33108eaf 2127Andreas Marienborg
2128
f4a57de4 2129Andrew Bramble
2130
15f0b5b7 2131Andrew Ford
2132
2133Andrew Ruthven
2134
fbcc39ad 2135Arthur Bergman
2136
15f0b5b7 2137Autrijus Tang
2138
0cf56dbc 2139Brian Cassidy
2140
6aaa1c60 2141Carl Franks
2142
15f0b5b7 2143Christian Hansen
2144
2145Christopher Hicks
2146
2147Dan Sully
2148
2149Danijel Milicevic
2150
0ef52a96 2151David Kamholz
2152
15f0b5b7 2153David Naughton
2154
61bef238 2155Drew Taylor
2156
15f0b5b7 2157Gary Ashton Jones
2158
2159Geoff Richards
2160
2161Jesse Sheidlower
2162
fbcc39ad 2163Jesse Vincent
2164
15f0b5b7 2165Jody Belka
2166
2167Johan Lindstrom
2168
2169Juan Camacho
2170
2171Leon Brocard
2172
2173Marcus Ramberg
2174
2175Matt S Trout
2176
71c3bcc3 2177Robert Sedlacek
2178
a727119f 2179Sam Vilain
2180
1cf1c56a 2181Sascha Kiefer
2182
15f0b5b7 2183Tatsuhiko Miyagawa
fc7ec1d9 2184
51f0308d 2185Ulf Edvinsson
2186
bdcb95ef 2187Yuval Kogman
2188
51f0308d 2189=head1 AUTHOR
2190
2191Sebastian Riedel, C<sri@oook.de>
2192
fc7ec1d9 2193=head1 LICENSE
2194
9ce5ab63 2195This library is free software, you can redistribute it and/or modify it under
41ca9ba7 2196the same terms as Perl itself.
fc7ec1d9 2197
2198=cut
2199
22001;