diff --git a/Changes b/Changes index b5a229c3c..361b019d3 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Go to http://github.com/plack/Plack/issues for the roadmap and known issues. {{$NEXT}} + [IMPROVEMENTS] + - Plack::Middleware::HTTPExceptions can now optionally send uncaught + exceptions to psgix.logger, instead of psgi.errors. (ether) 1.0024 2013-05-01 10:05:56 PDT [IMPROVEMENTS] diff --git a/dist.ini b/dist.ini index b1835cef4..c11f7b0b5 100644 --- a/dist.ini +++ b/dist.ini @@ -3,3 +3,6 @@ installer = MakeMaker [Metadata] x_authority = cpan:MIYAGAWA + +[Prereqs / TestRecommends] +Test::Deep = 0 diff --git a/lib/Plack/Middleware/HTTPExceptions.pm b/lib/Plack/Middleware/HTTPExceptions.pm index 23a7e935f..ba014950d 100644 --- a/lib/Plack/Middleware/HTTPExceptions.pm +++ b/lib/Plack/Middleware/HTTPExceptions.pm @@ -1,7 +1,7 @@ package Plack::Middleware::HTTPExceptions; use strict; use parent qw(Plack::Middleware); -use Plack::Util::Accessor qw(rethrow); +use Plack::Util::Accessor qw(rethrow use_logger); use Carp (); use Try::Tiny; @@ -60,7 +60,18 @@ sub transform_error { } else { $code = 500; - $env->{'psgi.errors'}->print($e); + if ($self->use_logger) { + if (defined $env->{'psgix.logger'}) { + $env->{'psgix.logger'}->({level=>'fatal',message=>$e}); + } + else { + $env->{'psgi.errors'}->print('no psgix.logger set - falling back to psgi.errors!'); + $env->{'psgi.errors'}->print($e); + } + } + else { + $env->{'psgi.errors'}->print($e); + } } } @@ -135,8 +146,9 @@ catch and display, but you can also implement your own exception class to throw. If the thrown exception is not an object that implements either a -C or an C method, a 500 error will be returned, and the -exception is printed to the psgi.errors stream. +C or an C method, a C<500> error will be returned, and the +exception is sent as a fatal message to C if the C +option is set, or printed to the C stream otherwise. Alternatively, you can pass a true value for the C parameter for this middleware, and the exception will instead be rethrown. This is enabled by default when C is set to C, so that diff --git a/t/Plack-Middleware/httpexceptions.t b/t/Plack-Middleware/httpexceptions.t index b7ee0a7a8..03ff9f8d3 100644 --- a/t/Plack-Middleware/httpexceptions.t +++ b/t/Plack-Middleware/httpexceptions.t @@ -70,4 +70,40 @@ test_psgi $app, sub { like $psgi_errors, qr/ugly stack trace here/; }; +SKIP: { + eval { require Test::Deep; 1 } + or skip 'Test::Deep required for remaining tests', 1; + + my $log_stash; + + my $app2 = sub { + my $env = shift; + $env->{'psgi.errors'} = undef; # will die if we attempt to use + $env->{'psgix.logger'} = sub { push @$log_stash, shift }; + die 'ugly stack trace here'; + }; + $app2 = Plack::Middleware::HTTPExceptions->wrap( + $app2, + use_logger => 1, + ); + + test_psgi $app2, sub { + my $cb = shift; + + # falls through to returning HTTP 500 + my $res = $cb->(GET "/uncaught"); + + Test::Deep::cmp_deeply( + $log_stash, + [ + { + level => 'fatal', + message => Test::Deep::re(qr/^ugly stack trace here/) + } + ], + 'psgix.logger is used, rather than psgi.errors', + ); + }; +} + done_testing;