You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2021/01/16 14:22:41 UTC
svn commit: r1885575 - in /httpd/httpd/branches/2.4.x: ./ docs/manual/mod/
include/ modules/proxy/
Author: minfrin
Date: Sat Jan 16 14:22:41 2021
New Revision: 1885575
URL: http://svn.apache.org/viewvc?rev=1885575&view=rev
Log:
Backport 2.4:
*) mod_proxy_http: individual status codes for ProxyErrorOverride. BZ 63628
trunk patch: https://svn.apache.org/r1754974
https://svn.apache.org/r1754975
https://svn.apache.org/r1876404
https://svn.apache.org/r1877696
https://svn.apache.org/r1877697
https://svn.apache.org/r1877728
2.4.x patch: http://people.apache.org/~ylavic/patches/2.4.x-mod_proxy_http-override-3on5.patch
https://github.com/apache/httpd/pull/157
+1: ylavic, covener, minfrin
ylavic: Besides ProxyErrorOverride individual status codes, merging now
the non-functional changes in ap_proxy_http_process_response()
around ProxyErrorOverride code helps reducing conflicts with the
following commits, and with trunk/2.4 alignment still.
Modified:
httpd/httpd/branches/2.4.x/CHANGES
httpd/httpd/branches/2.4.x/STATUS
httpd/httpd/branches/2.4.x/docs/manual/mod/mod_proxy.xml
httpd/httpd/branches/2.4.x/include/ap_mmn.h
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.h
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_fcgi.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_uwsgi.c
httpd/httpd/branches/2.4.x/modules/proxy/proxy_util.c
Modified: httpd/httpd/branches/2.4.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Sat Jan 16 14:22:41 2021
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes with Apache 2.4.47
+ *) mod_proxy: Allow ProxyErrorOverride to be restricted to specific status
+ codes. PR63628. [Martin Drößler <mail martindroessler.de>]
+
*) core: add ReadBufferSize, FlushMaxThreshold and FlushMaxPipelined
directives. [Yann Ylavic]
Modified: httpd/httpd/branches/2.4.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/STATUS?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/STATUS (original)
+++ httpd/httpd/branches/2.4.x/STATUS Sat Jan 16 14:22:41 2021
@@ -138,20 +138,6 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- *) mod_proxy_http: individual status codes for ProxyErrorOverride. BZ 63628
- trunk patch: https://svn.apache.org/r1754974
- https://svn.apache.org/r1754975
- https://svn.apache.org/r1876404
- https://svn.apache.org/r1877696
- https://svn.apache.org/r1877697
- https://svn.apache.org/r1877728
- 2.4.x patch: http://people.apache.org/~ylavic/patches/2.4.x-mod_proxy_http-override-3on5.patch
- https://github.com/apache/httpd/pull/157
- +1: ylavic, covener, minfrin
- ylavic: Besides ProxyErrorOverride individual status codes, merging now
- the non-functional changes in ap_proxy_http_process_response()
- around ProxyErrorOverride code helps reducing conflicts with the
- following commits, and with trunk/2.4 alignment still.
PATCHES PROPOSED TO BACKPORT FROM TRUNK:
Modified: httpd/httpd/branches/2.4.x/docs/manual/mod/mod_proxy.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/docs/manual/mod/mod_proxy.xml?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/mod/mod_proxy.xml (original)
+++ httpd/httpd/branches/2.4.x/docs/manual/mod/mod_proxy.xml Sat Jan 16 14:22:41 2021
@@ -1968,11 +1968,12 @@ header for proxied requests</description
<directivesynopsis>
<name>ProxyErrorOverride</name>
<description>Override error pages for proxied content</description>
-<syntax>ProxyErrorOverride On|Off</syntax>
+<syntax>ProxyErrorOverride Off|On [<var>code</var> ...]</syntax>
<default>ProxyErrorOverride Off</default>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context>
</contextlist>
+<compatibility>The list of status codes was added in 2.5.1</compatibility>
<usage>
<p>This directive is useful for reverse-proxy setups where you want to
@@ -1985,6 +1986,26 @@ header for proxied requests</description
<p>This directive does not affect the processing of informational (1xx),
normal success (2xx), or redirect (3xx) responses.</p>
+
+ <p>By default <directive>ProxyErrorOverride</directive> affects all responses with codes between 400 (including)
+ and 600 (excluding).</p>
+
+ <example><title>Example for default behavior</title>
+ <highlight language="config">
+ ProxyErrorOverride On
+ </highlight>
+ </example>
+
+ <p>To change the default behavior, you can specify the status codes to consider, separated by spaces.
+ If you do so, all other status codes will be ignored.
+ You can only specify status codes, that are considered error codes: between 400 (including)
+ and 600 (excluding).</p>
+
+ <example><title>Example for custom status codes</title>
+ <highlight language="config">
+ ProxyErrorOverride On 403 405 500 501 502 503 504
+ </highlight>
+ </example>
</usage>
</directivesynopsis>
Modified: httpd/httpd/branches/2.4.x/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/ap_mmn.h?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/include/ap_mmn.h (original)
+++ httpd/httpd/branches/2.4.x/include/ap_mmn.h Sat Jan 16 14:22:41 2021
@@ -541,6 +541,7 @@
* 20120211.97 (2.4.47-dev) Add read_buf_size member to core_dir_config,
* flush_max_threshold and flush_max_pipelined to
* core_server_config, and ap_get_read_buf_size().
+ * 20120211.98 (2.4.47-dev) Add ap_proxy_should_override to mod_proxy.h
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -548,7 +549,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 97 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 98 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c Sat Jan 16 14:22:41 2021
@@ -1575,6 +1575,7 @@ static void *create_proxy_dir_config(apr
new->raliases = apr_array_make(p, 10, sizeof(struct proxy_alias));
new->cookie_paths = apr_array_make(p, 10, sizeof(struct proxy_alias));
new->cookie_domains = apr_array_make(p, 10, sizeof(struct proxy_alias));
+ new->error_override_codes = apr_array_make(p, 10, sizeof(int));
new->preserve_host_set = 0;
new->preserve_host = 0;
new->interpolate_env = -1; /* unset */
@@ -1588,6 +1589,11 @@ static void *create_proxy_dir_config(apr
return (void *) new;
}
+static int int_order(const void *i1, const void *i2)
+{
+ return *(const int *)i1 - *(const int *)i2;
+}
+
static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
{
proxy_dir_conf *new = (proxy_dir_conf *) apr_pcalloc(p, sizeof(proxy_dir_conf));
@@ -1605,6 +1611,17 @@ static void *merge_proxy_dir_config(apr_
= apr_array_append(p, base->cookie_paths, add->cookie_paths);
new->cookie_domains
= apr_array_append(p, base->cookie_domains, add->cookie_domains);
+ new->error_override_codes
+ = apr_array_append(p, base->error_override_codes, add->error_override_codes);
+ /* Keep the array sorted for binary search (since "base" and "add" are
+ * already sorted, it's only needed only if both are merged).
+ */
+ if (base->error_override_codes->nelts
+ && add->error_override_codes->nelts) {
+ qsort(new->error_override_codes->elts,
+ new->error_override_codes->nelts,
+ sizeof(int), int_order);
+ }
new->interpolate_env = (add->interpolate_env == -1) ? base->interpolate_env
: add->interpolate_env;
new->preserve_host = (add->preserve_host_set == 0) ? base->preserve_host
@@ -2126,14 +2143,50 @@ static const char *
}
static const char *
- set_proxy_error_override(cmd_parms *parms, void *dconf, int flag)
+ set_proxy_error_override(cmd_parms *parms, void *dconf, const char *arg)
{
proxy_dir_conf *conf = dconf;
- conf->error_override = flag;
- conf->error_override_set = 1;
+ if (strcasecmp(arg, "Off") == 0) {
+ conf->error_override = 0;
+ conf->error_override_set = 1;
+ }
+ else if (strcasecmp(arg, "On") == 0) {
+ conf->error_override = 1;
+ conf->error_override_set = 1;
+ }
+ else if (conf->error_override_set == 1) {
+ int *newcode;
+ int argcode, i;
+ if (!apr_isdigit(arg[0]))
+ return "ProxyErrorOverride: status codes to intercept must be numeric";
+ if (!conf->error_override)
+ return "ProxyErrorOverride: status codes must follow a value of 'on'";
+
+ argcode = strtol(arg, NULL, 10);
+ if (!ap_is_HTTP_ERROR(argcode))
+ return "ProxyErrorOverride: status codes to intercept must be valid HTTP Status Codes >=400 && <600";
+
+ newcode = apr_array_push(conf->error_override_codes);
+ *newcode = argcode;
+
+ /* Keep the array sorted for binary search. */
+ for (i = conf->error_override_codes->nelts - 1; i > 0; --i) {
+ int *oldcode = &((int *)conf->error_override_codes->elts)[i - 1];
+ if (*oldcode <= argcode) {
+ break;
+ }
+ *newcode = *oldcode;
+ *oldcode = argcode;
+ newcode = oldcode;
+ }
+ }
+ else
+ return "ProxyErrorOverride first parameter must be one of: off | on";
+
return NULL;
}
+
static const char *
add_proxy_http_headers(cmd_parms *parms, void *dconf, int flag)
{
@@ -2723,7 +2776,7 @@ static const command_rec proxy_cmds[] =
"The default intranet domain name (in absence of a domain in the URL)"),
AP_INIT_TAKE1("ProxyVia", set_via_opt, NULL, RSRC_CONF,
"Configure Via: proxy header header to one of: on | off | block | full"),
- AP_INIT_FLAG("ProxyErrorOverride", set_proxy_error_override, NULL, RSRC_CONF|ACCESS_CONF,
+ AP_INIT_ITERATE("ProxyErrorOverride", set_proxy_error_override, NULL, RSRC_CONF|ACCESS_CONF,
"use our error handling pages instead of the servers' we are proxying"),
AP_INIT_FLAG("ProxyPreserveHost", set_preserve_host, NULL, RSRC_CONF|ACCESS_CONF,
"on if we should preserve host header while proxying"),
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.h?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.h (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.h Sat Jan 16 14:22:41 2021
@@ -201,7 +201,6 @@ typedef struct {
unsigned int ppinherit_set:1;
} proxy_server_conf;
-
typedef struct {
const char *p; /* The path */
ap_regex_t *r; /* Is this a regex? */
@@ -242,6 +241,8 @@ typedef struct {
unsigned int forward_100_continue:1;
unsigned int forward_100_continue_set:1;
+
+ apr_array_header_t *error_override_codes;
} proxy_dir_conf;
/* if we interpolate env vars per-request, we'll need a per-request
@@ -1232,6 +1233,15 @@ PROXY_DECLARE(int) ap_proxy_is_socket_co
int ap_proxy_lb_workers(void);
/**
+ * Returns 1 if a response with the given status should be overridden.
+ *
+ * @param conf proxy directory configuration
+ * @param code http status code
+ * @return 1 if code is considered an error-code, 0 otherwise
+ */
+PROXY_DECLARE(int) ap_proxy_should_override(proxy_dir_conf *conf, int code);
+
+/**
* Return the port number of a known scheme (eg: http -> 80).
* @param scheme scheme to test
* @return port number or 0 if unknown
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c Sat Jan 16 14:22:41 2021
@@ -475,7 +475,7 @@ static int ap_proxy_ajp_request(apr_pool
/* 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 (!ap_proxy_should_override(conf, r->status)) {
/* AJP13_SEND_BODY_CHUNK with zero length
* is explicit flush message
*/
@@ -498,8 +498,7 @@ static int ap_proxy_ajp_request(apr_pool
* 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(r->status)
- && ap_is_HTTP_ERROR(original_status)) {
+ if (ap_proxy_should_override(conf, original_status)) {
r->status = original_status;
r->status_line = original_status_line;
}
@@ -548,7 +547,7 @@ static int ap_proxy_ajp_request(apr_pool
if (status != APR_SUCCESS) {
backend_failed = 1;
}
- if (!conf->error_override || !ap_is_HTTP_ERROR(r->status)) {
+ if (!ap_proxy_should_override(conf, r->status)) {
e = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(output_brigade, e);
if (ap_pass_brigade(r->output_filters,
@@ -643,7 +642,7 @@ static int ap_proxy_ajp_request(apr_pool
conn->worker->cp->addr,
conn->worker->s->hostname_ex);
- if (conf->error_override && ap_is_HTTP_ERROR(r->status)) {
+ if (ap_proxy_should_override(conf, r->status)) {
/* clear r->status for override error, otherwise ErrorDocument
* thinks that this is a recursive error, and doesn't find the
* custom error page
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_fcgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_fcgi.c?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_fcgi.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_fcgi.c Sat Jan 16 14:22:41 2021
@@ -782,8 +782,7 @@ recv_again:
}
}
- if (conf->error_override
- && ap_is_HTTP_ERROR(r->status) && ap_is_initial_req(r)) {
+ if (ap_proxy_should_override(conf, r->status) && ap_is_initial_req(r)) {
/*
* set script_error_status to discard
* everything after the headers
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c Sat Jan 16 14:22:41 2021
@@ -1480,7 +1480,7 @@ int ap_proxy_http_process_response(proxy
} else {
/* an http/0.9 response */
backasswards = 1;
- r->status = 200;
+ r->status = proxy_status = 200;
r->status_line = "200 OK";
backend->close = 1;
}
@@ -1616,45 +1616,20 @@ int ap_proxy_http_process_response(proxy
* ProxyPassReverse/etc from here to ap_proxy_read_headers
*/
- if ((proxy_status == 401) && (dconf->error_override)) {
- const char *buf;
- const char *wa = "WWW-Authenticate";
- if ((buf = apr_table_get(r->headers_out, wa))) {
- apr_table_set(r->err_headers_out, wa, buf);
- } else {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01109)
- "origin server sent 401 without "
- "WWW-Authenticate header");
+ /* PR 41646: get HEAD right with ProxyErrorOverride */
+ if (ap_proxy_should_override(dconf, proxy_status)) {
+ if (proxy_status == HTTP_UNAUTHORIZED) {
+ const char *buf;
+ const char *wa = "WWW-Authenticate";
+ if ((buf = apr_table_get(r->headers_out, wa))) {
+ apr_table_set(r->err_headers_out, wa, buf);
+ } else {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01109)
+ "origin server sent 401 without "
+ "WWW-Authenticate header");
+ }
}
- }
- r->sent_bodyct = 1;
- /*
- * Is it an HTTP/0.9 response or did we maybe preread the 1st line of
- * the response? If so, load the extra data. These are 2 mutually
- * exclusive possibilities, that just happen to require very
- * similar behavior.
- */
- if (backasswards || pread_len) {
- apr_ssize_t cntr = (apr_ssize_t)pread_len;
- if (backasswards) {
- /*@@@FIXME:
- * At this point in response processing of a 0.9 response,
- * we don't know yet whether data is binary or not.
- * mod_charset_lite will get control later on, so it cannot
- * decide on the conversion of this buffer full of data.
- * However, chances are that we are not really talking to an
- * HTTP/0.9 server, but to some different protocol, therefore
- * the best guess IMHO is to always treat the buffer as "text/x":
- */
- ap_xlate_proto_to_ascii(buffer, len);
- cntr = (apr_ssize_t)len;
- }
- e = apr_bucket_heap_create(buffer, cntr, NULL, c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
- /* PR 41646: get HEAD right with ProxyErrorOverride */
- if (ap_is_HTTP_ERROR(r->status) && dconf->error_override) {
/* clear r->status for override error, otherwise ErrorDocument
* thinks that this is a recursive error, and doesn't find the
* custom error page
@@ -1684,10 +1659,38 @@ int ap_proxy_http_process_response(proxy
return proxy_status;
}
+ r->sent_bodyct = 1;
+ /*
+ * Is it an HTTP/0.9 response or did we maybe preread the 1st line of
+ * the response? If so, load the extra data. These are 2 mutually
+ * exclusive possibilities, that just happen to require very
+ * similar behavior.
+ */
+ if (backasswards || pread_len) {
+ apr_ssize_t cntr = (apr_ssize_t)pread_len;
+ if (backasswards) {
+ /*@@@FIXME:
+ * At this point in response processing of a 0.9 response,
+ * we don't know yet whether data is binary or not.
+ * mod_charset_lite will get control later on, so it cannot
+ * decide on the conversion of this buffer full of data.
+ * However, chances are that we are not really talking to an
+ * HTTP/0.9 server, but to some different protocol, therefore
+ * the best guess IMHO is to always treat the buffer as "text/x":
+ */
+ ap_xlate_proto_to_ascii(buffer, len);
+ cntr = (apr_ssize_t)len;
+ }
+ e = apr_bucket_heap_create(buffer, cntr, NULL, c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+
/* send body - but only if a body is expected */
if ((!r->header_only) && /* not HEAD request */
(proxy_status != HTTP_NO_CONTENT) && /* not 204 */
(proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */
+ apr_read_type_e mode;
+ int finish;
/* We need to copy the output headers and treat them as input
* headers as well. BUT, we need to do this before we remove
@@ -1708,150 +1711,144 @@ int ap_proxy_http_process_response(proxy
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, "start body send");
- /*
- * if we are overriding the errors, we can't put the content
- * of the page into the brigade
+ /* read the body, pass it to the output filters */
+
+ /* 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 (!dconf->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 (dconf->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;
-
- rv = ap_get_brigade(backend->r->input_filters, bb,
- AP_MODE_READBYTES, mode,
- req->sconf->io_buffer_size);
-
- /* ap_get_brigade will return success with an empty brigade
- * for a non-blocking read which would block: */
- if (mode == APR_NONBLOCK_READ
- && (APR_STATUS_IS_EAGAIN(rv)
- || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
- /* flush to the client and switch to blocking mode */
- e = apr_bucket_flush_create(c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- if (ap_pass_brigade(r->output_filters, bb)
- || c->aborted) {
- backend->close = 1;
- break;
- }
- apr_brigade_cleanup(bb);
- mode = APR_BLOCK_READ;
- continue;
- }
- else if (rv == APR_EOF) {
- backend->close = 1;
- break;
- }
- else if (rv != APR_SUCCESS) {
- /* In this case, we are in real trouble because
- * our backend bailed on us. Pass along a 502 error
- * error bucket
- */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110)
- "error reading response");
- ap_proxy_backend_broke(r, bb);
- ap_pass_brigade(r->output_filters, bb);
- backend_broke = 1;
+ if (ap_proxy_should_override(dconf, original_status)) {
+ r->status = original_status;
+ r->status_line = original_status_line;
+ }
+
+ mode = APR_NONBLOCK_READ;
+ finish = FALSE;
+ do {
+ apr_off_t readbytes;
+ apr_status_t rv;
+
+ rv = ap_get_brigade(backend->r->input_filters, bb,
+ AP_MODE_READBYTES, mode,
+ req->sconf->io_buffer_size);
+
+ /* ap_get_brigade will return success with an empty brigade
+ * for a non-blocking read which would block: */
+ if (mode == APR_NONBLOCK_READ
+ && (APR_STATUS_IS_EAGAIN(rv)
+ || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
+ /* flush to the client and switch to blocking mode */
+ e = apr_bucket_flush_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ if (ap_pass_brigade(r->output_filters, bb)
+ || c->aborted) {
backend->close = 1;
break;
}
- /* next time try a non-blocking read */
- mode = APR_NONBLOCK_READ;
+ apr_brigade_cleanup(bb);
+ mode = APR_BLOCK_READ;
+ continue;
+ }
+ else if (rv == APR_EOF) {
+ backend->close = 1;
+ break;
+ }
+ else if (rv != APR_SUCCESS) {
+ /* In this case, we are in real trouble because
+ * our backend bailed on us. Pass along a 502 error
+ * error bucket
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110)
+ "error reading response");
+ ap_proxy_backend_broke(r, bb);
+ ap_pass_brigade(r->output_filters, bb);
+ backend_broke = 1;
+ backend->close = 1;
+ break;
+ }
+ /* next time try a non-blocking read */
+ mode = APR_NONBLOCK_READ;
- if (!apr_is_empty_table(backend->r->trailers_in)) {
- apr_table_do(add_trailers, r->trailers_out,
- backend->r->trailers_in, NULL);
- apr_table_clear(backend->r->trailers_in);
- }
+ if (!apr_is_empty_table(backend->r->trailers_in)) {
+ apr_table_do(add_trailers, r->trailers_out,
+ backend->r->trailers_in, NULL);
+ apr_table_clear(backend->r->trailers_in);
+ }
- apr_brigade_length(bb, 0, &readbytes);
- backend->worker->s->read += readbytes;
+ apr_brigade_length(bb, 0, &readbytes);
+ backend->worker->s->read += readbytes;
#if DEBUGGING
- {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01111)
- "readbytes: %#x", readbytes);
- }
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01111)
+ "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);
+ /* sanity check */
+ if (APR_BRIGADE_EMPTY(bb)) {
+ break;
+ }
- /* found the last brigade? */
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) {
+ /* Switch the allocator lifetime of the buckets */
+ ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
- /* signal that we must leave */
- finish = TRUE;
+ /* found the last brigade? */
+ if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) {
- /* the brigade may contain transient buckets that contain
- * data that lives only as long as the backend connection.
- * Force a setaside so these transient buckets become heap
- * buckets that live as long as the request.
- */
- for (e = APR_BRIGADE_FIRST(pass_bb); e
- != APR_BRIGADE_SENTINEL(pass_bb); e
- = APR_BUCKET_NEXT(e)) {
- apr_bucket_setaside(e, r->pool);
- }
-
- /* finally it is safe to clean up the brigade from the
- * connection pool, as we have forced a setaside on all
- * buckets.
- */
- apr_brigade_cleanup(bb);
-
- /* make sure we release the backend connection as soon
- * as we know we are done, so that the backend isn't
- * left waiting for a slow client to eventually
- * acknowledge the data.
- */
- ap_proxy_release_connection(backend->worker->s->scheme,
- backend, r->server);
- /* Ensure that the backend is not reused */
- req->backend = NULL;
+ /* signal that we must leave */
+ finish = TRUE;
+ /* the brigade may contain transient buckets that contain
+ * data that lives only as long as the backend connection.
+ * Force a setaside so these transient buckets become heap
+ * buckets that live as long as the request.
+ */
+ for (e = APR_BRIGADE_FIRST(pass_bb); e
+ != APR_BRIGADE_SENTINEL(pass_bb); e
+ = APR_BUCKET_NEXT(e)) {
+ apr_bucket_setaside(e, r->pool);
}
- /* try send what we read */
- if (ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS
- || c->aborted) {
- /* Ack! Phbtt! Die! User aborted! */
- /* Only close backend if we haven't got all from the
- * backend. Furthermore if req->backend is NULL it is no
- * longer safe to fiddle around with backend as it might
- * be already in use by another thread.
- */
- if (req->backend) {
- /* this causes socket close below */
- req->backend->close = 1;
- }
- finish = TRUE;
+ /* finally it is safe to clean up the brigade from the
+ * connection pool, as we have forced a setaside on all
+ * buckets.
+ */
+ apr_brigade_cleanup(bb);
+
+ /* make sure we release the backend connection as soon
+ * as we know we are done, so that the backend isn't
+ * left waiting for a slow client to eventually
+ * acknowledge the data.
+ */
+ ap_proxy_release_connection(backend->worker->s->scheme,
+ backend, r->server);
+ /* Ensure that the backend is not reused */
+ req->backend = NULL;
+
+ }
+
+ /* try send what we read */
+ if (ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS
+ || c->aborted) {
+ /* Ack! Phbtt! Die! User aborted! */
+ /* Only close backend if we haven't got all from the
+ * backend. Furthermore if req->backend is NULL it is no
+ * longer safe to fiddle around with backend as it might
+ * be already in use by another thread.
+ */
+ if (req->backend) {
+ /* this causes socket close below */
+ req->backend->close = 1;
}
+ finish = TRUE;
+ }
- /* make sure we always clean up after ourselves */
- apr_brigade_cleanup(pass_bb);
- apr_brigade_cleanup(bb);
+ /* make sure we always clean up after ourselves */
+ apr_brigade_cleanup(pass_bb);
+ apr_brigade_cleanup(bb);
+
+ } while (!finish);
- } while (!finish);
- }
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "end body send");
}
else {
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_uwsgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_uwsgi.c?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_uwsgi.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_uwsgi.c Sat Jan 16 14:22:41 2021
@@ -371,9 +371,9 @@ static int uwsgi_response(request_rec *r
#if AP_MODULE_MAGIC_AT_LEAST(20101106,0)
dconf =
ap_get_module_config(r->per_dir_config, &proxy_module);
- if (dconf->error_override && ap_is_HTTP_ERROR(r->status)) {
+ if (ap_proxy_should_override(dconf, r->status)) {
#else
- if (conf->error_override && ap_is_HTTP_ERROR(r->status)) {
+ if (ap_proxy_should_override(conf, r->status)) {
#endif
int status = r->status;
r->status = HTTP_OK;
Modified: httpd/httpd/branches/2.4.x/modules/proxy/proxy_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/proxy_util.c?rev=1885575&r1=1885574&r2=1885575&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/proxy_util.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/proxy_util.c Sat Jan 16 14:22:41 2021
@@ -3401,6 +3401,45 @@ int ap_proxy_lb_workers(void)
return lb_workers_limit;
}
+static APR_INLINE int error_code_overridden(const int *elts, int nelts,
+ int code)
+{
+ int min = 0;
+ int max = nelts - 1;
+ AP_DEBUG_ASSERT(max >= 0);
+
+ while (min < max) {
+ int mid = (min + max) / 2;
+ int val = elts[mid];
+
+ if (val < code) {
+ min = mid + 1;
+ }
+ else if (val > code) {
+ max = mid - 1;
+ }
+ else {
+ return 1;
+ }
+ }
+
+ return elts[min] == code;
+}
+
+PROXY_DECLARE(int) ap_proxy_should_override(proxy_dir_conf *conf, int code)
+{
+ if (!conf->error_override)
+ return 0;
+
+ if (apr_is_empty_array(conf->error_override_codes))
+ return ap_is_HTTP_ERROR(code);
+
+ /* Since error_override_codes is sorted, apply binary search. */
+ return error_code_overridden((int *)conf->error_override_codes->elts,
+ conf->error_override_codes->nelts,
+ code);
+}
+
PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
apr_bucket_brigade *brigade)
{