Added exception handling
Added error doc mapping Moved more logic into Session middleware Added Credit example to app.psgi Made StackTrace and Debug panel automatically turn on when debug mode enabled Fixed errorHandler
This commit is contained in:
parent
2bac95fa26
commit
716bdaeb86
7 changed files with 114 additions and 145 deletions
5
TODO
5
TODO
|
|
@ -1,5 +1,8 @@
|
|||
TODO
|
||||
* Deprecate WebGUI::Session::HTTP - replace with WebGUI::Request/Response
|
||||
* Delete lib/WebGUI/URL and replace with new Middleware(s)
|
||||
* Investigate moving Cookie handling into middleware
|
||||
* Turn html debug output into a Plack::Middleware::Debug panel
|
||||
|
||||
DONE
|
||||
* $session->request is now a Plack::Request object
|
||||
|
|
@ -7,8 +10,8 @@ DONE
|
|||
* WebGUI::authen API changed
|
||||
* urlHandler API changed - no longer gets server, config
|
||||
* Streaming response body
|
||||
* Delete lib/WebGUI/URL and replace with new Middleware(s)
|
||||
* Mostly decoupled WebGUI from Log4perl
|
||||
* Exception handling and error doc mapping
|
||||
|
||||
NB
|
||||
* Periodically do a big stress-test and check for leaks, mysql overload etc..
|
||||
|
|
|
|||
15
app.psgi
15
app.psgi
|
|
@ -3,17 +3,18 @@ use Plack::Builder;
|
|||
use lib '/data/WebGUI/lib';
|
||||
use WebGUI;
|
||||
|
||||
my $wg = WebGUI->new( root => '/data/WebGUI', site => 'dev.localhost.localdomain.conf' );
|
||||
my $root = '/data/WebGUI';
|
||||
my $wg = WebGUI->new( root => $root, site => 'dev.localhost.localdomain.conf' );
|
||||
|
||||
builder {
|
||||
enable 'Debug', panels => [ qw(Environment Response Timer Memory Session DBITrace PerlConfig Response) ];
|
||||
enable 'Log4perl', category => 'mysite', conf => $wg->config->getWebguiRoot . '/etc/log.conf';
|
||||
|
||||
enable 'Log4perl', category => 'mysite', conf => "$root/etc/log.conf";
|
||||
enable 'Static', root => $root, path => sub { s{^/\*give-credit-where-credit-is-due\*$}{docs/credits.txt} };
|
||||
|
||||
# Open/close the WebGUI::Session at the outer-most onion layer
|
||||
enable '+WebGUI::Middleware::Session', config => $wg->config;
|
||||
|
||||
# Any additional WebGUI Middleware goes here
|
||||
# ..
|
||||
enable '+WebGUI::Middleware::Session',
|
||||
config => $wg->config;#,
|
||||
#error_docs => { 500 => "$root/www/maintenance.html" };
|
||||
|
||||
# Return the app
|
||||
$wg;
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ sub handle {
|
|||
# non-empty output should be used as the response body
|
||||
elsif (defined $output && $output ne "") {
|
||||
# Auto-set the headers
|
||||
$session->http->sendHeader; # TODO: should be renamed setHeader
|
||||
$session->http->sendHeader;
|
||||
|
||||
# Use contentHandler's return value as the output
|
||||
$session->output->print($output);
|
||||
|
|
|
|||
39
lib/WebGUI/Middleware/Debug.pm
Normal file
39
lib/WebGUI/Middleware/Debug.pm
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package WebGUI::Middleware::Debug;
|
||||
use strict;
|
||||
use parent qw(Plack::Middleware);
|
||||
use Plack::Middleware::StackTrace;
|
||||
use Plack::Middleware::Debug;
|
||||
use Plack::Middleware::HttpExceptions;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WebGUI::Middleware::Debug -
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is PSGI middleware for WebGUI that
|
||||
|
||||
=cut
|
||||
|
||||
sub call {
|
||||
my ( $self, $env ) = @_;
|
||||
|
||||
my $session = $env->{'webgui.session'} or die 'WebGUI::Session missing';
|
||||
|
||||
my $app = $self->app;
|
||||
|
||||
if ( $session->log->canShowDebug ) {
|
||||
warn 'seeing webgui.debug';
|
||||
$env->{'webgui.debug'} = 1;
|
||||
$app = Plack::Middleware::StackTrace->wrap($app);
|
||||
$app = Plack::Middleware::Debug->wrap( $app,
|
||||
panels => [qw(Environment Response Timer Memory Session DBITrace PerlConfig Response)] );
|
||||
}
|
||||
|
||||
# Turn exceptions into HTTP errors
|
||||
$app = Plack::Middleware::HTTPExceptions->wrap( $app );
|
||||
|
||||
return $app->($env);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -3,8 +3,13 @@ use strict;
|
|||
use parent qw(Plack::Middleware);
|
||||
use WebGUI::Config;
|
||||
use WebGUI::Session;
|
||||
use Try::Tiny;
|
||||
use Plack::Middleware::StackTrace;
|
||||
use Plack::Middleware::Debug;
|
||||
use Plack::Middleware::HTTPExceptions;
|
||||
use Plack::Middleware::ErrorDocument;
|
||||
|
||||
use Plack::Util::Accessor qw( config );
|
||||
use Plack::Util::Accessor qw( config error_docs );
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -26,13 +31,39 @@ and not worry about closing it.
|
|||
sub call {
|
||||
my ( $self, $env ) = @_;
|
||||
|
||||
my $app = $self->app;
|
||||
my $config = $self->config or die 'Mandatory config parameter missing';
|
||||
|
||||
# Open the Session
|
||||
$env->{'webgui.session'} = WebGUI::Session->open( $config->getWebguiRoot, $config, $env );
|
||||
my $session = try {
|
||||
$env->{'webgui.session'} = WebGUI::Session->open( $config->getWebguiRoot, $config, $env );
|
||||
};
|
||||
|
||||
if (!$session) {
|
||||
# We don't have access to a db connection to find out if the user is allowed to see
|
||||
# a verbose error message or not, so resort to a generic Internal Server Error
|
||||
# (using the error_docs mapping)
|
||||
return Plack::Middleware::ErrorDocument->wrap(
|
||||
sub { [ 500, [], [] ] },
|
||||
%{ $self->error_docs } )->($env);
|
||||
}
|
||||
|
||||
my $debug = $session->log->canShowDebug;
|
||||
if ($debug) {
|
||||
$app = Plack::Middleware::StackTrace->wrap($app);
|
||||
$app = Plack::Middleware::Debug->wrap( $app,
|
||||
panels => [qw(Environment Response Timer Memory Session DBITrace PerlConfig Response)] );
|
||||
}
|
||||
|
||||
# Turn exceptions into HTTP errors
|
||||
$app = Plack::Middleware::HTTPExceptions->wrap($app);
|
||||
|
||||
# HTTP error document mapping
|
||||
if ( !$debug && $self->error_docs ) {
|
||||
$app = Plack::Middleware::ErrorDocument->wrap( $app, %{ $self->error_docs } );
|
||||
}
|
||||
|
||||
# Run the app
|
||||
my $res = $self->app->($env);
|
||||
my $res = $app->($env);
|
||||
|
||||
# Use callback style response
|
||||
return $self->response_cb(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use strict;
|
|||
use JSON;
|
||||
use HTML::Entities qw(encode_entities);
|
||||
use Log::Log4perl;
|
||||
use WebGUI::Exception;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -221,33 +222,43 @@ sub fatal {
|
|||
my $message = shift;
|
||||
|
||||
local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 2;
|
||||
$self->session->http->setStatus("500","Server Error");
|
||||
$self->session->response->content_type('text/html') if ($self->session->response);
|
||||
$self->getLogger->({ level => 'fatal', message => $message });
|
||||
$self->getLogger->({ level => 'debug', message => "Stack trace for FATAL ".$message."\n".$self->getStackTrace() });
|
||||
$self->session->http->sendHeader if ($self->session->response);
|
||||
|
||||
my $error;
|
||||
if (! defined $self->session->db(1)) {
|
||||
# We can't even _determine_ whether we can show the debug text. Punt.
|
||||
$self->session->output->print("<h1>Fatal Internal Error</h1>");
|
||||
$error = q{<h1>Fatal Internal Error</h1>};
|
||||
}
|
||||
elsif ($self->canShowDebug()) {
|
||||
$self->session->output->print("<h1>WebGUI Fatal Error</h1><p>Something unexpected happened that caused this system to fault.</p>\n",1);
|
||||
$self->session->output->print("<p>".$message."</p>\n",1);
|
||||
$self->session->output->print("<pre>" . encode_entities($self->getStackTrace) . "</pre>", 1);
|
||||
$self->session->output->print($self->showDebug(),1);
|
||||
my $stack = encode_entities($self->getStackTrace);
|
||||
my $debug = $self->showDebug();
|
||||
$error = <<END_HTML;
|
||||
<h1>WebGUI Fatal Error</h1>
|
||||
<p>Something unexpected happened that caused this system to fault.</p>
|
||||
<p>$message</p>
|
||||
<pre>$stack</pre>
|
||||
$debug
|
||||
END_HTML
|
||||
}
|
||||
else {
|
||||
# NOTE: You can't internationalize this because with some types of errors that would cause an infinite loop.
|
||||
$self->session->output->print("<h1>Problem With Request</h1>
|
||||
We have encountered a problem with your request. Please use your back button and try again.
|
||||
If this problem persists, please contact us with what you were trying to do and the time and date of the problem.<br />",1);
|
||||
$self->session->output->print('<br />'.$self->session->setting->get("companyName"),1);
|
||||
$self->session->output->print('<br />'.$self->session->setting->get("companyEmail"),1);
|
||||
$self->session->output->print('<br />'.$self->session->setting->get("companyURL"),1);
|
||||
my $company = $self->session->setting->get("companyName");
|
||||
my $email = $self->session->setting->get("companyEmail");
|
||||
my $url = $self->session->setting->get("companyURL");
|
||||
|
||||
$error = <<END_HTML;
|
||||
<h1>Problem With Request</h1>
|
||||
We have encountered a problem with your request. Please use your back button and try again.
|
||||
If this problem persists, please contact us with what you were trying to do and the time and date of the problem.<br />
|
||||
<br />$company
|
||||
<br />$email
|
||||
<br />$url
|
||||
END_HTML
|
||||
}
|
||||
$self->session->close();
|
||||
last WEBGUI_FATAL;
|
||||
|
||||
# Fatal errors cause an exception to be thrown
|
||||
WebGUI::Error->throw( error => $error );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,116 +0,0 @@
|
|||
package WebGUI::URL::Content;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Apache2::Const -compile => qw(OK DECLINED);
|
||||
use WebGUI::Affiliate;
|
||||
use WebGUI::Exception;
|
||||
use WebGUI::Pluggable;
|
||||
use WebGUI::Session;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::URL::Content
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A URL handler that does whatever I tell it to do.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::URL::Content;
|
||||
my $status = WebGUI::URL::Content::handler($r, $s, $config);
|
||||
|
||||
=head1 SUBROUTINES
|
||||
|
||||
These subroutines are available from this package:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 handler ( request, server, config )
|
||||
|
||||
The Apache request handler for this package.
|
||||
|
||||
This handler takes care of certain special tokens returns by a sub-handler.
|
||||
|
||||
=head3 chunked
|
||||
|
||||
This indicates that the handler has already returned the output to Apache. Commonly
|
||||
used in Assets to get head tags back to the user to speed up the rendering process.
|
||||
|
||||
=head3 empty
|
||||
|
||||
This token indicates that the asset is legitimatally empty. Returns nothing
|
||||
to the user, instead of displaying the Page Not Found page.
|
||||
|
||||
=cut
|
||||
|
||||
sub handler {
|
||||
my ($request, $server, $config) = @_;
|
||||
$request->push_handlers(PerlResponseHandler => sub {
|
||||
my $session = $request->pnotes('wgSession');
|
||||
unless (defined $session) {
|
||||
$session = WebGUI::Session->open($server->dir_config('WebguiRoot'), $config->getFilename, $request, $server);
|
||||
}
|
||||
WEBGUI_FATAL: foreach my $handler (@{$config->get("contentHandlers")}) {
|
||||
my $output = eval { WebGUI::Pluggable::run($handler, "handler", [ $session ] )};
|
||||
if ( my $e = WebGUI::Error->caught ) {
|
||||
$session->errorHandler->error($e->package.":".$e->line." - ".$e->error);
|
||||
$session->errorHandler->debug($e->package.":".$e->line." - ".$e->trace);
|
||||
}
|
||||
elsif ( $@ ) {
|
||||
$session->errorHandler->error( $@ );
|
||||
}
|
||||
else {
|
||||
if ($output eq "chunked") {
|
||||
if ($session->errorHandler->canShowDebug()) {
|
||||
$session->output->print($session->errorHandler->showDebug(),1);
|
||||
}
|
||||
last;
|
||||
}
|
||||
if ($output eq "empty") {
|
||||
if ($session->errorHandler->canShowDebug()) {
|
||||
$session->output->print($session->errorHandler->showDebug(),1);
|
||||
}
|
||||
last;
|
||||
}
|
||||
elsif (defined $output && $output ne "") {
|
||||
$session->http->sendHeader;
|
||||
$session->output->print($output);
|
||||
if ($session->errorHandler->canShowDebug()) {
|
||||
$session->output->print($session->errorHandler->showDebug(),1);
|
||||
}
|
||||
last;
|
||||
}
|
||||
# Keep processing for success codes
|
||||
elsif ($session->http->getStatus < 200 || $session->http->getStatus > 299) {
|
||||
$session->http->sendHeader;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
$session->close;
|
||||
return Apache2::Const::OK;
|
||||
});
|
||||
$request->push_handlers(PerlMapToStorageHandler => sub { return Apache2::Const::OK });
|
||||
$request->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK });
|
||||
return Apache2::Const::OK;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue