X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FEngine.pm;h=98a5f924d6c6f002e0a4366f61a20bfb431cc5c9;hb=49490aabb7ab968b286f283d03c1816954c92e1f;hp=bff8fef21c1a1bd5c2ee1b65ed806e3b89d9e233;hpb=98dcf4391e13db6fda023d937e563d25ea764f5c;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Engine.pm b/lib/Catalyst/Engine.pm index bff8fef..98a5f92 100644 --- a/lib/Catalyst/Engine.pm +++ b/lib/Catalyst/Engine.pm @@ -3,6 +3,7 @@ package Catalyst::Engine; use strict; use base qw/Class::Data::Inheritable Class::Accessor::Fast/; use UNIVERSAL::require; +use CGI::Cookie; use Data::Dumper; use HTML::Entities; use HTTP::Headers; @@ -115,6 +116,40 @@ sub error { return $c->{error}; } +=item $c->execute($class, $coderef) + +Execute a coderef in given class and catch exceptions. +Errors are available via $c->error. + +=cut + +sub execute { + my ( $c, $class, $code ) = @_; + $class = $c->comp($class) || $class; + $c->state(0); + eval { + if ( $c->debug ) + { + my $action = $c->actions->{reverse}->{"$code"}; + $action = "/$action" unless $action =~ /\-\>/; + my ( $elapsed, @state ) = + $c->benchmark( $code, $class, $c, @{ $c->req->args } ); + push @{ $c->{stats} }, + _prettify( $action, sprintf( '%fs', $elapsed ), '' ); + $c->state(@state); + } + else { $c->state( &$code( $class, $c, @{ $c->req->args } ) ) } + }; + if ( my $error = $@ ) { + chomp $error; + $error = qq/Caught exception "$error"/; + $c->log->error($error); + $c->error($error) if $c->debug; + $c->state(0); + } + return $c->state; +} + =item $c->finalize Finalize request. @@ -124,24 +159,76 @@ Finalize request. sub finalize { my $c = shift; - if ( my $location = $c->res->redirect ) { + $c->finalize_cookies; + + if ( my $location = $c->response->redirect ) { $c->log->debug(qq/Redirecting to "$location"/) if $c->debug; - $c->res->headers->header( Location => $location ); - $c->res->status(302); - } - - if ( !$c->res->output || $#{ $c->error } >= 0 ) { - $c->res->headers->content_type('text/html'); - my $name = $c->config->{name} || 'Catalyst Application'; - my ( $title, $error, $infos ); - if ( $c->debug ) { - $error = join '
', @{ $c->error }; - $error ||= 'No output'; - $title = $name = "$name on Catalyst $Catalyst::VERSION"; - my $req = encode_entities Dumper $c->req; - my $res = encode_entities Dumper $c->res; - my $stash = encode_entities Dumper $c->stash; - $infos = <<""; + $c->response->header( Location => $location ); + $c->response->status(302); + } + + if ( $#{ $c->error } >= 0 ) { + $c->finalize_error; + } + + if ( !$c->response->output && $c->response->status !~ /^(1|3)\d\d)$/ ) { + $c->finalize_error; + } + + if ( $c->response->output ) { + use bytes; # play safe with a utf8 aware perl + $c->response->content_length( length $c->response->output ); + } + + my $status = $c->finalize_headers; + $c->finalize_output; + return $status; +} + +=item $c->finalize_cookies + +Finalize cookies. + +=cut + +sub finalize_cookies { + my $c = shift; + + while ( my ( $name, $cookie ) = each %{ $c->response->cookies } ) { + my $cookie = CGI::Cookie->new( + -name => $name, + -value => $cookie->{value}, + -expires => $cookie->{expires}, + -domain => $cookie->{domain}, + -path => $cookie->{path}, + -secure => $cookie->{secure} || 0 + ); + + $c->res->headers->push_header( 'Set-Cookie' => $cookie->as_string ); + } +} + +=item $c->finalize_error + +Finalize error. + +=cut + +sub finalize_error { + my $c = shift; + + $c->res->headers->content_type('text/html'); + my $name = $c->config->{name} || 'Catalyst Application'; + + my ( $title, $error, $infos ); + if ( $c->debug ) { + $error = join '
', @{ $c->error }; + $error ||= 'No output'; + $title = $name = "$name on Catalyst $Catalyst::VERSION"; + my $req = encode_entities Dumper $c->req; + my $res = encode_entities Dumper $c->res; + my $stash = encode_entities Dumper $c->stash; + $infos = <<"";
Request
$req
@@ -150,11 +237,11 @@ sub finalize { Stash
$stash
- } - else { - $title = $name; - $error = ''; - $infos = <<""; + } + else { + $title = $name; + $error = ''; + $infos = <<"";
 (en) Please come back later
 (de) Bitte versuchen sie es spaeter nocheinmal
@@ -166,67 +253,62 @@ sub finalize {
 (it) Ritornato prego piĆ¹ successivamente
 
- $name = ''; - } - $c->res->{output} = <<""; + $name = ''; + } + $c->res->output( <<"" ); - - $title - - - -
-
$error
-
$infos
-
$name
-
- + + $title + + + +
+
$error
+
$infos
+
$name
+
+ - } - $c->res->headers->content_length( length $c->res->output ); - my $status = $c->finalize_headers; - $c->finalize_output; - return $status; } =item $c->finalize_headers @@ -349,14 +431,16 @@ Handles the request. =cut -sub handler ($$) { - my ( $class, $r ) = @_; +sub handler { + my ( $class, $engine ) = @_; # Always expect worst case! my $status = -1; eval { + my @stats = (); my $handler = sub { - my $c = $class->prepare($r); + my $c = $class->prepare($engine); + $c->{stats} = \@stats; my $action = $c->req->action; my $namespace = ''; $namespace = ( join( '/', @{ $c->req->args } ) || '/' ) @@ -398,7 +482,7 @@ sub handler ($$) { ( $elapsed, $status ) = $class->benchmark($handler); $elapsed = sprintf '%f', $elapsed; my $av = sprintf '%.3f', 1 / $elapsed; - $class->log->info( "Request took $elapsed" . "s ($av/s)" ); + $class->log->info( "Request took $elapsed" . "s ($av/s)", @stats ); } else { $status = &$handler } }; @@ -462,9 +546,9 @@ sub prepare { my @params; for my $key ( keys %{ $c->req->params } ) { my $value = $c->req->params->{$key} || ''; - push @params, "$key=$value"; + push @params, " $key=$value"; } - $c->log->debug( 'Parameters are "' . join( ' ', @params ) . '"' ); + $c->log->debug( 'Parameters are', @params ); } $c->prepare_uploads; return $c; @@ -528,7 +612,13 @@ Prepare cookies. =cut -sub prepare_cookies { } +sub prepare_cookies { + my $c = shift; + + if ( my $header = $c->request->header('Cookie') ) { + $c->req->cookies( { CGI::Cookie->parse($header) } ); + } +} =item $c->prepare_headers @@ -570,39 +660,6 @@ Prepare uploads. sub prepare_uploads { } -=item $c->execute($class, $coderef) - -Execute a coderef in given class and catch exceptions. -Errors are available via $c->error. - -=cut - -sub execute { - my ( $c, $class, $code ) = @_; - $class = $c->comp($class) || $class; - $c->state(0); - eval { - if ( $c->debug ) - { - my $action = $c->actions->{reverse}->{"$code"} || "$code"; - my ( $elapsed, @state ) = - $c->benchmark( $code, $class, $c, @{ $c->req->args } ); - $c->log->info( sprintf qq/Processing "$action" took %fs/, $elapsed ) - if $c->debug; - $c->state(@state); - } - else { $c->state( &$code( $class, $c, @{ $c->req->args } ) ) } - }; - if ( my $error = $@ ) { - chomp $error; - $error = qq/Caught exception "$error"/; - $c->log->error($error); - $c->error($error) if $c->debug; - $c->state(0); - } - return $c->state; -} - =item $c->run Starts the engine. @@ -666,8 +723,6 @@ sub set_action { my $uid = $parent->getUID; $c->actions->{private}->{$uid}->{$method} = [ $namespace, $code ]; my $forward = $prefix ? "$prefix/$method" : $method; - $c->log->debug(qq|Private "/$forward" is "$namespace->$method"|) - if $c->debug; if ( $flags{path} ) { $flags{path} =~ s/^\w+//; @@ -682,7 +737,7 @@ sub set_action { if ( $flags{regex} =~ /^"(.*)"$/ ) { $flags{regex} = $1 } } - my $reverse = $prefix ? "$method ($prefix)" : $method; + my $reverse = $prefix ? "$prefix/$method" : $method; if ( $flags{local} || $flags{global} || $flags{path} ) { my $path = $flags{path} || $method; @@ -694,12 +749,10 @@ sub set_action { $absolute = 1 if $flags{global}; my $name = $absolute ? $path : "$prefix/$path"; $c->actions->{plain}->{$name} = [ $namespace, $code ]; - $c->log->debug(qq|Public "/$name" is "/$forward"|) if $c->debug; } if ( my $regex = $flags{regex} ) { push @{ $c->actions->{compiled} }, [ $regex, qr#$regex# ]; $c->actions->{regex}->{$regex} = [ $namespace, $code ]; - $c->log->debug(qq|Public "$regex" is "/$forward"|) if $c->debug; } $c->actions->{reverse}->{"$code"} = $reverse; @@ -736,17 +789,16 @@ sub setup_actions { my $name = ''; no strict 'refs'; my @cache = ( $comp, @{"$comp\::ISA"} ); - my @namespaces; - my %seen; + my %namespaces; while ( my $namespace = shift @cache ) { - push @namespaces, $namespace; + $namespaces{$namespace}++; for my $isa ( @{"$comp\::ISA"} ) { - next if $seen{$isa}; + next if $namespaces{$isa}; push @cache, $isa; - $seen{$isa}++; + $namespaces{$isa}++; } } - for my $namespace (@namespaces) { + for my $namespace ( keys %namespaces ) { for my $sym ( values %{ $namespace . '::' } ) { if ( *{$sym}{CODE} && *{$sym}{CODE} == $code ) { $name = *{$sym}{NAME}; @@ -790,10 +842,38 @@ sub setup_components { $self->components->{ ref $comp } = $comp; $self->setup_actions($comp); } - $self->log->debug( 'Initialized components "' - . join( ' ', keys %{ $self->components } ) - . '"' ) - if $self->debug; + my @comps; + push @comps, " $_" for keys %{ $self->components }; + $self->log->debug( 'Loaded components', @comps ) + if ( @comps && $self->debug ); + my $actions = $self->actions; + my @messages = ('Loaded private actions'); + my $walker = sub { + my ( $walker, $parent, $messages, $prefix ) = @_; + $prefix .= $parent->getNodeValue || ''; + $prefix .= '/' unless $prefix =~ /\/$/; + my $uid = $parent->getUID; + for my $action ( keys %{ $actions->{private}->{$uid} } ) { + my ( $class, $code ) = @{ $actions->{private}->{$uid}->{$action} }; + push @$messages, _prettify( "$prefix$action", $class, $code ); + } + $walker->( $walker, $_, $messages, $prefix ) + for $parent->getAllChildren; + }; + $walker->( $walker, $self->tree, \@messages, '' ); + $self->log->debug(@messages) if ( $#messages && $self->debug ); + @messages = ('Loaded plain actions'); + for my $plain ( sort keys %{ $actions->{plain} } ) { + my ( $class, $code ) = @{ $actions->{plain}->{$plain} }; + push @messages, _prettify( "/$plain", $class, $code ); + } + $self->log->debug(@messages) if ( $#messages && $self->debug ); + @messages = ('Loaded regex actions'); + for my $regex ( sort keys %{ $actions->{regex} } ) { + my ( $class, $code ) = @{ $actions->{regex}->{$regex} }; + push @messages, _prettify( $regex, $class, $code ); + } + $self->log->debug(@messages) if ( $#messages && $self->debug ); } =item $c->stash @@ -833,6 +913,16 @@ sub _class2prefix { return $prefix; } +sub _prettify { + my ( $val1, $val2, $val3 ) = @_; + formline +' @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>>>>>> ', + $val1, $val2, $val3; + my $formatted = $^A; + $^A = ''; + return $formatted; +} + =back =head1 AUTHOR