Skip to content

Commit

Permalink
Added exception handling
Browse files Browse the repository at this point in the history
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
  • Loading branch information
patspam committed Apr 11, 2010
1 parent 2bac95f commit 716bdae
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 145 deletions.
5 changes: 4 additions & 1 deletion TODO
@@ -1,14 +1,17 @@
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
* serverObject gone from WebGUI::Session::open()
* 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..
Expand Down
15 changes: 8 additions & 7 deletions app.psgi
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/WebGUI.pm
Expand Up @@ -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);
Expand Down
39 changes: 39 additions & 0 deletions lib/WebGUI/Middleware/Debug.pm
@@ -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;
39 changes: 35 additions & 4 deletions lib/WebGUI/Middleware/Session.pm
Expand Up @@ -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
Expand All @@ -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(
Expand Down
43 changes: 27 additions & 16 deletions lib/WebGUI/Session/ErrorHandler.pm
Expand Up @@ -19,6 +19,7 @@ use strict;
use JSON;
use HTML::Entities qw(encode_entities);
use Log::Log4perl;
use WebGUI::Exception;

=head1 NAME
Expand Down Expand Up @@ -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 );
}


Expand Down
116 changes: 0 additions & 116 deletions lib/WebGUI/URL/Content.pm

This file was deleted.

0 comments on commit 716bdae

Please sign in to comment.