Return-Path: X-Original-To: apmail-httpd-cvs-archive@www.apache.org Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 355AA18EE7 for ; Wed, 20 Jan 2016 22:13:05 +0000 (UTC) Received: (qmail 11208 invoked by uid 500); 20 Jan 2016 22:13:05 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 11140 invoked by uid 500); 20 Jan 2016 22:13:05 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 11131 invoked by uid 99); 20 Jan 2016 22:13:05 -0000 Received: from Unknown (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 20 Jan 2016 22:13:05 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 9D2FE1A0761 for ; Wed, 20 Jan 2016 22:13:04 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.246 X-Spam-Level: * X-Spam-Status: No, score=1.246 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.554] autolearn=disabled Received: from mx1-us-west.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id LuSSywpSaM1q for ; Wed, 20 Jan 2016 22:13:03 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-us-west.apache.org (ASF Mail Server at mx1-us-west.apache.org) with ESMTP id 09E4320D3F for ; Wed, 20 Jan 2016 22:13:03 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 89CAFE0423 for ; Wed, 20 Jan 2016 22:13:02 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 613CB3A0185 for ; Wed, 20 Jan 2016 22:13:02 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1725822 - in /httpd/httpd/trunk/modules/proxy: mod_proxy.c mod_proxy_hcheck.c Date: Wed, 20 Jan 2016 22:13:02 -0000 To: cvs@httpd.apache.org From: jim@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20160120221302.613CB3A0185@svn01-us-west.apache.org> Author: jim Date: Wed Jan 20 22:13:02 2016 New Revision: 1725822 URL: http://svn.apache.org/viewvc?rev=1725822&view=rev Log: With the updated ap_expr, we can now check for the returned response body, stored in kept_body Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.c httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy.c?rev=1725822&r1=1725821&r2=1725822&view=diff ============================================================================== --- httpd/httpd/trunk/modules/proxy/mod_proxy.c (original) +++ httpd/httpd/trunk/modules/proxy/mod_proxy.c Wed Jan 20 22:13:02 2016 @@ -48,7 +48,7 @@ hcmethods_t hcmethods[] = { {TCP, "TCP", 1}, {OPTIONS, "OPTIONS", 1}, {HEAD, "HEAD", 1}, - {GET, "GET", 0}, + {GET, "GET", 1}, {CPING, "CPING", 0}, {PROVIDER, "PROVIDER", 0}, {EOT, NULL, 1} Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c?rev=1725822&r1=1725821&r2=1725822&view=diff ============================================================================== --- httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c (original) +++ httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c Wed Jan 20 22:13:02 2016 @@ -284,16 +284,22 @@ static const char *set_hc_template(cmd_p return NULL; } -static request_rec *create_request_rec(apr_pool_t *p1, conn_rec *conn) +/* + * Create a dummy request rec, simply so we can use ap_expr. + * Use our short-lived poll for bucket_alloc + */ +static request_rec *create_request_rec(apr_pool_t *p1, conn_rec *conn, const char *method) { request_rec *r; apr_pool_t *p; - + apr_bucket_alloc_t *ba; apr_pool_create(&p, p1); apr_pool_tag(p, "request"); r = apr_pcalloc(p, sizeof(request_rec)); + ba = apr_bucket_alloc_create(p); r->pool = p; r->connection = conn; + r->connection->bucket_alloc = ba; r->server = conn->base_server; r->user = NULL; @@ -309,6 +315,7 @@ static request_rec *create_request_rec(a r->trailers_out = apr_table_make(r->pool, 5); r->notes = apr_table_make(r->pool, 5); + r->kept_body = apr_brigade_create(r->pool, r->connection->bucket_alloc); r->request_config = ap_create_request_config(r->pool); /* Must be set before we run create request hook */ @@ -324,7 +331,7 @@ static request_rec *create_request_rec(a r->read_body = REQUEST_NO_BODY; r->status = HTTP_OK; /* Until further notice */ - r->header_only = 0; + r->header_only = 1; r->the_request = NULL; /* Begin by presuming any module can make its own path_info assumptions, @@ -337,11 +344,11 @@ static request_rec *create_request_rec(a /* Time to populate r with the data we have. */ - r->method = "OPTIONS"; + r->method = method; /* Provide quick information about the request method as soon as known */ r->method_number = ap_method_number_of(r->method); - if (r->method_number == M_GET && r->method[0] == 'H') { - r->header_only = 1; + if (r->method_number == M_GET && r->method[0] == 'G') { + r->header_only = 0; } r->protocol = (char*)"HTTP/1.1"; @@ -576,13 +583,60 @@ static int hc_read_headers(sctx_t *ctx, return OK; } +static int hc_read_body (sctx_t *ctx, request_rec *r) +{ + apr_status_t rv = APR_SUCCESS; + apr_bucket_brigade *bb; + int seen_eos = 0; + + bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); + do { + apr_bucket *bucket, *cpy; + apr_size_t len = HUGE_STRING_LEN; + + rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_READBYTES, + APR_BLOCK_READ, len); + + if (rv != APR_SUCCESS) { + if (APR_STATUS_IS_TIMEUP(rv) || APR_STATUS_IS_EOF(rv)) { + rv = APR_SUCCESS; + break; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ctx->s, APLOGNO() + "Error reading response body"); + break; + } + + for (bucket = APR_BRIGADE_FIRST(bb); + bucket != APR_BRIGADE_SENTINEL(bb); + bucket = APR_BUCKET_NEXT(bucket)) + { + if (APR_BUCKET_IS_EOS(bucket)) { + seen_eos = 1; + break; + } + if (APR_BUCKET_IS_FLUSH(bucket)) { + continue; + } + rv = apr_bucket_copy(bucket, &cpy); + if (rv != APR_SUCCESS) { + break; + } + APR_BRIGADE_INSERT_TAIL(r->kept_body, cpy); + } + apr_brigade_cleanup(bb); + } + while (!seen_eos); + return (rv == APR_SUCCESS ? OK : !OK); +} + /* - * Send the OPTIONS or HEAD HTTP request to the backend + * Send the HTTP OPTIONS, HEAD or GET request to the backend * server associated w/ worker. If we have Conditions, * then apply those to the resulting response, otherwise * any status code 2xx or 3xx is considered "passing" */ -static apr_status_t hc_check_headers(sctx_t *ctx, apr_pool_t *p, proxy_worker *worker) +static apr_status_t hc_check_http(sctx_t *ctx, apr_pool_t *p, proxy_worker *worker) { int status; proxy_conn_rec *backend = NULL; @@ -591,6 +645,7 @@ static apr_status_t hc_check_headers(sct request_rec *r; wctx_t *wctx; hc_condition_t *cond; + const char *method; hc = hc_get_hcworker(ctx, worker, p); wctx = (wctx_t *)hc->context; @@ -611,20 +666,34 @@ static apr_status_t hc_check_headers(sct case OPTIONS: if (!wctx->req) { wctx->req = apr_psprintf(ctx->p, - "OPTIONS * HTTP/1.1\r\nHost: %s:%d\r\n\r\n", + "OPTIONS * HTTP/1.0\r\nHost: %s:%d\r\n\r\n", hc->s->hostname, (int)hc->s->port); } + method = "OPTIONS"; break; case HEAD: if (!wctx->req) { wctx->req = apr_psprintf(ctx->p, - "HEAD %s%s%s HTTP/1.1\r\nHost: %s:%d\r\n\r\n", + "HEAD %s%s%s HTTP/1.0\r\nHost: %s:%d\r\n\r\n", + (wctx->path ? wctx->path : ""), + (wctx->path && *hc->s->hcuri ? "/" : "" ), + (*hc->s->hcuri ? hc->s->hcuri : ""), + hc->s->hostname, (int)hc->s->port); + } + method = "HEAD"; + break; + + case GET: + if (!wctx->req) { + wctx->req = apr_psprintf(ctx->p, + "GET %s%s%s HTTP/1.0\r\nHost: %s:%d\r\n\r\n", (wctx->path ? wctx->path : ""), (wctx->path && *hc->s->hcuri ? "/" : "" ), (*hc->s->hcuri ? hc->s->hcuri : ""), hc->s->hostname, (int)hc->s->port); } + method = "GET"; break; default: @@ -634,11 +703,15 @@ static apr_status_t hc_check_headers(sct hc_send(ctx, p, wctx->req, backend); - r = create_request_rec(p, backend->connection); - r->pool = p; + r = create_request_rec(p, backend->connection, method); if ((status = hc_read_headers(ctx, r)) != OK) { return backend_cleanup("HCOH", backend, ctx->s, status); } + if (hc->s->method == GET) { + if ((status = hc_read_body(ctx, r)) != OK) { + return backend_cleanup("HCOH", backend, ctx->s, status); + } + } if (*worker->s->hcexpr && (cond = (hc_condition_t *)apr_table_get(ctx->conditions, worker->s->hcexpr)) != NULL) { @@ -680,7 +753,8 @@ static void hc_check(sctx_t *ctx, apr_po case OPTIONS: case HEAD: - rv = hc_check_headers(ctx, p, worker); + case GET: + rv = hc_check_http(ctx, p, worker); break; default: