summaryrefslogtreecommitdiff
path: root/modules/proxy/proxy_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/proxy/proxy_http.c')
-rw-r--r--modules/proxy/proxy_http.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c
index 214967ebaf..754b809bef 100644
--- a/modules/proxy/proxy_http.c
+++ b/modules/proxy/proxy_http.c
@@ -75,6 +75,10 @@ typedef struct {
int close;
} proxy_http_conn_t;
+static apr_status_t ap_proxy_http_cleanup(request_rec *r,
+ proxy_http_conn_t *p_conn,
+ proxy_conn_rec *backend);
+
/*
* Canonicalise http-like URLs.
* scheme is the scheme for the URL
@@ -813,17 +817,19 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
"proxy: start body send");
/*
- * if we are overriding the errors, we cant put the content of the
- * page into the brigade
+ * if we are overriding the errors, we can't put the content
+ * of the page into the brigade
*/
if ( (conf->error_override ==0) || r->status < 400 ) {
- /* read the body, pass it to the output filters */
+
+ /* read the body, pass it to the output filters */
apr_bucket *e;
+ int finish = FALSE;
while (ap_get_brigade(rp->input_filters,
bb,
AP_MODE_READBYTES,
APR_BLOCK_READ,
- AP_IOBUFSIZE) == APR_SUCCESS) {
+ conf->io_buffer_size) == APR_SUCCESS) {
#if DEBUGGING
{
apr_off_t readbytes;
@@ -833,21 +839,44 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
getpid(), readbytes);
}
#endif
+ /* sanity check */
if (APR_BRIGADE_EMPTY(bb)) {
+ apr_brigade_cleanup(bb);
break;
}
+
+ /* found the last brigade? */
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- ap_pass_brigade(r->output_filters, bb);
- break;
+ /* if this is the last brigade, cleanup the
+ * backend connection first to prevent the
+ * backend server from hanging around waiting
+ * for a slow client to eat these bytes
+ */
+ ap_proxy_http_cleanup(r, p_conn, backend);
+ /* signal that we must leave */
+ finish = TRUE;
}
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
+
+ /* if no EOS yet, then we must flush */
+ if (FALSE == finish) {
+ e = apr_bucket_flush_create();
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+
+ /* try send what we read */
if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
/* Ack! Phbtt! Die! User aborted! */
p_conn->close = 1; /* this causes socket close below */
- break;
+ finish = TRUE;
}
+
+ /* make sure we always clean up after ourselves */
apr_brigade_cleanup(bb);
+
+ /* if we are done, leave */
+ if (TRUE == finish) {
+ break;
+ }
}
}
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
@@ -886,8 +915,11 @@ apr_status_t ap_proxy_http_cleanup(request_rec *r, proxy_http_conn_t *p_conn,
* we close the socket, otherwise we leave it open for KeepAlive support
*/
if (p_conn->close || (r->proto_num < HTTP_VERSION(1,1))) {
- apr_socket_close(p_conn->sock);
- backend->connection = NULL;
+ if (p_conn->sock) {
+ apr_socket_close(p_conn->sock);
+ p_conn->sock = NULL;
+ backend->connection = NULL;
+ }
}
return OK;
}