Revision: 108 Author: matt Date: 2006-08-22 03:33:20 +0000 (Tue, 22 Aug 2006)
Log Message: ----------- Error code handling Modified Paths: -------------- trunk/lib/AxKit2/Client.pm trunk/lib/AxKit2/Connection.pm trunk/lib/AxKit2/Constants.pm trunk/lib/AxKit2/HTTPHeaders.pm trunk/plugins/uri_to_file Modified: trunk/lib/AxKit2/Client.pm =================================================================== --- trunk/lib/AxKit2/Client.pm 2006-08-21 22:56:09 UTC (rev 107) +++ trunk/lib/AxKit2/Client.pm 2006-08-22 03:33:20 UTC (rev 108) @@ -20,6 +20,8 @@ use AxKit2::Plugin; use AxKit2::Constants; +use AxKit2::Processor; +use AxKit2::Utils qw(xml_escape); our %PLUGINS; @@ -134,7 +136,8 @@ if ($@) { my $err = $@; $self->log(LOGERROR, "FATAL PLUGIN ERROR: $err"); - return SERVER_ERROR, $err; + $self->hook_error($err); + return DONE; } next unless @r; if ($r[0] == CONTINUATION) { @@ -167,10 +170,9 @@ my ($ret, $out) = @_; if ($ret == DECLINED || $ret == OK) { # success - $self->hook_pre_request; + $self->run_hooks('pre_request'); } else { - # TODO: Output some stuff... $self->close("connect hook closing"); return; } @@ -199,14 +201,14 @@ return; } if ($ret == DONE) { - $self->hook_uri_to_file(); + $self->run_hooks('uri_translation'); return; } elsif ($ret == OK) { return 1; } else { - # TODO: output error stuff? + $self->default_error_out($ret); } } @@ -216,15 +218,18 @@ } sub hook_post_read_request_end { - my ($self, $ret) = @_; + my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - if ($self->headers_in->request_method =~ /GET|HEAD/) { + if ($hd->request_method =~ /GET|HEAD/) { return $self->process_request; } return; } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: Handle errors or other conditions + $self->default_error_out($ret); } } @@ -236,146 +241,112 @@ sub hook_uri_translation_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - return $self->hook_mime_map($hd, $hd->filename); + return $self->run_hooks('mime_map', $hd, $hd->filename); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: output error stuff? - return; + $self->default_error_out($ret); } } -sub hook_mime_map { - my $self = shift; - $self->run_hooks('mime_map', @_); -} - sub hook_mime_map_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - return $self->hook_access_control($hd); + return $self->run_hooks('access_control', $hd); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: output error stuff? + $self->default_error_out($ret); } } -sub hook_access_control { - my $self = shift; - $self->run_hooks('access_control', @_); -} - sub hook_access_control_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - return $self->hook_authentication($hd); + return $self->run_hooks('authentication', $hd); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: output error stuff? + $self->default_error_out($ret); } } -sub hook_authentication { - my $self = shift; - $self->run_hooks('authentication', @_); -} - sub hook_authentication_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - return $self->hook_authorization($hd); + return $self->run_hooks('authorization', $hd); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: output error stuff? + $self->default_error_out($ret); } } -sub hook_authorization { - my $self = shift; - $self->run_hooks('authorization', @_); -} - sub hook_authorization_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - return $self->hook_fixup($hd); + return $self->run_hooks('fixup', $hd); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: output error stuff? + $self->default_error_out($ret); } } -sub hook_fixup { - my $self = shift; - $self->run_hooks('fixup', @_); -} - sub hook_fixup_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED || $ret == OK) { - return $self->hook_xmlresponse(AxKit2::Processor->new($self, $hd->filename), $hd); + return $self->run_hooks( + 'xmlresponse', + AxKit2::Processor->new($self, $hd->filename), + $hd); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } else { - # TODO: output error stuff? + $self->default_error_out($ret); } } -sub hook_xmlresponse { - my $self = shift; - $self->run_hooks('xmlresponse', @_); -} - sub hook_xmlresponse_end { my ($self, $ret, $out, $input, $hd) = @_; if ($ret == DECLINED) { - return $self->hook_response($hd); + return $self->run_hooks('response', $hd); } + elsif ($ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); + } elsif ($ret == OK) { $out->output($self) if $out; } - elsif ($ret == SERVER_ERROR) { - $self->hook_error($out); - } else { - # TODO: handle errors + $self->default_error_out($ret); } - - $self->write(sub { $self->http_response_sent() }); } -sub hook_response { - my $self = shift; - $self->run_hooks('response', @_); -} - sub hook_response_end { my ($self, $ret, $out, $hd) = @_; if ($ret == DECLINED) { - $self->headers_out->code(NOT_FOUND); - $self->headers_out->header('Content-Type' => 'text/html; charset=UTF-8'); - $self->send_http_headers; - my $uri = $self->headers_in->uri; - $self->write(<<EOT); -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> -<HTML><HEAD> -<TITLE>404 Not Found</TITLE> -</HEAD><BODY> -<H1>Not Found</H1> -The requested URL $uri was not found on this server.<P> -<HR> -</BODY></HTML> -EOT + $self->default_error_out(NOT_FOUND); } - elsif ($ret == OK) { - # do nothing... + elsif ($ret == OK || $ret == DONE) { + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); } - elsif ($ret == SERVER_ERROR) { - $self->hook_error($out); - } else { - # TODO: output error stuff? + $self->default_error_out($ret); } - $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); } sub hook_response_sent { @@ -392,7 +363,7 @@ return $self->http_response_sent; } else { - # TODO: errors? + $self->default_error_out($ret); } } @@ -404,27 +375,79 @@ sub hook_error_end { my ($self, $ret) = @_; - if ($ret != OK) { - $self->headers_out->header('Content-Type' => 'text/html; charset=UTF-8'); - $self->send_http_headers; - $self->write(<<EOT); -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> -<HTML><HEAD> -<TITLE>500 Internal Server Error</TITLE> -</HEAD><BODY> -<H1>Internal Server Error</H1> -The server encountered an internal error or -misconfiguration and was unable to complete -your request.<P> -More information about this error may be available -in the server error log.<P> -<HR> -</BODY></HTML> -EOT + if ($ret == DECLINED) { + $self->default_error_out(SERVER_ERROR); } - else { + elsif ($ret == OK || $ret == DONE) { # we assume some hook handled the error } + else { + $self->default_error_out($ret); + } } +# stolen shamelessly from httpd-2.2.2/modules/http/http_protocol.c +sub default_error_out { + my ($self, $code, $extras) = @_; + + $self->headers_out->code($code); + $self->headers_out->header('Content-Type', 'text/html'); + $self->send_http_headers; + + if ($code == NOT_MODIFIED) { + # The 304 response MUST NOT contain a message-body + return; + } + + $self->write("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" . + "<HTML><HEAD>\n" . + "<TITLE>$code ".$self->headers_out->http_code_english."</TITLE>\n" . + "</HEAD></BODY>\n" . + "<H1>".$self->headers_out->http_code_english."</H1>\n" + ); + + if ($code == REDIRECT) { + my $new_uri = $self->headers_out->header('Location') + || die "No Location header set for REDIRECT"; + $self->write('The document has moved <A HREF="' . + xml_escape($new_uri) . "\">here</A>.<P>\n"); + } + elsif ($code == BAD_REQUEST) { + $self->write("<p>Your browser sent a request that this server could not understand.<br />\n" . + xml_escape($extras)."</p>\n"); + } + elsif ($code == UNAUTHORIZED) { + $self->write("<p>This server could not verify that you\n" . + "are authorized to access the document\n" . + "requested. Either you supplied the wrong\n" . + "credentials (e.g., bad password), or your\n" . + "browser doesn't understand how to supply\n" . + "the credentials required.</p>\n"); + } + elsif ($code == FORBIDDEN) { + $self->write("<p>You don't have permission to access " . + xml_escape($self->headers_in->uri) . + "\non this server.</p>\n"); + } + elsif ($code == NOT_FOUND) { + $self->write("<p>The requested URL " . + xml_escape($self->headers_in->uri) . + " was not found on this server.</p>\n"); + } + else { + $self->write("The server encountered an internal error or \n" . + "misconfiguration and was unable to complete \n" . + "your request.<p>\n" . + "More information about this error may be available\n" . + "in the server error log.<p>\n"); + } + + $self->write(<<EOT); +<HR> +</BODY></HTML> +EOT + + $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); +} + 1; Modified: trunk/lib/AxKit2/Connection.pm =================================================================== --- trunk/lib/AxKit2/Connection.pm 2006-08-21 22:56:09 UTC (rev 107) +++ trunk/lib/AxKit2/Connection.pm 2006-08-22 03:33:20 UTC (rev 108) @@ -21,7 +21,6 @@ use AxKit2::HTTPHeaders; use AxKit2::Constants; -use AxKit2::Processor; use AxKit2::Utils qw(http_date); use fields qw( Modified: trunk/lib/AxKit2/Constants.pm =================================================================== --- trunk/lib/AxKit2/Constants.pm 2006-08-21 22:56:09 UTC (rev 107) +++ trunk/lib/AxKit2/Constants.pm 2006-08-22 03:33:20 UTC (rev 108) @@ -36,11 +36,17 @@ # return codes my %return_codes = ( OK => 200, + NO_CONTENT => 204, + PARTIAL_CONTENT => 206, + REDIRECT => 302, NOT_MODIFIED => 304, BAD_REQUEST => 400, + UNAUTHORIZED => 401, FORBIDDEN => 403, NOT_FOUND => 404, SERVER_ERROR => 500, + NOT_IMPLEMENTED => 501, + SERVICE_UNAVAILABLE => 503, DECLINED => 909, DONE => 910, CONTINUATION => 911, Modified: trunk/lib/AxKit2/HTTPHeaders.pm =================================================================== --- trunk/lib/AxKit2/HTTPHeaders.pm 2006-08-21 22:56:09 UTC (rev 107) +++ trunk/lib/AxKit2/HTTPHeaders.pm 2006-08-22 03:33:20 UTC (rev 108) @@ -49,6 +49,7 @@ 200 => 'OK', 204 => 'No Content', 206 => 'Partial Content', + 302 => 'Found', 304 => 'Not Modified', 400 => 'Bad request', 403 => 'Forbidden', Modified: trunk/plugins/uri_to_file =================================================================== --- trunk/plugins/uri_to_file 2006-08-21 22:56:09 UTC (rev 107) +++ trunk/plugins/uri_to_file 2006-08-22 03:33:20 UTC (rev 108) @@ -84,21 +84,8 @@ if ($original_uri !~ /\/$/) { # send redirect $self->log(LOGINFO, "redirect to $original_uri/$removed"); - $self->client->headers_out->code(302, "Found"); $self->client->headers_out->header('Location', "$original_uri/$removed"); - $self->client->headers_out->header('Content-Type', 'text/html'); - $self->client->send_http_headers; - $self->client->write(<<EOT); -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> -<HTML><HEAD> -<TITLE>302 Found</TITLE> -</HEAD><BODY> -<H1>Found</H1> -The document has moved <A HREF="$original_uri/$removed">here</A>.<P> -<HR> -</BODY></HTML> -EOT - return DONE; + return REDIRECT; } if (my $dirindex = $self->config->notes($self->plugin_name . '::dirindex')) { my $filepath = catfile($path, $dirindex);