Plasp
view release on metacpan or search on metacpan
lib/Plasp/App.pm view on Meta::CPAN
}
# Parse and compile the ASP code
$compiled = $_asp->compile_file(
path( $_asp->DocumentRoot, $req->path_info )->stringify
);
1;
} catch {
if ( $_asp && blessed( $_ ) ) {
# Handle not found exception
if ( $_->isa( 'Plasp::Exception::NotFound' ) ) {
$error_response = _not_found_response();
} else {
# Handle code or compilation exception by loggin it
$_asp->error( sprintf( "Encountered %s error: %s",
$_->isa( 'Plasp::Exception::Code' )
? 'application code'
: 'unknown compilation',
$_
) ) unless $_asp->has_errors;
$error_response = _error_response( undef, '500_error' );
}
} else {
# Plasp error due to error in Plasp code. $asp and $Response is
# not reliable. This implies a bug in Plasp.
Plasp->log->fatal( "Plasp error: $_" );
$error_response = _error_response(
undef,
'plasp_error',
$class->config->{Debug} ? "<pre>$_</pre>" : ''
);
}
# Ensure return value is false to signify failure
return;
};
unless ( $success ) {
$_asp->cleanup;
return $error_response;
}
# Define a callback once server is ready to write data to client. The
# callback is called and passed subroutine called a responder.
my $callback = sub {
# Setup a hash here holding references to various objects at this
# scope, so that the closures for calling the responder will be
# able to write to this scope.
my %refs = ( responder => shift );
# If a responder is passed in, that means streaming response is
# supported so pass a closure to write out headers and body
if ( $refs{responder} ) {
$_asp->Response->_headers_writer(
sub { $refs{writer} = $refs{responder}->( \@_ ) }
);
$_asp->Response->_content_writer(
sub { $refs{writer}->write( @_ ) }
);
}
# Keep the stacktrace available for exception processing
$success = try {
local $SIG{__DIE__} = sub {
$_asp->_stack_trace( Devel::StackTrace->new(
frame_filter => $stack_trace_ignore,
) );
};
local $SIG{__WARN__} = sub {
$_asp->log->warn(
$_[0],
stack_trace => Devel::StackTrace->new(
frame_filter => $stack_trace_ignore,
)->as_string
);
};
# Execute the code, render the ASP page
$_asp->GlobalASA->Script_OnStart;
$_asp->execute( $compiled->{code} );
1;
} catch {
if ( blessed( $_ ) ) {
# A Redirect or End might come here (without already being
# caught). In that case, just ignore it and continue
# processing.
if ( $_->isa( 'Plasp::Exception::Code' ) ) {
# If an application error occured, log the error along
# with the stack trace that was captured
$_asp->error(
"Encountered application error: $_",
stack_trace => $_->stack_trace,
);
}
# Plasp application reported errors
$error_response = _error_response(
$refs{responder},
'500_error'
) if $_asp->has_errors;
} else {
# Plasp did not throw exception, implying a bug in Plasp
# itself
$_asp->log->fatal( "Plasp error: $_" );
$error_response = _error_response(
$refs{responder},
'plasp_error',
$_asp->config->{Debug} ? "<pre>$_</pre>" : ''
);
}
return;
} finally {
if ( $_asp ) {
# Do one final $Response->Flush
my $resp = $_asp->Response;
$resp->Flush;
if ( $refs{writer} ) {
# Close the writer so as to conclude the response to the
# client
$refs{writer}->close;
} else {
# If not using streaming response, then save response
# for reference later
$refs{status} = $resp->Status;
$refs{headers} = $resp->Headers;
$refs{body} = [ $resp->Output ];
}
# Ensure destruction!
$_asp->cleanup;
}
};
# If a responder was passed in, then no need to return anything,
# but otherwise need to return the PSGI three-element array
unless ( $refs{responder} ) {
return $success
? \( @refs{qw(status headers body)} )
: $error_response;
}
};
if ( $_asp->req->env->{'psgi.streaming'} ) {
# Return the callback subroutine if streaming is supported
return $callback;
} else {
# Manually call the callback to get response
return $callback->();
}
}
}
# Construct error response
sub _error_response {
my $responder = shift;
my $error_type = shift;
my $body = sprintf( $_error_docs{$error_type}, @_ );
if ( $_asp ) {
$_asp->Response->Status( 500 );
$_asp->Response->ContentType( 'text/html' );
if ( $_asp->Error500Path ) {
my $compiled = $_asp->compile_file(
path( $_asp->DocumentRoot, $_asp->Error500Path )->stringify
);
$_asp->execute( $compiled->{code} );
$body = $_asp->Response->Output;
} else {
$_asp->Response->Output( $body );
}
}
# If a responder is defined, then the responder would already have written
# out the error Response, but otherwise return the three-element array
unless ( $responder ) {
return [ 500, [ 'Content-Type' => 'text/html' ], [$body] ];
}
}
# Construct not found response
sub _not_found_response {
my $body;
if ( $_asp && $_asp->Error404Path ) {
my $compiled = $_asp->compile_file(
path( $_asp->DocumentRoot, $_asp->Error404Path )->stringify
);
$_asp->execute( $compiled->{code} );
$body = $_asp->Response->Output;
} else {
$body = $_error_docs{'404_not_found'};
}
return [ 404, [ 'Content-Type' => 'text/html' ], [$body] ];
}
1;
( run in 1.286 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )