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