X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FEngine.pm;h=fd510b37fec508b0a82e8c911fdcd7035b68a997;hb=b4ca0ee8572ea5c33295686b7f786ab5ff43a2b7;hp=f74fa734ccb5fb8d95787a50394ad09f5db4e2a7;hpb=b18987fe030c042bea8c545094098a6157e93f11;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Engine.pm b/lib/Catalyst/Engine.pm index f74fa73..fd510b3 100644 --- a/lib/Catalyst/Engine.pm +++ b/lib/Catalyst/Engine.pm @@ -20,7 +20,7 @@ require Module::Pluggable::Fast; $Data::Dumper::Terse = 1; __PACKAGE__->mk_classdata('components'); -__PACKAGE__->mk_accessors(qw/request response state/); +__PACKAGE__->mk_accessors(qw/counter request response state/); *comp = \&component; *req = \&request; @@ -30,8 +30,9 @@ __PACKAGE__->mk_accessors(qw/request response state/); *finalize_output = \&finalize_body; # For statistics -our $COUNT = 1; -our $START = time; +our $COUNT = 1; +our $START = time; +our $RECURSION = 1000; =head1 NAME @@ -82,7 +83,7 @@ Regex search for a component. sub component { my $c = shift; - if ( @_ ) { + if (@_) { my $name = shift; @@ -100,6 +101,11 @@ sub component { return sort keys %{ $c->components }; } +=item $c->counter + +Returns a hashref containing coderefs and execution counts. +(Needed for deep recursion detection) + =item $c->error =item $c->error($error, ...) @@ -136,12 +142,26 @@ sub execute { $c->state(0); my $callsub = ( caller(1) )[3]; + my $action = ''; + if ( $c->debug ) { + $action = $c->actions->{reverse}->{"$code"}; + $action = "/$action" unless $action =~ /\-\>/; + $c->counter->{"$code"}++; + + if ( $c->counter->{"$code"} > $RECURSION ) { + my $error = qq/Deep recursion detected in "$action"/; + $c->log->error($error); + $c->error($error); + $c->state(0); + return $c->state; + } + + $action = "-> $action" if $callsub =~ /forward$/; + } + eval { if ( $c->debug ) { - my $action = $c->actions->{reverse}->{"$code"}; - $action = "/$action" unless $action =~ /\-\>/; - $action = "-> $action" if $callsub =~ /forward$/; my ( $elapsed, @state ) = $c->benchmark( $code, $class, $c, @{ $c->req->args } ); push @{ $c->{stats} }, [ $action, sprintf( '%fs', $elapsed ) ]; @@ -199,6 +219,10 @@ sub finalize { return $status; } +=item $c->finalize_output + +, see finalize_body + =item $c->finalize_body Finalize body. @@ -341,14 +365,14 @@ Finalize headers. sub finalize_headers { } -=item $c->handler( $class, $engine ) +=item $c->handler( $class, @arguments ) Handles the request. =cut sub handler { - my ( $class, $engine ) = @_; + my ( $class, @arguments ) = @_; # Always expect worst case! my $status = -1; @@ -356,7 +380,7 @@ sub handler { my @stats = (); my $handler = sub { - my $c = $class->prepare($engine); + my $c = $class->prepare(@arguments); $c->{stats} = \@stats; $c->dispatch; return $c->finalize; @@ -366,7 +390,8 @@ sub handler { my $elapsed; ( $elapsed, $status ) = $class->benchmark($handler); $elapsed = sprintf '%f', $elapsed; - my $av = sprintf '%.3f', ( $elapsed == 0 ? '??' : (1 / $elapsed) ); + my $av = sprintf '%.3f', + ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) ); my $t = Text::ASCIITable->new; $t->setCols( 'Action', 'Time' ); $t->setColWidth( 'Action', 64, 1 ); @@ -389,7 +414,7 @@ sub handler { return $status; } -=item $c->prepare($engine) +=item $c->prepare(@arguments) Turns the engine-specific request( Apache, CGI ... ) into a Catalyst context . @@ -397,9 +422,10 @@ into a Catalyst context . =cut sub prepare { - my ( $class, $engine ) = @_; + my ( $class, @arguments ) = @_; my $c = bless { + counter => {}, request => Catalyst::Request->new( { arguments => [], @@ -432,7 +458,7 @@ sub prepare { $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION ); } - $c->prepare_request($engine); + $c->prepare_request(@arguments); $c->prepare_connection; $c->prepare_headers; $c->prepare_cookies; @@ -441,10 +467,9 @@ sub prepare { my $method = $c->req->method || ''; my $path = $c->req->path || ''; - my $hostname = $c->req->hostname || ''; my $address = $c->req->address || ''; - $c->log->debug(qq/"$method" request for "$path" from $hostname($address)/) + $c->log->debug(qq/"$method" request for "$path" from $address/) if $c->debug; if ( $c->request->method eq 'POST' and $c->request->content_length ) { @@ -601,35 +626,6 @@ Prepare uploads. sub prepare_uploads { } -=item $c->retrieve_components - -Retrieve Components. - -=cut - -sub retrieve_components { - my $self = shift; - - my $class = ref $self || $self; - eval <<""; - package $class; - import Module::Pluggable::Fast - name => '_components', - search => [ - '$class\::Controller', '$class\::C', - '$class\::Model', '$class\::M', - '$class\::View', '$class\::V' - ], - require => 1; - - if ( my $error = $@ ) { - chomp $error; - die qq/Couldn't load components "$error"/; - } - - return $self->_components; -} - =item $c->run Starts the engine. @@ -679,7 +675,7 @@ Setup components. sub setup_components { my $self = shift; - + # Components my $class = ref $self || $self; eval <<""; @@ -729,7 +725,7 @@ Returns a hashref containing all your data. sub stash { my $self = shift; - if ( @_ ) { + if (@_) { my $stash = @_ > 1 ? {@_} : $_[0]; while ( my ( $key, $val ) = each %$stash ) { $self->{stash}->{$key} = $val;