From 90089065b62d05631f15e27c211a8504f90fbf96 Mon Sep 17 00:00:00 2001 From: Ruediger Pluem Date: Sun, 18 Dec 2005 22:09:05 +0000 Subject: [PATCH] * Move code for broken backend detection out of core filter into a new http protocol filter (ap_http_broken_backend_filter) that is only run in the proxy case. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@357519 13f79535-47bb-0310-9956-ffa450edef68 --- modules/http/http_core.c | 5 +++++ modules/http/http_filters.c | 23 +++++++++++++++++++++++ modules/http/mod_core.h | 5 +++++ server/core_filters.c | 23 +++++------------------ 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 14d8a1b598..b939967e6e 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -39,6 +39,7 @@ AP_DECLARE_DATA ap_filter_rec_t *ap_http_input_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_http_header_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_chunk_filter_handle; +AP_DECLARE_DATA ap_filter_rec_t *ap_broken_backend_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_byterange_filter_handle; static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy, @@ -242,6 +243,10 @@ static void register_hooks(apr_pool_t *p) ap_chunk_filter_handle = ap_register_output_filter("CHUNK", ap_http_chunk_filter, NULL, AP_FTYPE_TRANSCODE); + ap_broken_backend_filter_handle = + ap_register_output_filter("BROKEN_BACKEND", + ap_http_broken_backend_filter, + NULL, AP_FTYPE_PROTOCOL); ap_byterange_filter_handle = ap_register_output_filter("BYTERANGE", ap_byterange_filter, NULL, AP_FTYPE_PROTOCOL); diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c index 750fdbda46..9434ac1668 100644 --- a/modules/http/http_filters.c +++ b/modules/http/http_filters.c @@ -1055,6 +1055,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, */ ap_add_output_filter("CHUNK", NULL, r, r->connection); } + /* If we have a Proxy request, add the BROKEN_BACKEND filter now */ + if (r->proxyreq != PROXYREQ_NONE) + ap_add_output_filter("BROKEN_BACKEND", NULL, r, r->connection); /* Don't remove this filter until after we have added the CHUNK filter. * Otherwise, f->next won't be the CHUNK filter and thus the first @@ -1330,3 +1333,23 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, return bufsiz; } +apr_status_t ap_http_broken_backend_filter(ap_filter_t *f, + apr_bucket_brigade *b) +{ + request_rec *r = f->r; + apr_bucket *e; + + for (e = APR_BRIGADE_FIRST(b); + e != APR_BRIGADE_SENTINEL(b); + e = APR_BUCKET_NEXT(e)) + { + if (AP_BUCKET_IS_ERROR(e) + && (((ap_bucket_error *)(e->data))->status == HTTP_BAD_GATEWAY)) { + /* stream aborted and we have not ended it yet */ + r->connection->keepalive = AP_CONN_CLOSE; + } + } + + return ap_pass_brigade(f->next, b); +} + diff --git a/modules/http/mod_core.h b/modules/http/mod_core.h index 1f5c1d8c9a..c084a755ec 100644 --- a/modules/http/mod_core.h +++ b/modules/http/mod_core.h @@ -42,6 +42,7 @@ extern "C" { extern AP_DECLARE_DATA ap_filter_rec_t *ap_http_input_filter_handle; extern AP_DECLARE_DATA ap_filter_rec_t *ap_http_header_filter_handle; extern AP_DECLARE_DATA ap_filter_rec_t *ap_chunk_filter_handle; +extern AP_DECLARE_DATA ap_filter_rec_t *ap_broken_backend_filter_handle; extern AP_DECLARE_DATA ap_filter_rec_t *ap_byterange_filter_handle; /* @@ -54,6 +55,10 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, /* HTTP/1.1 chunked transfer encoding filter. */ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b); +/* Filter to close the connection to the client if backend broke */ +apr_status_t ap_http_broken_backend_filter(ap_filter_t *f, + apr_bucket_brigade *b); + char *ap_response_code_string(request_rec *r, int error_index); /** diff --git a/server/core_filters.c b/server/core_filters.c index 90f5d4bf7b..5f6ff31ec4 100644 --- a/server/core_filters.c +++ b/server/core_filters.c @@ -315,9 +315,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s, apr_size_t *bytes_written, conn_rec *c); -static void detect_error_bucket(apr_bucket *bucket, conn_rec *c); - -static void remove_empty_buckets(apr_bucket_brigade *bb, conn_rec *c); +static void remove_empty_buckets(apr_bucket_brigade *bb); static apr_status_t send_brigade_blocking(apr_socket_t *s, apr_bucket_brigade *bb, @@ -489,7 +487,7 @@ static void setaside_remaining_output(ap_filter_t *f, if (bb == NULL) { return; } - remove_empty_buckets(bb, c); + remove_empty_buckets(bb); if (!APR_BRIGADE_EMPTY(bb)) { c->data_in_output_filters = 1; if (make_a_copy) { @@ -528,7 +526,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s, struct iovec vec[MAX_IOVEC_TO_WRITE]; apr_size_t nvec = 0; - remove_empty_buckets(bb, c); + remove_empty_buckets(bb); for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb); @@ -598,26 +596,16 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s, } } - remove_empty_buckets(bb, c); + remove_empty_buckets(bb); return APR_SUCCESS; } -static void detect_error_bucket(apr_bucket *bucket, conn_rec *c) -{ - if (AP_BUCKET_IS_ERROR(bucket) - && (((ap_bucket_error *)(bucket->data))->status == HTTP_BAD_GATEWAY)) { - /* stream aborted and we have not ended it yet */ - c->keepalive = AP_CONN_CLOSE; - } -} - -static void remove_empty_buckets(apr_bucket_brigade *bb, conn_rec *c) +static void remove_empty_buckets(apr_bucket_brigade *bb) { apr_bucket *bucket; while (((bucket = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) && (APR_BUCKET_IS_METADATA(bucket) || (bucket->length == 0))) { - detect_error_bucket(bucket, c); APR_BUCKET_REMOVE(bucket); apr_bucket_destroy(bucket); } @@ -690,7 +678,6 @@ static apr_status_t writev_nonblocking(apr_socket_t *s, for (i = offset; i < nvec; ) { apr_bucket *bucket = APR_BRIGADE_FIRST(bb); if (APR_BUCKET_IS_METADATA(bucket)) { - detect_error_bucket(bucket, c); APR_BUCKET_REMOVE(bucket); apr_bucket_destroy(bucket); } -- 2.40.0