diff --git a/CHANGES b/CHANGES index ceca74b249..86c250e53c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_proxy_fcgi: Add the support for mod_proxy's flushpackets and flushwait + parameters. [Luca Toscano, Ruediger Pluem, Yann Ylavic] + *) mod_proxy_wstunnel: Fix detection of unresponded request which could have led to spurious HTTP 502 error messages sent on upgrade connections. PR 61283. [Yann Ylavic] diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml index 746436f18c..a97abc36d9 100644 --- a/docs/manual/mod/mod_proxy.xml +++ b/docs/manual/mod/mod_proxy.xml @@ -1089,7 +1089,7 @@ ProxyPass "/example" "http://backend.example.com" max=20 ttl=120 retry=300 only when needed; 'on' means after each chunk is sent; and 'auto' means poll/wait for a period of time and flush if no input has been received for 'flushwait' milliseconds. - Currently, this is in effect only for AJP. + Currently, this is in effect only for mod_proxy_ajp and mod_proxy_fcgi. flushwait 10 diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c index 41292e8726..019f4a9335 100644 --- a/modules/proxy/mod_proxy_fcgi.c +++ b/modules/proxy/mod_proxy_fcgi.c @@ -532,6 +532,8 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf, ap_fcgi_header header; unsigned char farray[AP_FCGI_HEADER_LEN]; apr_pollfd_t pfd; + apr_pollfd_t *flushpoll; + apr_int32_t flushpoll_fd; int header_state = HDR_STATE_READING_HEADERS; char stack_iobuf[AP_IOBUFSIZE]; apr_size_t iobuf_size = AP_IOBUFSIZE; @@ -548,6 +550,13 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf, pfd.p = r->pool; pfd.reqevents = APR_POLLIN | APR_POLLOUT; + if (conn->worker->s->flush_packets == flush_auto) { + flushpoll = apr_pcalloc(r->pool, sizeof(apr_pollfd_t)); + flushpoll->reqevents = APR_POLLIN; + flushpoll->desc_type = APR_POLL_SOCKET; + flushpoll->desc.s = conn->sock; + } + ib = apr_brigade_create(r->pool, c->bucket_alloc); ob = apr_brigade_create(r->pool, c->bucket_alloc); @@ -876,6 +885,19 @@ recv_again: break; } } + + if ((conn->worker->s->flush_packets == flush_on) || + ((conn->worker->s->flush_packets == flush_auto) && + (apr_poll(flushpoll, 1, &flushpoll_fd, + conn->worker->s->flush_wait) == APR_TIMEUP))) { + apr_bucket* flush_b = apr_bucket_flush_create(r->connection->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(ob, flush_b); + rv = ap_pass_brigade(r->output_filters, ob); + if (rv != APR_SUCCESS) { + *err = "passing headers brigade to output filters"; + break; + } + } } }