diff options
Diffstat (limited to 'modules/proxy/mod_proxy_http.c')
| -rw-r--r-- | modules/proxy/mod_proxy_http.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 34015263..7e4767f9 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1369,6 +1369,10 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, {"Keep-Alive", "Proxy-Authenticate", "TE", "Trailer", "Upgrade", NULL}; int i; const char *te = NULL; + int original_status = r->status; + int proxy_status = OK; + const char *original_status_line = r->status_line; + const char *proxy_status_line = NULL; bb = apr_brigade_create(p, c->bucket_alloc); pass_bb = apr_brigade_create(p, c->bucket_alloc); @@ -1482,7 +1486,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, keepchar = buffer[12]; buffer[12] = '\0'; - r->status = atoi(&buffer[9]); + proxy_status = atoi(&buffer[9]); if (keepchar != '\0') { buffer[12] = keepchar; @@ -1493,8 +1497,13 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, buffer[12] = ' '; buffer[13] = '\0'; } - r->status_line = apr_pstrdup(p, &buffer[9]); + proxy_status_line = apr_pstrdup(p, &buffer[9]); + /* The status out of the front is the same as the status coming in + * from the back, until further notice. + */ + r->status = proxy_status; + r->status_line = proxy_status_line; /* read the headers. */ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers*/ @@ -1570,7 +1579,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, if ((buf = apr_table_get(r->headers_out, "Content-Type"))) { ap_set_content_type(r, apr_pstrdup(p, buf)); } - if (!ap_is_HTTP_INFO(r->status)) { + if (!ap_is_HTTP_INFO(proxy_status)) { ap_proxy_pre_http_request(origin, rp); } @@ -1621,7 +1630,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, backend->close += 1; } - if (ap_is_HTTP_INFO(r->status)) { + if (ap_is_HTTP_INFO(proxy_status)) { interim_response++; } else { @@ -1660,7 +1669,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, * ProxyPassReverse/etc from here to ap_proxy_read_headers */ - if ((r->status == 401) && (conf->error_override)) { + if ((proxy_status == 401) && (conf->error_override)) { const char *buf; const char *wa = "WWW-Authenticate"; if ((buf = apr_table_get(r->headers_out, wa))) { @@ -1700,8 +1709,8 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, /* send body - but only if a body is expected */ if ((!r->header_only) && /* not HEAD request */ !interim_response && /* not any 1xx response */ - (r->status != HTTP_NO_CONTENT) && /* not 204 */ - (r->status != HTTP_NOT_MODIFIED)) { /* not 304 */ + (proxy_status != HTTP_NO_CONTENT) && /* not 204 */ + (proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */ /* We need to copy the output headers and treat them as input * headers as well. BUT, we need to do this before we remove @@ -1727,11 +1736,22 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, * if we are overriding the errors, we can't put the content * of the page into the brigade */ - if (!conf->error_override || !ap_is_HTTP_ERROR(r->status)) { + if (!conf->error_override || !ap_is_HTTP_ERROR(proxy_status)) { /* read the body, pass it to the output filters */ apr_read_type_e mode = APR_NONBLOCK_READ; int finish = FALSE; + /* Handle the case where the error document is itself reverse + * proxied and was successful. We must maintain any previous + * error status so that an underlying error (eg HTTP_NOT_FOUND) + * doesn't become an HTTP_OK. + */ + if (conf->error_override && !ap_is_HTTP_ERROR(proxy_status) + && ap_is_HTTP_ERROR(original_status)) { + r->status = original_status; + r->status_line = original_status_line; + } + do { apr_off_t readbytes; apr_status_t rv; @@ -1848,25 +1868,27 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, if (conf->error_override) { /* the code above this checks for 'OK' which is what the hook expects */ - if (!ap_is_HTTP_ERROR(r->status)) + if (!ap_is_HTTP_ERROR(proxy_status)) { return OK; + } else { /* clear r->status for override error, otherwise ErrorDocument * thinks that this is a recursive error, and doesn't find the * custom error page */ - int status = r->status; r->status = HTTP_OK; /* Discard body, if one is expected */ if (!r->header_only && /* not HEAD request */ - (status != HTTP_NO_CONTENT) && /* not 204 */ - (status != HTTP_NOT_MODIFIED)) { /* not 304 */ - ap_discard_request_body(rp); - } - return status; + (proxy_status != HTTP_NO_CONTENT) && /* not 204 */ + (proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */ + ap_discard_request_body(rp); + } + return proxy_status; } - } else + } + else { return OK; + } } static @@ -1974,10 +1996,7 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker, /* Step Two: Make the Connection */ if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) { - if (r->proxyreq == PROXYREQ_PROXY) - status = HTTP_NOT_FOUND; - else - status = HTTP_SERVICE_UNAVAILABLE; + status = HTTP_SERVICE_UNAVAILABLE; goto cleanup; } |
