From: Ryan Bloom Date: Sat, 27 Jan 2001 07:13:39 +0000 (+0000) Subject: filters can now report an HTTP error to the server. This is done X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28e92fac2cfe4057a08d2da887a26cc1831f3cdd;p=apache 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. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87863 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 8c783c18fb..bb0d80146b 100644 --- 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 diff --git a/include/http_protocol.h b/include/http_protocol.h index 578e03d170..09985a185b 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -59,9 +59,11 @@ #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 diff --git a/include/util_filter.h b/include/util_filter.h index e01b04a264..e340bd70c9 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -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 * diff --git a/modules/http/config.m4 b/modules/http/config.m4 index 4a5c9b06e8..6c646533c1 100644 --- a/modules/http/config.m4 +++ b/modules/http/config.m4 @@ -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) diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 4262c0e2e3..29da4704d7 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -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) diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 5c4c5b1dd2..c6c1ddc825 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -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; diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 28807e59db..a98bae9356 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -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; }