| blib/lib/AxKit2/Client.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 13 | 15 | 86.6 |
| branch | n/a | ||
| condition | n/a | ||
| subroutine | 5 | 5 | 100.0 |
| pod | n/a | ||
| total | 18 | 20 | 90.0 |
| line | stmt | bran | cond | sub | pod | time | code | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | # Copyright 2001-2006 The Apache Software Foundation | |||||||||||||
| 2 | # | |||||||||||||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |||||||||||||
| 4 | # you may not use this file except in compliance with the License. | |||||||||||||
| 5 | # You may obtain a copy of the License at | |||||||||||||
| 6 | # | |||||||||||||
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 | |||||||||||||
| 8 | # | |||||||||||||
| 9 | # Unless required by applicable law or agreed to in writing, software | |||||||||||||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | |||||||||||||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||||||||||
| 12 | # See the License for the specific language governing permissions and | |||||||||||||
| 13 | # limitations under the License. | |||||||||||||
| 14 | # | |||||||||||||
| 15 | ||||||||||||||
| 16 | package AxKit2::Client; | |||||||||||||
| 17 | ||||||||||||||
| 18 | 9 | 9 | 54 | use strict; | ||||||||||
| 9 | 29 | |||||||||||||
| 9 | 339 | |||||||||||||
| 19 | 9 | 9 | 50 | use warnings; | ||||||||||
| 9 | 15 | |||||||||||||
| 9 | 278 | |||||||||||||
| 20 | ||||||||||||||
| 21 | 9 | 9 | 4996 | use AxKit2::Plugin; | ||||||||||
| 9 | 30 | |||||||||||||
| 9 | 269 | |||||||||||||
| 22 | 9 | 9 | 65 | use AxKit2::Constants; | ||||||||||
| 9 | 18 | |||||||||||||
| 9 | 1157 | |||||||||||||
| 23 | 9 | 9 | 6377 | use AxKit2::Processor; | ||||||||||
| 0 | ||||||||||||||
| 0 | ||||||||||||||
| 24 | use AxKit2::Utils qw(xml_escape); | |||||||||||||
| 25 | use Carp qw(croak); | |||||||||||||
| 26 | ||||||||||||||
| 27 | our %PLUGINS; | |||||||||||||
| 28 | ||||||||||||||
| 29 | sub load_plugin { | |||||||||||||
| 30 | my ($class, $conf, $plugin) = @_; | |||||||||||||
| 31 | ||||||||||||||
| 32 | my $package; | |||||||||||||
| 33 | ||||||||||||||
| 34 | if ($plugin =~ m/::/) { | |||||||||||||
| 35 | # "full" package plugin (My::Plugin) | |||||||||||||
| 36 | $package = $plugin; | |||||||||||||
| 37 | $package =~ s/[^_a-z0-9:]+//gi; | |||||||||||||
| 38 | my $eval = qq[require $package;\n] | |||||||||||||
| 39 | .qq[sub ${plugin}::plugin_name { '$plugin' }] | |||||||||||||
| 40 | .qq[sub ${plugin}::hook_name { shift->{_hook}; }]; | |||||||||||||
| 41 | $eval =~ m/(.*)/s; | |||||||||||||
| 42 | $eval = $1; | |||||||||||||
| 43 | eval $eval; | |||||||||||||
| 44 | die "Failed loading $package - eval $@" if $@; | |||||||||||||
| 45 | $class->log(LOGDEBUG, "Loaded Plugin $package"); | |||||||||||||
| 46 | } | |||||||||||||
| 47 | else { | |||||||||||||
| 48 | ||||||||||||||
| 49 | my $dir = $conf->plugin_dir || "./plugins"; | |||||||||||||
| 50 | ||||||||||||||
| 51 | my $plugin_name = plugin_to_name($plugin); | |||||||||||||
| 52 | $package = "AxKit2::Plugin::$plugin_name"; | |||||||||||||
| 53 | ||||||||||||||
| 54 | # don't reload plugins if they are already loaded | |||||||||||||
| 55 | unless ( defined &{"${package}::plugin_name"} ) { | |||||||||||||
| 56 | AxKit2::Plugin->_compile($plugin_name, | |||||||||||||
| 57 | $package, "$dir/$plugin"); | |||||||||||||
| 58 | } | |||||||||||||
| 59 | } | |||||||||||||
| 60 | ||||||||||||||
| 61 | return if $PLUGINS{$plugin}; | |||||||||||||
| 62 | ||||||||||||||
| 63 | my $plug = $package->new(); | |||||||||||||
| 64 | $PLUGINS{$plugin} = $plug; | |||||||||||||
| 65 | $plug->_register(); | |||||||||||||
| 66 | } | |||||||||||||
| 67 | ||||||||||||||
| 68 | sub plugin_to_name { | |||||||||||||
| 69 | my $plugin = shift; | |||||||||||||
| 70 | ||||||||||||||
| 71 | my $plugin_name = $plugin; | |||||||||||||
| 72 | ||||||||||||||
| 73 | # Escape everything into valid perl identifiers | |||||||||||||
| 74 | $plugin_name =~ s/([^A-Za-z0-9_\/])/sprintf("_%2x",unpack("C",$1))/eg; | |||||||||||||
| 75 | ||||||||||||||
| 76 | # second pass cares for slashes and words starting with a digit | |||||||||||||
| 77 | $plugin_name =~ s{ | |||||||||||||
| 78 | (/+) # directory | |||||||||||||
| 79 | (\d?) # package's first character | |||||||||||||
| 80 | }[ | |||||||||||||
| 81 | "::" . (length $2 ? sprintf("_%2x",unpack("C",$2)) : "") | |||||||||||||
| 82 | ]egx; | |||||||||||||
| 83 | ||||||||||||||
| 84 | ||||||||||||||
| 85 | return $plugin_name; | |||||||||||||
| 86 | } | |||||||||||||
| 87 | ||||||||||||||
| 88 | sub plugin_instance { | |||||||||||||
| 89 | my $plugin = shift; | |||||||||||||
| 90 | return $PLUGINS{$plugin}; | |||||||||||||
| 91 | } | |||||||||||||
| 92 | ||||||||||||||
| 93 | sub config { | |||||||||||||
| 94 | # should be subclassed - clients get a server config | |||||||||||||
| 95 | AxKit2::Config->global; | |||||||||||||
| 96 | } | |||||||||||||
| 97 | ||||||||||||||
| 98 | sub run_hooks { | |||||||||||||
| 99 | my ($self, $hook) = (shift, shift); | |||||||||||||
| 100 | ||||||||||||||
| 101 | my $conf = $self->config(); | |||||||||||||
| 102 | ||||||||||||||
| 103 | if (my $cached_hooks = $conf->cached_hooks($hook)) { | |||||||||||||
| 104 | return $self->_run_hooks($conf, $hook, [@_], $cached_hooks, 0); | |||||||||||||
| 105 | } | |||||||||||||
| 106 | ||||||||||||||
| 107 | my @hooks; | |||||||||||||
| 108 | for my $plugin ($conf->plugins) { | |||||||||||||
| 109 | my $plug = $PLUGINS{$plugin} || next; | |||||||||||||
| 110 | push @hooks, map { [$plugin, $plug, $_] } $plug->hooks($hook); | |||||||||||||
| 111 | } | |||||||||||||
| 112 | ||||||||||||||
| 113 | $conf->cached_hooks($hook, \@hooks); | |||||||||||||
| 114 | $self->_run_hooks($conf, $hook, [@_], \@hooks, 0); | |||||||||||||
| 115 | } | |||||||||||||
| 116 | ||||||||||||||
| 117 | sub finish_continuation { | |||||||||||||
| 118 | my ($self) = @_; | |||||||||||||
| 119 | my $todo = $self->{continuation} || croak "No continuation in progress"; | |||||||||||||
| 120 | $self->continue_read(); | |||||||||||||
| 121 | $self->{continuation} = undef; | |||||||||||||
| 122 | my $hook = shift @$todo; | |||||||||||||
| 123 | my $args = shift @$todo; | |||||||||||||
| 124 | my $pos = shift @$todo; | |||||||||||||
| 125 | my $conf = $self->config; | |||||||||||||
| 126 | my $hooks = $conf->cached_hooks($hook); | |||||||||||||
| 127 | $self->_run_hooks($conf, $hook, $args, $hooks, $pos+1); | |||||||||||||
| 128 | } | |||||||||||||
| 129 | ||||||||||||||
| 130 | sub _run_hooks { | |||||||||||||
| 131 | my $self = shift; | |||||||||||||
| 132 | my ($conf, $hook, $args, $hooks, $pos) = @_; | |||||||||||||
| 133 | ||||||||||||||
| 134 | my $last_hook = $#$hooks; | |||||||||||||
| 135 | ||||||||||||||
| 136 | my @r; | |||||||||||||
| 137 | if ($pos <= $last_hook) { | |||||||||||||
| 138 | for my $idx ($pos .. $last_hook) { | |||||||||||||
| 139 | my $info = $hooks->[$idx]; | |||||||||||||
| 140 | my ($plugin, $plug, $h) = @$info; | |||||||||||||
| 141 | # $self->log(LOGDEBUG, "$plugin ($idx) running hook $hook") unless $hook eq 'logging'; | |||||||||||||
| 142 | eval { @r = $plug->$h($self, $conf, @$args) }; | |||||||||||||
| 143 | if ($@) { | |||||||||||||
| 144 | my $err = $@; | |||||||||||||
| 145 | $self->log(LOGERROR, "FATAL PLUGIN ERROR: $err"); | |||||||||||||
| 146 | $self->hook_error($err) unless $hook eq 'error'; | |||||||||||||
| 147 | return DONE; | |||||||||||||
| 148 | } | |||||||||||||
| 149 | next unless @r; | |||||||||||||
| 150 | if (!defined $r[0]) { | |||||||||||||
| 151 | print "r0 not defined in hook $hook\[$idx]\n"; | |||||||||||||
| 152 | } | |||||||||||||
| 153 | if ($r[0] == CONTINUATION) { | |||||||||||||
| 154 | $self->pause_read(); | |||||||||||||
| 155 | $self->{continuation} = [$hook, $args, $idx]; | |||||||||||||
| 156 | } | |||||||||||||
| 157 | last unless $r[0] == DECLINED; | |||||||||||||
| 158 | } | |||||||||||||
| 159 | } | |||||||||||||
| 160 | ||||||||||||||
| 161 | $r[0] = DECLINED if not defined $r[0]; | |||||||||||||
| 162 | if ($r[0] != CONTINUATION) { | |||||||||||||
| 163 | my $responder = "hook_${hook}_end"; | |||||||||||||
| 164 | if (my $meth = $self->can($responder)) { | |||||||||||||
| 165 | return $meth->($self, $r[0], $r[1], @$args); | |||||||||||||
| 166 | } | |||||||||||||
| 167 | } | |||||||||||||
| 168 | return @r; | |||||||||||||
| 169 | } | |||||||||||||
| 170 | ||||||||||||||
| 171 | sub log { | |||||||||||||
| 172 | my $self = shift; | |||||||||||||
| 173 | $self->run_hooks('logging', @_); | |||||||||||||
| 174 | } | |||||||||||||
| 175 | ||||||||||||||
| 176 | sub hook_connect { | |||||||||||||
| 177 | my $self = shift; | |||||||||||||
| 178 | $self->run_hooks('connect'); | |||||||||||||
| 179 | } | |||||||||||||
| 180 | ||||||||||||||
| 181 | sub hook_connect_end { | |||||||||||||
| 182 | my $self = shift; | |||||||||||||
| 183 | my ($ret, $out) = @_; | |||||||||||||
| 184 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 185 | # success | |||||||||||||
| 186 | $self->run_hooks('pre_request'); | |||||||||||||
| 187 | } | |||||||||||||
| 188 | else { | |||||||||||||
| 189 | $self->close("connect hook closing"); | |||||||||||||
| 190 | return; | |||||||||||||
| 191 | } | |||||||||||||
| 192 | } | |||||||||||||
| 193 | ||||||||||||||
| 194 | sub hook_pre_request { | |||||||||||||
| 195 | my $self = shift; | |||||||||||||
| 196 | $self->run_hooks('pre_request'); | |||||||||||||
| 197 | } | |||||||||||||
| 198 | ||||||||||||||
| 199 | sub hook_pre_request_end { | |||||||||||||
| 200 | my $self = shift; | |||||||||||||
| 201 | my ($ret, $out) = @_; | |||||||||||||
| 202 | # TODO: Manage $ret | |||||||||||||
| 203 | return; | |||||||||||||
| 204 | } | |||||||||||||
| 205 | ||||||||||||||
| 206 | sub hook_body_data { | |||||||||||||
| 207 | my $self = shift; | |||||||||||||
| 208 | $self->run_hooks('body_data', @_); | |||||||||||||
| 209 | } | |||||||||||||
| 210 | ||||||||||||||
| 211 | sub hook_body_data_end { | |||||||||||||
| 212 | my ($self, $ret) = @_; | |||||||||||||
| 213 | if ($ret == DECLINED || $ret == DONE) { | |||||||||||||
| 214 | return $self->process_request(); | |||||||||||||
| 215 | } | |||||||||||||
| 216 | elsif ($ret == OK) { | |||||||||||||
| 217 | return 1; | |||||||||||||
| 218 | } | |||||||||||||
| 219 | else { | |||||||||||||
| 220 | $self->default_error_out($ret); | |||||||||||||
| 221 | } | |||||||||||||
| 222 | } | |||||||||||||
| 223 | ||||||||||||||
| 224 | sub hook_write_body_data { | |||||||||||||
| 225 | my $self = shift; | |||||||||||||
| 226 | my ($ret) = $self->run_hooks('write_body_data'); | |||||||||||||
| 227 | if ($ret == CONTINUATION) { | |||||||||||||
| 228 | die "Continuations not supported on write_body_data"; | |||||||||||||
| 229 | } | |||||||||||||
| 230 | elsif ($ret == DECLINED || $ret == DONE) { | |||||||||||||
| 231 | return; | |||||||||||||
| 232 | } | |||||||||||||
| 233 | elsif ($ret == OK) { | |||||||||||||
| 234 | return 1; | |||||||||||||
| 235 | } | |||||||||||||
| 236 | else { | |||||||||||||
| 237 | $self->default_error_out($ret); | |||||||||||||
| 238 | } | |||||||||||||
| 239 | } | |||||||||||||
| 240 | ||||||||||||||
| 241 | sub hook_post_read_request { | |||||||||||||
| 242 | my $self = shift; | |||||||||||||
| 243 | $self->run_hooks('post_read_request', @_); | |||||||||||||
| 244 | } | |||||||||||||
| 245 | ||||||||||||||
| 246 | sub hook_post_read_request_end { | |||||||||||||
| 247 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 248 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 249 | if ($hd->request_method =~ /GET|HEAD/) { | |||||||||||||
| 250 | return $self->process_request; | |||||||||||||
| 251 | } | |||||||||||||
| 252 | return; | |||||||||||||
| 253 | } | |||||||||||||
| 254 | elsif ($ret == DONE) { | |||||||||||||
| 255 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 256 | } | |||||||||||||
| 257 | else { | |||||||||||||
| 258 | $self->default_error_out($ret); | |||||||||||||
| 259 | } | |||||||||||||
| 260 | } | |||||||||||||
| 261 | ||||||||||||||
| 262 | sub hook_uri_translation { | |||||||||||||
| 263 | my ($self, $hd, $uri) = @_; | |||||||||||||
| 264 | $self->run_hooks('uri_translation', $hd, $uri); | |||||||||||||
| 265 | } | |||||||||||||
| 266 | ||||||||||||||
| 267 | sub hook_uri_translation_end { | |||||||||||||
| 268 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 269 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 270 | return $self->run_hooks('mime_map', $hd, $hd->filename); | |||||||||||||
| 271 | } | |||||||||||||
| 272 | elsif ($ret == DONE) { | |||||||||||||
| 273 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 274 | } | |||||||||||||
| 275 | else { | |||||||||||||
| 276 | $self->default_error_out($ret); | |||||||||||||
| 277 | } | |||||||||||||
| 278 | } | |||||||||||||
| 279 | ||||||||||||||
| 280 | sub hook_mime_map_end { | |||||||||||||
| 281 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 282 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 283 | return $self->run_hooks('access_control', $hd); | |||||||||||||
| 284 | } | |||||||||||||
| 285 | elsif ($ret == DONE) { | |||||||||||||
| 286 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 287 | } | |||||||||||||
| 288 | else { | |||||||||||||
| 289 | $self->default_error_out($ret); | |||||||||||||
| 290 | } | |||||||||||||
| 291 | } | |||||||||||||
| 292 | ||||||||||||||
| 293 | sub hook_access_control_end { | |||||||||||||
| 294 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 295 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 296 | return $self->run_hooks('authentication', $hd); | |||||||||||||
| 297 | } | |||||||||||||
| 298 | elsif ($ret == DONE) { | |||||||||||||
| 299 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 300 | } | |||||||||||||
| 301 | else { | |||||||||||||
| 302 | $self->default_error_out($ret); | |||||||||||||
| 303 | } | |||||||||||||
| 304 | } | |||||||||||||
| 305 | ||||||||||||||
| 306 | sub hook_authentication_end { | |||||||||||||
| 307 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 308 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 309 | return $self->run_hooks('authorization', $hd); | |||||||||||||
| 310 | } | |||||||||||||
| 311 | elsif ($ret == DONE) { | |||||||||||||
| 312 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 313 | } | |||||||||||||
| 314 | else { | |||||||||||||
| 315 | $self->default_error_out($ret); | |||||||||||||
| 316 | } | |||||||||||||
| 317 | } | |||||||||||||
| 318 | ||||||||||||||
| 319 | sub hook_authorization_end { | |||||||||||||
| 320 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 321 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 322 | return $self->run_hooks('fixup', $hd); | |||||||||||||
| 323 | } | |||||||||||||
| 324 | elsif ($ret == DONE) { | |||||||||||||
| 325 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 326 | } | |||||||||||||
| 327 | else { | |||||||||||||
| 328 | $self->default_error_out($ret); | |||||||||||||
| 329 | } | |||||||||||||
| 330 | } | |||||||||||||
| 331 | ||||||||||||||
| 332 | sub hook_fixup_end { | |||||||||||||
| 333 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 334 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 335 | return $self->run_hooks( | |||||||||||||
| 336 | 'xmlresponse', | |||||||||||||
| 337 | AxKit2::Processor->new($self, $hd->filename), | |||||||||||||
| 338 | $hd); | |||||||||||||
| 339 | } | |||||||||||||
| 340 | elsif ($ret == DONE) { | |||||||||||||
| 341 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 342 | } | |||||||||||||
| 343 | else { | |||||||||||||
| 344 | $self->default_error_out($ret); | |||||||||||||
| 345 | } | |||||||||||||
| 346 | } | |||||||||||||
| 347 | ||||||||||||||
| 348 | sub hook_xmlresponse_end { | |||||||||||||
| 349 | my ($self, $ret, $out, $input, $hd) = @_; | |||||||||||||
| 350 | if ($ret == DECLINED) { | |||||||||||||
| 351 | return $self->run_hooks('response', $hd); | |||||||||||||
| 352 | } | |||||||||||||
| 353 | elsif ($ret == DONE) { | |||||||||||||
| 354 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 355 | } | |||||||||||||
| 356 | elsif ($ret == OK) { | |||||||||||||
| 357 | $out->output() if $out; | |||||||||||||
| 358 | $self->write(sub { $self->http_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 359 | } | |||||||||||||
| 360 | else { | |||||||||||||
| 361 | $self->default_error_out($ret); | |||||||||||||
| 362 | } | |||||||||||||
| 363 | } | |||||||||||||
| 364 | ||||||||||||||
| 365 | sub hook_response_end { | |||||||||||||
| 366 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
| 367 | if ($ret == DECLINED) { | |||||||||||||
| 368 | $self->default_error_out(NOT_FOUND); | |||||||||||||
| 369 | } | |||||||||||||
| 370 | elsif ($ret == OK || $ret == DONE) { | |||||||||||||
| 371 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 372 | } | |||||||||||||
| 373 | else { | |||||||||||||
| 374 | $self->default_error_out($ret); | |||||||||||||
| 375 | } | |||||||||||||
| 376 | ||||||||||||||
| 377 | } | |||||||||||||
| 378 | ||||||||||||||
| 379 | sub hook_response_sent { | |||||||||||||
| 380 | my $self = shift; | |||||||||||||
| 381 | $self->run_hooks('response_sent', @_); | |||||||||||||
| 382 | } | |||||||||||||
| 383 | ||||||||||||||
| 384 | sub hook_response_sent_end { | |||||||||||||
| 385 | my ($self, $ret, $out, $code) = @_; | |||||||||||||
| 386 | if ($ret == DONE) { | |||||||||||||
| 387 | $self->close("plugin decided not to keep connection open"); | |||||||||||||
| 388 | } | |||||||||||||
| 389 | elsif ($ret == DECLINED || $ret == OK) { | |||||||||||||
| 390 | return $self->http_response_sent; | |||||||||||||
| 391 | } | |||||||||||||
| 392 | else { | |||||||||||||
| 393 | $self->default_error_out($ret); | |||||||||||||
| 394 | } | |||||||||||||
| 395 | } | |||||||||||||
| 396 | ||||||||||||||
| 397 | sub hook_error { | |||||||||||||
| 398 | my $self = shift; | |||||||||||||
| 399 | $self->headers_out->code(SERVER_ERROR); | |||||||||||||
| 400 | $self->run_hooks('error', @_); | |||||||||||||
| 401 | } | |||||||||||||
| 402 | ||||||||||||||
| 403 | sub hook_error_end { | |||||||||||||
| 404 | my ($self, $ret) = @_; | |||||||||||||
| 405 | if ($ret == DECLINED) { | |||||||||||||
| 406 | $self->default_error_out(SERVER_ERROR); | |||||||||||||
| 407 | } | |||||||||||||
| 408 | elsif ($ret == OK || $ret == DONE) { | |||||||||||||
| 409 | # we assume some hook handled the error | |||||||||||||
| 410 | } | |||||||||||||
| 411 | else { | |||||||||||||
| 412 | $self->default_error_out($ret); | |||||||||||||
| 413 | } | |||||||||||||
| 414 | } | |||||||||||||
| 415 | ||||||||||||||
| 416 | # stolen shamelessly from httpd-2.2.2/modules/http/http_protocol.c | |||||||||||||
| 417 | sub default_error_out { | |||||||||||||
| 418 | my ($self, $code, $extras) = @_; | |||||||||||||
| 419 | $extras = '' unless defined $extras; | |||||||||||||
| 420 | ||||||||||||||
| 421 | $self->initialize_response; | |||||||||||||
| 422 | ||||||||||||||
| 423 | $self->headers_out->code($code); | |||||||||||||
| 424 | ||||||||||||||
| 425 | if ($code == NOT_MODIFIED) { | |||||||||||||
| 426 | $self->send_http_headers; | |||||||||||||
| 427 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
| 428 | # The 304 response MUST NOT contain a message-body | |||||||||||||
| 429 | return; | |||||||||||||
| 430 | } | |||||||||||||
| 431 | ||||||||||||||
| 432 | $self->headers_out->header('Content-Type', 'text/html'); | |||||||||||||
| 433 | $self->headers_out->header('Connection', 'close'); | |||||||||||||
| 434 | $self->send_http_headers; | |||||||||||||
| 435 | ||||||||||||||
| 436 | $self->write("\n" . | |||||||||||||
| 437 | "\n" . | |||||||||||||
| 438 | " |
|||||||||||||
| 439 | "\n" . | |||||||||||||
| 440 | "".$self->headers_out->http_code_english."\n" |
|||||||||||||
| 441 | ); | |||||||||||||
| 442 | ||||||||||||||
| 443 | if ($code == REDIRECT) { | |||||||||||||
| 444 | my $new_uri = $self->headers_out->header('Location') | |||||||||||||
| 445 | || die "No Location header set for REDIRECT"; | |||||||||||||
| 446 | $self->write('The document has moved 447 | xml_escape($new_uri) . "\">here. \n"); |
||||||||||||
| 448 | } | |||||||||||||
| 449 | elsif ($code == BAD_REQUEST) { | |||||||||||||
| 450 | $self->write(" Your browser sent a request that this server could not understand. |
|||||||||||||
| 451 | xml_escape($extras)."\n"); | |||||||||||||
| 452 | } | |||||||||||||
| 453 | elsif ($code == UNAUTHORIZED) { | |||||||||||||
| 454 | $self->write(" This server could not verify that you\n" . |
|||||||||||||
| 455 | "are authorized to access the document\n" . | |||||||||||||
| 456 | "requested. Either you supplied the wrong\n" . | |||||||||||||
| 457 | "credentials (e.g., bad password), or your\n" . | |||||||||||||
| 458 | "browser doesn't understand how to supply\n" . | |||||||||||||
| 459 | "the credentials required.\n"); | |||||||||||||
| 460 | } | |||||||||||||
| 461 | elsif ($code == FORBIDDEN) { | |||||||||||||
| 462 | $self->write(" You don't have permission to access " . |
|||||||||||||
| 463 | xml_escape($self->headers_in->uri) . | |||||||||||||
| 464 | "\non this server.\n"); | |||||||||||||
| 465 | } | |||||||||||||
| 466 | elsif ($code == NOT_FOUND) { | |||||||||||||
| 467 | $self->write(" The requested URL " . |
|||||||||||||
| 468 | xml_escape($self->headers_in->uri) . | |||||||||||||
| 469 | " was not found on this server.\n"); | |||||||||||||
| 470 | } | |||||||||||||
| 471 | elsif ($code == SERVICE_UNAVAILABLE) { | |||||||||||||
| 472 | $self->write(" The server is temporarily unable to service your\n" . |
|||||||||||||
| 473 | "request due to maintenance downtime or capacity\n" . | |||||||||||||
| 474 | "problems. Please try again later.\n"); | |||||||||||||
| 475 | } | |||||||||||||
| 476 | else { | |||||||||||||
| 477 | $self->write("The server encountered an internal error or \n" . | |||||||||||||
| 478 | "misconfiguration and was unable to complete \n" . | |||||||||||||
| 479 | "your request. \n" . |
|||||||||||||
| 480 | "More information about this error may be available\n" . | |||||||||||||
| 481 | "in the server error log. \n"); |
|||||||||||||
| 482 | } | |||||||||||||
| 483 | ||||||||||||||
| 484 | $self->write(< | |||||||||||||
| 485 | |
|||||||||||||
| 486 |