Commit bb83bab1 authored by Ruediger Pluem's avatar Ruediger Pluem
Browse files

* 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
parent 06852d0f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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);
+23 −0
Original line number Diff line number Diff line
@@ -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);
}
+5 −0
Original line number Diff line number Diff line
@@ -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);

/**
+5 −18
Original line number Diff line number Diff line
@@ -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);
                }