File Coverage

blib/lib/Plack/Middleware/ExtractedStackTrace.pm
Criterion Covered Total %
statement 39 48 81.2
branch 3 10 30.0
condition 1 8 12.5
subroutine 13 13 100.0
pod 1 1 100.0
total 57 80 71.2


line stmt bran cond sub pod time code
1             package Plack::Middleware::ExtractedStackTrace;
2              
3 1     1   51048 use strict;
  1         1  
  1         22  
4 1     1   3 use warnings;
  1         2  
  1         19  
5              
6 1     1   2 use parent qw/Plack::Middleware/;
  1         1  
  1         3  
7              
8             our $VERSION = '1.000000';
9              
10 1     1   53 use Devel::StackTrace;
  1         1  
  1         21  
11 1     1   390 use Devel::StackTrace::Extract qw( extract_stack_trace );
  1         370  
  1         42  
12 1     1   391 use Devel::StackTrace::AsHTML;
  1         6267  
  1         26  
13 1     1   400 use Try::Tiny qw( catch try );
  1         903  
  1         46  
14 1     1   4 use Plack::Util::Accessor qw( force no_print_errors );
  1         1  
  1         6  
15              
16             ## no critic (ValuesAndExpressions::ProhibitAccessOfPrivateData)
17              
18             sub call {
19 3     3 1 22449 my ( $self, $env ) = @_;
20              
21 3         3 my $trace;
22             my $caught;
23              
24             my $res = try {
25 3     3   57 $self->app->($env);
26             }
27             catch {
28 1     1   598 $caught = $_;
29             [
30 1         4 500,
31             [ 'Content-Type', 'text/plain; charset=utf-8' ],
32             [ _no_trace_error( _utf8_safe($caught) ) ]
33             ];
34 3         17 };
35              
36 3 100       652 $trace = extract_stack_trace($caught) if $caught;
37              
38 3 0 0     10 if (
      33        
39             $trace
40             && ( $caught
41             || ( $self->force && ref $res eq 'ARRAY' && $res->[0] == 500 ) )
42             ) {
43 0         0 my $text = $trace->as_string;
44 0         0 my $html = $trace->as_html;
45 0         0 $env->{'plack.stacktrace.text'} = $text;
46 0         0 $env->{'plack.stacktrace.html'} = $html;
47 0 0       0 $env->{'psgi.errors'}->print($text) unless $self->no_print_errors;
48 0 0 0     0 if ( ( $env->{HTTP_ACCEPT} || '*/*' ) =~ /html/ ) {
49 0         0 $res = [
50             500,
51             [ 'Content-Type' => 'text/html; charset=utf-8' ],
52             [ _utf8_safe($html) ]
53             ];
54             }
55             else {
56 0         0 $res = [
57             500,
58             [ 'Content-Type' => 'text/plain; charset=utf-8' ],
59             [ _utf8_safe($text) ]
60             ];
61             }
62             }
63              
64 3         12 return $res;
65             }
66              
67             sub _no_trace_error {
68 1     1   1 my $msg = shift;
69 1         3 chomp($msg);
70              
71 1         8 return <<"EOF";
72             The application raised the following error:
73              
74             $msg
75              
76             For which no stack trace was captured.
77             EOF
78             }
79              
80             sub _utf8_safe {
81 1     1   2 my $str = shift;
82              
83             # NOTE: I know messing with utf8:: in the code is WRONG, but
84             # because we're running someone else's code that we can't
85             # guarantee which encoding an exception is encoded, there's no
86             # better way than doing this. The latest Devel::StackTrace::AsHTML
87             # (0.08 or later) encodes high-bit chars as HTML entities, so this
88             # path won't be executed.
89             ## no critic (Subroutines::ProhibitCallsToUnexportedSubs)
90             ## no critic (Modules::RequireExplicitInclusion)
91 1 50       5 if ( utf8::is_utf8($str) ) {
92 0         0 utf8::encode($str);
93             }
94             ## use critic
95              
96 1         3 $str;
97             }
98              
99             1;
100              
101             =pod
102              
103             =head1 NAME
104              
105             Plack::Middleware::ExtractedStackTrace - Displays stack trace from your exception objects when your app dies
106              
107             =head1 VERSION
108              
109             version 1.000000
110              
111             =head1 ACKNOWLEDGEMENTS
112              
113             Parts of this code (in this module file only) were derived from
114             L, part of the Plack distribution. Copyright for
115             code derived from Plack resides with the original holder.
116              
117             =head1 AUTHOR
118              
119             Mark Fowler
120              
121             =head1 CONTRIBUTOR
122              
123             =for stopwords Olaf Alders
124              
125             Olaf Alders
126              
127             =head1 COPYRIGHT AND LICENSE
128              
129             This software is copyright (c) 2016 by MaxMind, Inc.
130              
131             This is free software; you can redistribute it and/or modify it under
132             the same terms as the Perl 5 programming language system itself.
133              
134             =cut
135              
136             __END__