1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-07 04:02:58 +03:00

mod_proxy: Handle ap_proxy_buckets_lifetime_transform() errors.

* modules/proxy/mod_proxy.h,modules/proxy/proxy_util.c:
  Add ap_proxy_fill_error_brigade() to factorize proxy error handling
  on the client connection side.

* modules/proxy/mod_proxy_{http,ajp,uwsgi}.c:
  Use ap_proxy_fill_error_brigade() where needed, including when an
  empty brigade is returned on the backend side or when calling
  ap_proxy_buckets_lifetime_transform fails.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1893595 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yann Ylavic
2021-09-24 11:25:42 +00:00
parent 074d55133a
commit b44b9b6b2a
7 changed files with 138 additions and 66 deletions

View File

@@ -1177,11 +1177,7 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
" Number of keepalives %i", backend->hostname,
backend->port, c->keepalives);
e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL,
r->pool, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
e = ap_bucket_eoc_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
ap_proxy_fill_error_brigade(r, HTTP_BAD_GATEWAY, bb, 1);
ap_pass_brigade(r->output_filters, bb);
/* Mark the backend connection for closing */
backend->close = 1;
@@ -1710,11 +1706,12 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
mode = APR_BLOCK_READ;
continue;
}
else if (rv == APR_EOF) {
if (rv == APR_EOF) {
backend->close = 1;
break;
}
else if (rv != APR_SUCCESS) {
if (rv != APR_SUCCESS || APR_BRIGADE_EMPTY(bb)) {
int error_status = HTTP_BAD_GATEWAY;
if (rv == APR_ENOSPC) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02475)
"Response chunk/line was too large to parse");
@@ -1723,10 +1720,15 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02476)
"Response Transfer-Encoding was not recognised");
}
else {
else if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110)
"Network error reading response");
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10293)
"Unexpected empty data reading response");
error_status = HTTP_INTERNAL_SERVER_ERROR;
}
/* In this case, we are in real trouble because
* our backend bailed on us. Given we're half way
@@ -1734,11 +1736,7 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
* disconnect the client too.
*/
apr_brigade_cleanup(bb);
e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL,
r->pool, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
e = ap_bucket_eoc_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
ap_proxy_fill_error_brigade(r, error_status, bb, 1);
ap_pass_brigade(r->output_filters, bb);
backend_broke = 1;
@@ -1762,13 +1760,28 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
"readbytes: %#x", readbytes);
}
#endif
/* sanity check */
if (APR_BRIGADE_EMPTY(bb)) {
break;
}
/* Switch the allocator lifetime of the buckets */
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
rv = ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
if (rv != APR_SUCCESS) {
/* Same, half way through a response, our only option is
* to notice the output filters and then disconnect the
* client and backend.
*/
if (!APR_BRIGADE_EMPTY(pass_bb)) {
/* Pass what we have still */
ap_pass_brigade(r->output_filters, pass_bb);
apr_brigade_cleanup(pass_bb);
}
ap_proxy_fill_error_brigade(r, HTTP_INTERNAL_SERVER_ERROR,
pass_bb, 1);
ap_pass_brigade(r->output_filters, pass_bb);
apr_brigade_cleanup(pass_bb);
backend_broke = 1;
backend->close = 1;
break;
}
/* found the last brigade? */
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) {