You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axkit-dev@xml.apache.org by ma...@sergeant.org on 2006/08/22 05:33:49 UTC

[SVN] [108] Error code handling

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);