commit bdafe984565f146c376ee674b13fb42c77c8410a Author: Michael Osipov Date: 2019-08-05 12:39:28 +0200 BZ 63626: mod_proxy_http uses incorrect status codes for timed out upstream requests If a status is known to time out at some point, use HTTP_GATEWAY_TIME_OUT rather than HTTP_BAD_GATEWAY because we know that the connection has been established and the upstream server has received our request. diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 895b937088..18c5e0515f 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -1087,6 +1087,18 @@ PROXY_DECLARE(int) ap_proxy_connection_reusable(proxy_conn_rec *conn); PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r, apr_bucket_brigade *brigade); +/** + * Signal the upstream chain that the connection to the backend broke in the + * middle of the response. This is done by sending an error bucket with + * status supplied from error and an EOS bucket up the filter chain. + * @param r current request record of client request + * @param brigade The brigade that is sent through the output filter chain + * @param error The HTTP error code to put in the bucket + */ +PROXY_DECLARE(void) ap_proxy_backend_broke_ex(request_rec *r, + apr_bucket_brigade *brigade, + int error); + /** * Return a hash based on the passed string * @param str string to produce hash from diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index e94bf26d41..7999c78686 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1302,7 +1302,9 @@ int ap_proxy_http_process_response(proxy_http_req_t *req) " failed.", backend->hostname, backend->port); } - return ap_proxyerror(r, HTTP_BAD_GATEWAY, + return ap_proxyerror(r, APR_STATUS_IS_TIMEUP(rc) + ? HTTP_GATEWAY_TIME_OUT + : HTTP_BAD_GATEWAY, "Error reading from remote server"); } /* XXX: Is this a real headers length send from remote? */ @@ -1759,12 +1761,12 @@ int ap_proxy_http_process_response(proxy_http_req_t *req) } else if (rv != APR_SUCCESS) { /* In this case, we are in real trouble because - * our backend bailed on us. Pass along a 502 error + * our backend bailed on us. Pass along a 504 error * error bucket */ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110) "error reading response"); - ap_proxy_backend_broke(r, bb); + ap_proxy_backend_broke_ex(r, bb, HTTP_GATEWAY_TIME_OUT); ap_pass_brigade(r->output_filters, bb); backend_broke = 1; backend->close = 1; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index e7ffe33f21..12642ad297 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -3322,6 +3322,13 @@ int ap_proxy_lb_workers(void) PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r, apr_bucket_brigade *brigade) +{ + ap_proxy_backend_broke_ex(r, brigade, HTTP_BAD_GATEWAY); +} + +PROXY_DECLARE(void) ap_proxy_backend_broke_ex(request_rec *r, + apr_bucket_brigade *brigade, + int error) { apr_bucket *e; conn_rec *c = r->connection; @@ -3333,8 +3340,7 @@ PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r, */ if (r->main) r->main->no_cache = 1; - e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL, c->pool, - c->bucket_alloc); + e = ap_bucket_error_create(error, NULL, c->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(brigade, e); e = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(brigade, e);