| blib/lib/Dancer2/Core/Error.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 152 | 152 | 100.0 |
| branch | 55 | 64 | 85.9 |
| condition | 32 | 40 | 80.0 |
| subroutine | 24 | 24 | 100.0 |
| pod | 5 | 8 | 62.5 |
| total | 268 | 288 | 93.0 |
| line | stmt | bran | cond | sub | pod | time | code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | package Dancer2::Core::Error; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2 | # ABSTRACT: Class representing fatal errors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 3 | $Dancer2::Core::Error::VERSION = '2.0.1'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4 | 158 | 158 | 510664 | use Moo; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 21423 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 1332 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 5 | 158 | 158 | 79655 | use Carp; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 390 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 15023 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 6 | 158 | 158 | 2543 | use Dancer2::Core::Types; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 436 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 1759 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 7 | 158 | 158 | 2218552 | use Dancer2::Core::HTTP; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 599 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 9805 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 8 | 158 | 158 | 105958 | use Data::Dumper; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 1549771 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 16154 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 9 | 158 | 158 | 3358 | use Dancer2::FileUtils qw/path open_file/; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 375 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 12448 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10 | 158 | 158 | 1278 | use Sub::Quote; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 514 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 11641 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 11 | 158 | 158 | 2714 | use Module::Runtime qw/ require_module use_module /; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 6198 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 1521 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 12 | 158 | 158 | 12278 | use Ref::Util qw< is_hashref >; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 2506 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 8064 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 13 | 158 | 158 | 23895 | use Clone qw(clone); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 27141 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | 528754 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 14 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 15 | has app => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 16 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 17 | isa => InstanceOf['Dancer2::Core::App'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 18 | predicate => 'has_app', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 19 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 20 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 21 | has show_stacktrace => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 22 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 23 | isa => Bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 24 | default => sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 25 | my $self = shift; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 26 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 27 | $self->has_app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 28 | and return $self->app->setting('show_stacktrace'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 29 | }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 30 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 31 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 32 | has charset => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 33 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 34 | isa => Str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 35 | default => sub {'UTF-8'}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 36 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 37 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 38 | has type => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 39 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 40 | isa => Str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 41 | default => sub {'Runtime Error'}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 42 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 43 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 44 | has title => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 45 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 46 | isa => Str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 47 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 48 | builder => '_build_title', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 49 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 50 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 51 | has censor => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 52 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 53 | isa => CodeRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 54 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 55 | default => sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 56 | my $self = shift; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 57 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 58 | if( my $custom = $self->has_app && $self->app->setting('error_censor') ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 59 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 60 | if( is_hashref $custom ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 61 | die "only one key can be set for the 'error_censor' setting\n" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 62 | if 1 != keys %$custom; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 63 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 64 | my( $class, $args ) = %$custom; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 65 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 66 | my $censor = use_module($class)->new(%$args); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 67 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 68 | return sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 69 | $censor->censor(@_); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 70 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 71 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 72 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 73 | my $coderef = eval '\&'.$custom; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 74 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 75 | # it's already defined? Nice! We're done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 76 | return $coderef if $coderef; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 77 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 78 | my $module = $custom =~ s/::[^:]*?$//r; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 79 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 80 | require_module($module); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 81 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 82 | return eval '\&'.$custom; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 83 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 84 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 85 | # reminder: update POD below if changing the config here | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 86 | my $data_censor = use_module('Data::Censor')->new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 87 | sensitive_fields => qr/pass|card.?num|pan|secret/i, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 88 | replacement => "Hidden (looks potentially sensitive)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 89 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 90 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 91 | return sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 92 | $data_censor->censor(@_); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 93 | }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 94 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 95 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 96 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 97 | sub _build_title { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 98 | 132 | 132 | 4622 | my ($self) = @_; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 99 | 132 | 2988 | my $title = 'Error ' . $self->status; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 100 | 132 | 100 | 3458 | if ( my $msg = Dancer2::Core::HTTP->status_message($self->status) ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 101 | 131 | 424 | $title .= ' - ' . $msg; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 102 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 103 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 104 | 132 | 3165 | return $title; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 105 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 106 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 107 | has template => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 108 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 109 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 110 | builder => '_build_error_template', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 111 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 112 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 113 | sub _build_error_template { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 114 | 119 | 119 | 1426 | my ($self) = @_; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 115 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 116 | # look for a template named after the status number. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 117 | # E.g.: views/404.tt for a TT template | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 118 | 119 | 2729 | my $engine = $self->app->template_engine; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 119 | 119 | 100 | 3439 | return $self->status | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 120 | if $engine->pathname_exists( $engine->view_pathname( $self->status ) ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 121 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 122 | 113 | 1071 | return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 123 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 124 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 125 | has static_page => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 126 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 127 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 128 | builder => '_build_static_page', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 129 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 130 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 131 | sub _build_static_page { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 132 | 113 | 113 | 1336 | my ($self) = @_; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 133 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 134 | # TODO there must be a better way to get it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 135 | my $public_dir = $ENV{DANCER_PUBLIC} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 136 | 113 | 66 | 3287 | || ( $self->has_app && $self->app->config->{public_dir} ); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 137 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 138 | 113 | 3302 | my $filename = sprintf "%s/%d.html", $public_dir, $self->status; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 139 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 140 | 113 | 100 | 7100 | open my $fh, '<', $filename or return; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 141 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 142 | 2 | 18 | local $/ = undef; # slurp time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 143 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 144 | 2 | 246 | return <$fh>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 145 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 146 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 147 | sub default_error_page { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 148 | 115 | 115 | 0 | 274 | my $self = shift; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 149 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 150 | 115 | 1470 | require_module('Template::Tiny'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 151 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 152 | 115 | 100 | 100 | 6168 | my $uri_base = $self->has_app && $self->app->has_request ? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 153 | $self->app->request->uri_base : ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 154 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 155 | # GH#1001 stack trace if show_stacktrace is true and this is a 'server' error (5xx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 156 | 115 | 100 | 1365 | my $show_fullmsg = $self->show_stacktrace && $self->status =~ /^5/; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 157 | 115 | 100 | 100 | 3821 | my $opts = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 158 | title => $self->title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 159 | charset => $self->charset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 160 | content => $show_fullmsg ? $self->full_message : _html_encode($self->message) || 'Wooops, something went wrong', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 161 | version => Dancer2->VERSION, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 162 | uri_base => $uri_base, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 163 | }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 164 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 165 | 115 | 1127 | Template::Tiny->new->process( \<<"END_TEMPLATE", $opts, \my $output ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 166 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 167 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 168 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 169 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 170 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 171 | |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 172 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 173 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 174 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 175 | [% title %] |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 176 | |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 177 | [% content %] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 178 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 179 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 180 | Powered by Dancer2 [% version %] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 181 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 182 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 183 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 184 | END_TEMPLATE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 185 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 186 | 115 | 90903 | return $output; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 187 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 188 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 189 | # status and message are 'rw' to permit modification in core.error.before hooks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 190 | has status => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 191 | is => 'rw', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 192 | default => sub {500}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 193 | isa => Num, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 194 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 195 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 196 | has message => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 197 | is => 'rw', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 198 | isa => Str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 199 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 200 | default => sub { '' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 201 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 202 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 203 | sub full_message { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 204 | 7 | 7 | 0 | 326 | my ($self) = @_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 205 | 7 | 43 | my $html_output = "" . $self->type . ""; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 206 | 7 | 32 | $html_output .= $self->backtrace; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 207 | 7 | 41 | $html_output .= $self->environment; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 208 | 7 | 87 | return $html_output; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 209 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 210 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 211 | has serializer => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 212 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 213 | isa => Maybe[ConsumerOf['Dancer2::Core::Role::Serializer']], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 214 | builder => '_build_serializer', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 215 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 216 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 217 | sub _build_serializer { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 218 | 138 | 138 | 7448 | my ($self) = @_; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 219 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 220 | 138 | 100 | 100 | 2022 | $self->has_app && $self->app->has_serializer_engine | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 221 | and return $self->app->serializer_engine; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 222 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 223 | 130 | 3247 | return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 224 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 225 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 226 | sub BUILD { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 227 | 141 | 141 | 0 | 4281 | my ($self) = @_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 228 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 229 | 141 | 100 | 4668 | $self->has_app && | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 230 | $self->app->execute_hook( 'core.error.init', $self ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 231 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 232 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 233 | has exception => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 234 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 235 | isa => Str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 236 | predicate => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 237 | coerce => sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 238 | # Until we properly support exception objects, we shouldn't barf on | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 239 | # them because that hides the actual error, if object overloads "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 240 | # which most exception objects do, this will result in a nicer string. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 241 | # other references will produce a meaningless error, but that is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 242 | # better than a meaningless stacktrace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 243 | return "$_[0]" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 244 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 245 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 246 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 247 | has response => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 248 | is => 'rw', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 249 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 250 | default => sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 251 | my $self = shift; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 252 | my $serializer = $self->serializer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 253 | # include server tokens in response ? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 254 | my $no_server_tokens = $self->has_app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 255 | ? $self->app->config->{'no_server_tokens'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 256 | : defined $ENV{DANCER_NO_SERVER_TOKENS} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 257 | ? $ENV{DANCER_NO_SERVER_TOKENS} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 258 | : 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 259 | return Dancer2::Core::Response->new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 260 | server_tokens => !$no_server_tokens, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 261 | ( serializer => $serializer )x!! $serializer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 262 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 263 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 264 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 265 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 266 | has content_type => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 267 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 268 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 269 | default => sub { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 270 | my $self = shift; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 271 | $self->serializer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 272 | ? $self->serializer->content_type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 273 | : 'text/html' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 274 | }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 275 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 276 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 277 | has content => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 278 | is => 'ro', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 279 | lazy => 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 280 | builder => '_build_content', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 281 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 282 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 283 | sub _build_content { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 284 | 134 | 134 | 2585 | my $self = shift; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 285 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 286 | # return a hashref if a serializer is available | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 287 | 134 | 100 | 725 | if ( $self->serializer ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 288 | 10 | 232 | my $content = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 289 | message => $self->message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 290 | title => $self->title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 291 | status => $self->status, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 292 | }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 293 | 10 | 100 | 696 | $content->{exception} = $self->exception | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 294 | if $self->has_exception; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 295 | 10 | 56 | return $content; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 296 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 297 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 298 | # otherwise we check for a template, for a static file, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 299 | # for configured error_template, and, if all else fails, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 300 | # the default error page | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 301 | 124 | 100 | 100 | 3172 | if ( $self->has_app and $self->template ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 302 | # Render the template using apps' template engine. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 303 | # This may well be what caused the initial error, in which | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 304 | # case we fall back to static page if any error was thrown. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 305 | # Note: this calls before/after render hooks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 306 | 6 | 100 | my $content = eval { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 307 | 6 | 157 | $self->app->template( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 308 | $self->template, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 309 | { title => $self->title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 310 | content => $self->message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 311 | exception => $self->exception, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 312 | status => $self->status, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 313 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 314 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 315 | }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 316 | 6 | 100 | 77 | $@ && $self->app->engine('logger')->log( warning => $@ ); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 317 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 318 | # return rendered content unless there was an error. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 319 | 6 | 100 | 71 | return $content if defined $content; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 320 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 321 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 322 | # It doesn't make sense to return a static page for a 500 if show_stacktrace is on | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 323 | 120 | 100 | 100 | 1310 | if ( !($self->show_stacktrace && $self->status eq '500') ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 324 | 113 | 100 | 3107 | if ( my $content = $self->static_page ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 325 | 2 | 21 | return $content; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 326 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 327 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 328 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 329 | 118 | 100 | 100 | 3506 | if ($self->has_app && $self->app->config->{error_template}) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 330 | 3 | 22 | my $content = eval { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 331 | $self->app->template( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 332 | $self->app->config->{error_template}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 333 | 3 | 35 | { title => $self->title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 334 | content => $self->message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 335 | exception => $self->exception, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 336 | status => $self->status, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 337 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 338 | ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 339 | }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 340 | 3 | 50 | 13 | $@ && $self->app->engine('logger')->log( warning => $@ ); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 341 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 342 | # return rendered content unless there was an error. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 343 | 3 | 50 | 22 | return $content if defined $content; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 344 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 345 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 346 | 115 | 1435 | return $self->default_error_page; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 347 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 348 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 349 | sub throw { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 350 | 133 | 133 | 1 | 2919 | my $self = shift; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 351 | 133 | 100 | 543 | $self->response(shift) if @_; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 352 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 353 | 133 | 50 | 3146 | $self->response | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 354 | or croak "error has no response to throw at"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 355 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 356 | 133 | 100 | 4402 | $self->has_app && | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 357 | $self->app->execute_hook( 'core.error.before', $self ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 358 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 359 | 133 | 4583 | my $message = $self->content; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 360 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 361 | 133 | 5724 | $self->response->status( $self->status ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 362 | 133 | 8492 | $self->response->content_type( $self->content_type ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 363 | 133 | 3393 | $self->response->content($message); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 364 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 365 | 133 | 100 | 19447 | $self->has_app && | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 366 | $self->app->execute_hook('core.error.after', $self->response); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 367 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 368 | 133 | 4298 | $self->response->is_halted(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 369 | 133 | 10604 | return $self->response; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 370 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 371 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 372 | sub backtrace { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 373 | 7 | 7 | 1 | 22 | my ($self) = @_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 374 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 375 | 7 | 202 | my $message = $self->message; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 376 | 7 | 50 | 244 | if ($self->exception) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 377 | 7 | 50 | 30 | $message .= "\n" if $message; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 378 | 7 | 32 | $message .= $self->exception; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 379 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 380 | 7 | 50 | 25 | $message ||= 'Wooops, something went wrong'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 381 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 382 | 7 | 50 | my $html = '' . _html_encode($message) . "\n"; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 383 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 384 | # the default perl warning/error pattern | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 385 | 7 | 57 | my ($file, $line) = $message =~ /at (\S+) line (\d+)/; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 386 | # the Devel::SimpleTrace pattern | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 387 | 7 | 100 | 66 | 75 | ($file, $line) = $message =~ /at.*\((\S+):(\d+)\)/ unless $file and $line; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 388 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 389 | # no file/line found, cannot open a file for context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 390 | 7 | 100 | 66 | 87 | return $html unless $file and $line; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 391 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 392 | # file and line are located, let's read the source Luke! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 393 | 4 | 50 | 14 | my $fh = eval { open_file('<', $file) } or return $html; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4 | 31 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 394 | 4 | 144 | my @lines = <$fh>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 395 | 4 | 1184 | close $fh; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 396 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 397 | 4 | 20 | $html .= qq| $file around line $line |; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 398 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 399 | # get 5 lines of context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 400 | 4 | 50 | 28 | my $start = $line - 5 > 1 ? $line - 5 : 1; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 401 | 4 | 50 | 19 | my $stop = $line + 5 < @lines ? $line + 5 : @lines; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 402 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 403 | 4 | 15 | $html .= qq|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 411 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 412 | 4 | 135 | return $html; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 413 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 414 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 415 | sub dumper { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 416 | 13 | 13 | 1 | 169 | my ($self,$obj) = @_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 417 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 418 | # Take a copy of the data, so we can mask sensitive-looking stuff: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 419 | 13 | 1297 | my $data = clone($obj); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 420 | 13 | 549 | my $censored = $self->censor->( $data ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 421 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 422 | #use Data::Dumper; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 423 | 13 | 5214 | my $dd = Data::Dumper->new( [ $data ] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 424 | 13 | 625 | my $hash_separator = ' @@!%,+$$#._(-- '; # Very unlikely string to exist already | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 425 | 13 | 31 | my $prefix_padding = ' #+#+@%.,$_-!(( '; # Very unlikely string to exist already | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 426 | 13 | 72 | $dd->Terse(1)->Quotekeys(0)->Indent(1)->Sortkeys(1)->Pair($hash_separator)->Pad($prefix_padding); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 427 | 13 | 803 | my $content = _html_encode( $dd->Dump ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 428 | 13 | 121 | $content =~ s/^.+//; # Remove the first line | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 429 | 13 | 346 | $content =~ s/\n.+$//; # Remove the last line | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 430 | 13 | 495 | $content =~ s/^\Q$prefix_padding\E //gm; # Remove the padding | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 431 | 13 | 2134 | $content =~ s{^(\s*)(.+)\Q$hash_separator}{$1$2 => }gm; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 432 | 13 | 100 | 75 | if ($censored) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 433 | 7 | 21 | $content | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 434 | .= "\n\nNote: Values of $censored sensitive-looking keys hidden\n"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 435 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 436 | 13 | 677 | return $content; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 437 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 438 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 439 | sub environment { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 440 | 13 | 13 | 1 | 84 | my ($self) = @_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 441 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 442 | 13 | 57 | my $stack = $self->get_caller; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 443 | 13 | 66 | 142 | my $settings = $self->has_app && $self->app->settings; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 444 | 13 | 33 | 434 | my $session = $self->has_app && $self->app->_has_session && $self->app->session->data; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 445 | 13 | 66 | 139 | my $env = $self->has_app && $self->app->has_request && $self->app->request->env; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 446 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 447 | # Get a sanitised dump of the settings, session and environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 448 | 13 | 100 | 132 | $_ = $_ ? $self->dumper($_) : 'undefined' for $settings, $session, $env; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 449 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 450 | 13 | 335 | return <<"END_HTML"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 451 | Stack $stack |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 452 | Settings $settings |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 453 | Session $session |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 454 | Environment $env |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 455 | END_HTML | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 456 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 457 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 458 | sub get_caller { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 459 | 13 | 13 | 1 | 37 | my ($self) = @_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 460 | 13 | 28 | my @stack; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 461 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 462 | 13 | 29 | my $deepness = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 463 | 13 | 134 | while ( my ( $package, $file, $line ) = caller( $deepness++ ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 464 | 206 | 1340 | push @stack, "$package in $file l. $line"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 465 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 466 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 467 | 13 | 133 | return join( "\n", reverse(@stack) ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 468 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 469 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 470 | # private | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 471 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 472 | # Replaces the entities that are illegal in (X)HTML. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 473 | sub _html_encode { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 474 | 172 | 172 | 10684 | my $value = shift; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 475 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 476 | 172 | 50 | 607 | return if !defined $value; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 477 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 478 | 172 | 499 | $value =~ s/&/&/g; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 479 | 172 | 359 | $value =~ s/</g; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 480 | 172 | 488 | $value =~ s/>/>/g; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 481 | 172 | 699 | $value =~ s/'/'/g; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 482 | 172 | 442 | $value =~ s/"/"/g; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 483 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 484 | 172 | 1368 | return $value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 485 | } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 486 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 487 | 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 488 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 489 | __END__ |