From 356378fbc98f70dc3125f01db949af9288df2976 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 11 Nov 2004 19:49:56 +0000 Subject: [PATCH] * modules/proxy/proxy_http.c (ap_proxy_http_process_response): Use the standard non-blocking-read/flush/blocking-read logic to ensure that buffered content is flushed to the client if the next read will block. PR: 19954 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@105751 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ modules/proxy/proxy_http.c | 44 ++++++++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index e0c9f2a692..565c389419 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.1.0-dev [Remove entries to the current 2.0 section below, when backported] + *) mod_proxy_http: Stream content better - always flush buffered data to + the client before blocking waiting for new data. PR 19954. + [Joe Orton] + *) mod_ssl: Add support for command-line option "-t -DDUMP_CERTS" which will dump the filenames of all configured SSL certificates to stdout. [Joe Orton] diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index f083971f1e..91b7875bf2 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -1022,15 +1022,41 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, * of the page into the brigade */ if (conf->error_override == 0 || ap_is_HTTP_SUCCESS(r->status)) { - /* read the body, pass it to the output filters */ + apr_read_type_e mode = APR_NONBLOCK_READ; int finish = FALSE; - while (ap_get_brigade(rp->input_filters, - bb, - AP_MODE_READBYTES, - APR_BLOCK_READ, - conf->io_buffer_size) == APR_SUCCESS) { + + do { apr_off_t readbytes; + apr_status_t rv; + + rv = ap_get_brigade(rp->input_filters, bb, + AP_MODE_READBYTES, mode, + conf->io_buffer_size); + + /* ap_get_brigade will return success with an empty brigade + * for a non-blocking read which would block: */ + if (APR_STATUS_IS_EAGAIN(rv) + || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) { + /* flush to the client and switch to blocking mode */ + e = apr_bucket_flush_create(c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); + if (ap_pass_brigade(r->output_filters, bb)) { + backend->close = 1; + break; + } + apr_brigade_cleanup(bb); + mode = APR_BLOCK_READ; + continue; + } + else if (rv != APR_SUCCESS) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, + "proxy: error reading response"); + break; + } + /* next time try a non-blocking read */ + mode = APR_NONBLOCK_READ; + apr_brigade_length(bb, 0, &readbytes); backend->worker->s->readed += readbytes; #if DEBUGGING @@ -1068,11 +1094,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, /* make sure we always clean up after ourselves */ apr_brigade_cleanup(bb); - /* if we are done, leave */ - if (TRUE == finish) { - break; - } - } + } while (!finish); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: end body send"); -- 2.50.1