summaryrefslogtreecommitdiffstats
path: root/modules/proxy
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2022-05-30 17:54:34 +0200
committerYann Ylavic <ylavic@apache.org>2022-05-30 17:54:34 +0200
commit9a8214d08fac52dda13ecc673ade2f5152f8e9de (patch)
tree57cde6e5bfc2573de2237d52ab9f122499620993 /modules/proxy
parentMerge of PR 318: (diff)
downloadapache2-9a8214d08fac52dda13ecc673ade2f5152f8e9de.tar.xz
apache2-9a8214d08fac52dda13ecc673ade2f5152f8e9de.zip
mod_proxy_http: Avoid 417 responses for non forwardable 100-continue. PR 65666.
Stop returning 417 when mod_proxy has to forward an HTTP/1.1 request with both "Expect: 100-continue" and "force-proxy-request-1.0" set, mod_proxy can instead handle the 100-continue by itself before forwarding the request, like in the "Proxy100Continue Off" case. Note that this does not change the behaviour of httpd receiving an HTTP/1.0 request with an Expect header, ap_check_request_header() will still correctly return 417 in this case. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1901420 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/proxy')
-rw-r--r--modules/proxy/mod_proxy.h11
-rw-r--r--modules/proxy/mod_proxy_http.c9
-rw-r--r--modules/proxy/proxy_util.c50
3 files changed, 34 insertions, 36 deletions
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 2eac740dac..6301845712 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -398,11 +398,14 @@ do { \
(w)->s->io_buffer_size_set = (c)->io_buffer_size_set; \
} while (0)
+#define PROXY_SHOULD_PING_100_CONTINUE(w, r) \
+ ((w)->s->ping_timeout_set \
+ && (PROXYREQ_REVERSE == (r)->proxyreq) \
+ && ap_request_has_body((r)))
+
#define PROXY_DO_100_CONTINUE(w, r) \
-((w)->s->ping_timeout_set \
- && (PROXYREQ_REVERSE == (r)->proxyreq) \
- && !(apr_table_get((r)->subprocess_env, "force-proxy-request-1.0")) \
- && ap_request_has_body((r)))
+ (PROXY_SHOULD_PING_100_CONTINUE(w, r) \
+ && !apr_table_get((r)->subprocess_env, "force-proxy-request-1.0"))
/* use 2 hashes */
typedef struct {
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index d86f29afb4..c0b20c2462 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -547,10 +547,6 @@ static int ap_proxy_http_prefetch(proxy_http_req_t *req,
apr_off_t bytes;
int rv;
- if (req->force10 && r->expecting_100) {
- return HTTP_EXPECTATION_FAILED;
- }
-
rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
req->worker, req->sconf,
uri, url, req->server_portstr,
@@ -2008,8 +2004,9 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
apr_pool_userdata_get((void **)&input_brigade, "proxy-req-input", p);
/* Should we handle end-to-end or ping 100-continue? */
- if ((r->expecting_100 && (dconf->forward_100_continue || input_brigade))
- || PROXY_DO_100_CONTINUE(worker, r)) {
+ if (!req->force10
+ && ((r->expecting_100 && (dconf->forward_100_continue || input_brigade))
+ || PROXY_SHOULD_PING_100_CONTINUE(worker, r))) {
req->do_100_continue = 1;
}
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 5c55531ee4..c0c6b99486 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -3891,9 +3891,9 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
char *buf;
apr_table_t *saved_headers_in, *request_headers;
apr_bucket *e;
- int do_100_continue;
+ int force10 = 0, ping100 = 0;
conn_rec *origin = p_conn->connection;
- const char *fpr1, *creds;
+ const char *creds;
proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
/*
@@ -3901,29 +3901,25 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
* To be compliant, we only use 100-Continue for requests with bodies.
* We also make sure we won't be talking HTTP/1.0 as well.
*/
- fpr1 = apr_table_get(r->subprocess_env, "force-proxy-request-1.0");
- do_100_continue = PROXY_DO_100_CONTINUE(worker, r);
-
- if (fpr1) {
- /*
- * According to RFC 2616 8.2.3 we are not allowed to forward an
- * Expect: 100-continue to an HTTP/1.0 server. Instead we MUST return
- * a HTTP_EXPECTATION_FAILED
- */
- if (r->expecting_100) {
- return HTTP_EXPECTATION_FAILED;
- }
- buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL);
- p_conn->close = 1;
- } else {
- buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
+ if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
+ force10 = 1;
+ }
+ else if (PROXY_SHOULD_PING_100_CONTINUE(worker, r)) {
+ ping100 = 1;
}
- if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {
+ if (force10 || apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {
if (origin) {
origin->keepalive = AP_CONN_CLOSE;
}
p_conn->close = 1;
}
+
+ if (force10) {
+ buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL);
+ }
+ else {
+ buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
+ }
ap_xlate_proto_to_ascii(buf, strlen(buf));
e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(header_brigade, e);
@@ -4016,16 +4012,17 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
/* Use HTTP/1.1 100-Continue as quick "HTTP ping" test
* to backend
*/
- if (do_100_continue) {
- const char *val;
-
+ if (ping100) {
/* Add the Expect header if not already there. */
- if (((val = apr_table_get(request_headers, "Expect")) == NULL)
- || (ap_cstr_casecmp(val, "100-Continue") != 0 /* fast path */
- && !ap_find_token(r->pool, val, "100-Continue"))) {
+ const char *val = apr_table_get(request_headers, "Expect");
+ if (!val || (ap_cstr_casecmp(val, "100-Continue") != 0 /* fast path */
+ && !ap_find_token(r->pool, val, "100-Continue"))) {
apr_table_mergen(request_headers, "Expect", "100-Continue");
}
}
+ else if (force10 || !dconf->forward_100_continue || !r->expecting_100) {
+ apr_table_unset(request_headers, "Expect");
+ }
/* X-Forwarded-*: handling
*
@@ -4101,7 +4098,8 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
* request bodies, it seems unwise to clear any Trailer
* header present. Is this the correct thing now?
*/
- if (fpr1) apr_table_unset(request_headers, "Trailer");
+ if (force10)
+ apr_table_unset(request_headers, "Trailer");
apr_table_unset(request_headers, "Upgrade");