diff --git a/lib/WebGUI/Middleware/Session.pm b/lib/WebGUI/Middleware/Session.pm index 3f70cf908..37eb67fac 100644 --- a/lib/WebGUI/Middleware/Session.pm +++ b/lib/WebGUI/Middleware/Session.pm @@ -42,6 +42,9 @@ sub call { my $session = try { $env->{'webgui.session'} = WebGUI::Session->open( $config->getWebguiRoot, $config, $env ); + } catch { + # We don't have a logger object, so for now just warn() the error + warn "Unable to instantiate WebGUI::Session - $_"; }; if ( !$session ) { @@ -49,7 +52,11 @@ sub call { # 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); + if ($self->error_docs) { + return Plack::Middleware::ErrorDocument->wrap( sub { [ 500, [], [] ] }, %{ $self->error_docs } )->($env); + } else { + return [ 500, [ 'Content-Type' => 'text/plain' ], [ 'Internal Server Error' ] ]; + } } my $debug = $session->log->canShowDebug; diff --git a/lib/WebGUI/Session/ErrorHandler.pm b/lib/WebGUI/Session/ErrorHandler.pm index a2ad0e913..682f7072f 100644 --- a/lib/WebGUI/Session/ErrorHandler.pm +++ b/lib/WebGUI/Session/ErrorHandler.pm @@ -272,27 +272,7 @@ Returns a reference to the logger. =cut -sub getLogger { - my $self = shift; - if ($self->session->request) { - return $self->session->request->logger; - } else { - - # Thanks to Plack, wG has been decoupled from Log4Perl - # However when called outside a web context, we currently still fall back to Log4perl - # (pending a better idea) - if (!$self->{_logger}) { - Log::Log4perl->init_once( $self->session->config->getWebguiRoot."/etc/log.conf" ); - my $logger = Log::Log4perl->get_logger($self->session->config->getFilename); - $self->{_logger} = sub { - my $args = shift; - my $level = $args->{level}; - $logger->$level($args->{message}); - }; - } - return $self->{_logger}; - } -} +sub getLogger { $_[0]->{_logger} } #------------------------------------------------------------------- @@ -349,9 +329,25 @@ An active WebGUI::Session object. =cut sub new { - my $class = shift; - my $session = shift; - bless {_queryCount=>0, _session=>$session}, $class; + my $class = shift; + my $session = shift; + + my $logger = $session->request && $session->request->logger; + if ( !$logger ) { + + # Thanks to Plack, wG has been decoupled from Log4Perl + # However when called outside a web context, we currently still fall back to Log4perl + # (pending a better idea) + Log::Log4perl->init_once( $session->config->getWebguiRoot . "/etc/log.conf" ); + my $log4perl = Log::Log4perl->get_logger( $session->config->getFilename ); + $logger = sub { + my $args = shift; + my $level = $args->{level}; + $log4perl->$level( $args->{message} ); + }; + } + + bless { _queryCount => 0, _session => $session, _logger => $logger }, $class; } #---------------------------------------------------------------------------- diff --git a/t/Exception/app.t b/t/Exception/app.t new file mode 100644 index 000000000..fa2f77a91 --- /dev/null +++ b/t/Exception/app.t @@ -0,0 +1,85 @@ +# Test what happens when the WebGUI PSGI app throws exceptions +use strict; +use FindBin; +use lib "$FindBin::Bin/../../lib"; +use WebGUI; +use Plack::Test; +use Plack::Builder; +use HTTP::Request::Common; +use Test::More tests => 9; +use HTTP::Exception; + +my $wg = WebGUI->new; + +my $regular_app = builder { + enable '+WebGUI::Middleware::Session', config => $wg->config; + $wg; +}; + +my $generic_dead_app = builder { + enable '+WebGUI::Middleware::Session', config => $wg->config; + + # Pretend that WebGUI dies during request handling + sub { die 'WebGUI died' } +}; + +my $specific_dead_app = builder { + enable '+WebGUI::Middleware::Session', config => $wg->config; + + # Pretend that WebGUI throws a '501 - Not Implemented' HTTP error + sub { HTTP::Exception::501->throw } +}; + +my $fatal_app = builder { + enable '+WebGUI::Middleware::Session', config => $wg->config; + + # Pretend that WebGUI calls $session->log->fatal during request handling + sub { + my $env = shift; + + $env->{'webgui.session'}->log->fatal('Fatally yours'); + } +}; + +test_psgi $regular_app, sub { + my $cb = shift; + my $res = $cb->( GET "/" ); + like $res->content, qr/My Company/; +}; + +# N.B. The die() is caught thanks to WebGUI::Middleware::HTTPExceptions, +# but generates a warning to STDOUT - should perhaps be silenced? +test_psgi $generic_dead_app, sub { + my $cb = shift; + my $res = $cb->( GET "/" ); + is $res->code, 500; + is $res->content, 'Internal Server Error'; +}; + +test_psgi $specific_dead_app, sub { + my $cb = shift; + my $res = $cb->( GET "/" ); + is $res->code, 501; + is $res->content, 'Not Implemented'; # how apt +}; + +test_psgi $fatal_app, sub { + my $cb = shift; + my $res = $cb->( GET "/" ); + is $res->code, 500; + + # WebGUI doesn't know who you are, so it displays the generic error page + like $res->content, qr/Problem With Request/; +}; + +test_psgi $fatal_app, sub { + my $cb = shift; + + local *WebGUI::Session::ErrorHandler::canShowDebug = sub {1}; + my $res = $cb->( GET "/" ); + is $res->code, 500; + + # We canShowDebug, so WebGUI gives us more info + like $res->content, qr/Fatally yours/; +}; +