]> granicus.if.org Git - apache/commitdiff
filters can now report an HTTP error to the server. This is done
authorRyan Bloom <rbb@apache.org>
Sat, 27 Jan 2001 07:13:39 +0000 (07:13 +0000)
committerRyan Bloom <rbb@apache.org>
Sat, 27 Jan 2001 07:13:39 +0000 (07:13 +0000)
by sending a brigade where the first bucket is an error_bucket.
This bucket is a simple bucket that stores an HTTP error and
a string.  Currently the string is not used, but it may be needed
to output an error log.  The http_header_filter will find this
bucket, and output the error text, and then return
AP_FILTER_ERROR, which informs the server that the error web page
has already been sent.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87863 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/http_protocol.h
include/util_filter.h
modules/http/config.m4
modules/http/http_core.c
modules/http/http_protocol.c
modules/http/http_request.c

diff --git a/CHANGES b/CHANGES
index 8c783c18fbf1749e526f73819767ec01bd93399d..bb0d80146bf71a7cea7be4e9fc6c406e5299fb3d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,14 @@
 Changes with Apache 2.0b1
 
+  *) filters can now report an HTTP error to the server.  This is done
+     by sending a brigade where the first bucket is an error_bucket.
+     This bucket is a simple bucket that stores an HTTP error and
+     a string.  Currently the string is not used, but it may be needed
+     to output an error log.  The http_header_filter will find this
+     bucket, and output the error text, and then return 
+     AP_FILTER_ERROR, which informs the server that the error web page
+     has already been sent.  [Ryan Bloom]
+
   *) If we get an error, then we should remove all filters except for
      those critical to serving a web page.  This fixes a bug, where
      error pages were going through the byterange filter, even though
index 578e03d170740402336bd19d7ca74051f3632be1..09985a185b1860f89925edccbe2ffdd7baede4b5 100644 (file)
 #ifndef APACHE_HTTP_PROTOCOL_H
 #define APACHE_HTTP_PROTOCOL_H
 
+#include "httpd.h"
 #include "apr_hooks.h"
 #include "apr_portable.h"
 #include "apr_mmap.h"
+#include "apr_buckets.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -550,6 +552,46 @@ AP_DECLARE_HOOK(const char *,http_method,(const request_rec *))
  */
 AP_DECLARE_HOOK(apr_port_t,default_port,(const request_rec *))
 
+typedef struct ap_bucket_error ap_bucket_error;
+/**
+ * A bucket referring to an HTTP error
+ * This bucket can be passed down the filter stack to indicate that an
+ * HTTP error occurred while running a filter.  In order for this bucket
+ * to be used successfully, it MUST be sent as the first bucket in the
+ * first brigade to be sent from a given filter.
+ */
+struct ap_bucket_error {
+    /** The start of the data actually allocated.  This should never be
+     * modified, it is only used to free the bucket.
+     */
+    char    *start;
+};
+
+extern const apr_bucket_type_t ap_bucket_type_error;
+
+/**
+ * Make the bucket passed in an error bucket
+ * @param b The bucket to make into an error bucket
+ * @param error The HTTP error code to put in the bucket. 
+ * @param buf An optional error string to put in the bucket.
+ * @param p A pool to allocate out of.
+ * @return The new bucket, or NULL if allocation failed
+ * @deffunc apr_bucket *ap_bucket_make_error(apr_bucket *b, int error, const char *buf, apr_pool_t *p)
+ */
+AP_DECLARE(apr_bucket *) ap_bucket_make_error(apr_bucket *b, int error,
+                const char *buf, apr_pool_t *p);
+
+/**
+ * Create a bucket referring to an HTTP error.
+ * @param error The HTTP error code to put in the bucket. 
+ * @param buf An optional error string to put in the bucket.
+ * @param p A pool to allocate out of.
+ * @return The new bucket, or NULL if allocation failed
+ * @deffunc apr_bucket *ap_bucket_create_error(int error, const char *buf, apr_pool_t *p)
+ */
+AP_DECLARE(apr_bucket *) ap_bucket_create_error(int error,
+                const char *buf, apr_pool_t *p);
+
 #ifdef __cplusplus
 }
 #endif
index e01b04a264a26956d70a25af03e7bfcb0c00765e..e340bd70c9a604a7db3e06b9bc61bb03973114cb 100644 (file)
@@ -73,6 +73,7 @@ extern "C" {
 
 #define AP_NOBODY_WROTE         -1
 #define AP_NOBODY_READ          -2
+#define AP_FILTER_ERROR         -3
 
 /* ap_input_mode_t - input filtering modes 
  * 
index 4a5c9b06e86350e289b6e5c8311c49433b68dfef..6c646533c1310c27cc877f13e3b692685c6dceb6 100644 (file)
@@ -2,7 +2,7 @@ dnl modules enabled in this directory by default
 
 APACHE_MODPATH_INIT(http)
 
-http_objects="http_core.lo http_protocol.lo http_request.lo"
+http_objects="http_core.lo http_protocol.lo http_request.lo error_bucket.lo"
 
 APACHE_MODULE(core, HTTP protocol handling, $http_objects, , yes)
 APACHE_MODULE(mime, mapping of file-extension to MIME, , , yes)
index 4262c0e2e3396be43162bf036b8229c4a396c94f..29da4704d7188f0b727d1fe5429e487d5f19df2d 100644 (file)
@@ -3516,6 +3516,7 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
 static void core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
 {
     apr_init_bucket_types(pconf);
+    apr_insert_bucket_type(&ap_bucket_type_error);
 }
 
 static void core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
index 5c4c5b1dd204855717e8637c08faef7cfdc0eea3..c6c1ddc8256fb86c9e0bceb0627853b4e121a14d 100644 (file)
@@ -2466,6 +2466,14 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, apr_b
         return OK;
     }
 
+    if (APR_BRIGADE_FIRST(b)->type == &ap_bucket_type_error) {
+        const char *str;
+        apr_size_t length;
+        apr_bucket_read(APR_BRIGADE_FIRST(b), &str, &length, APR_NONBLOCK_READ);
+        ap_die(atoi(ap_getword_white(r->pool, &str)), r);
+        return AP_FILTER_ERROR;
+    }
+
     if (r->assbackwards) {
         r->bytes_sent = 0;
         r->sent_bodyct = 1;
index 28807e59db4da8518f22039cb75fe50ac89362fd..a98bae93568cdcae699589f8b324076201a5300d 100644 (file)
@@ -1351,7 +1351,7 @@ static void process_request_internal(request_rec *r)
      */
     ap_run_insert_filter(r);
 
-    if ((access_status = ap_invoke_handler(r)) != 0) {
+    if ((access_status = ap_invoke_handler(r)) != 0 && access_status != -3) {
         ap_die(access_status, r);
         return;
     }