From: Yann Ylavic Date: Wed, 13 May 2020 14:25:25 +0000 (+0000) Subject: mod_proxy_http: follow up to r1877646: send Upgrade header with 101 response. X-Git-Tag: 2.5.0-alpha2-ci-test-only~1442 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=461ba17fa0c51c6cbcca20b39706f41dfe632c3b;p=thirdparty%2Fapache%2Fhttpd.git mod_proxy_http: follow up to r1877646: send Upgrade header with 101 response. Also, add a comment about why we forward the Upgrade header in non-101 responses provided the protocol matches the upgrade= configuration. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1877695 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 1e84aee74fd..10631420079 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1544,6 +1544,8 @@ int ap_proxy_http_process_response(proxy_http_req_t *req) } if (ap_is_HTTP_INFO(proxy_status)) { + const char *policy = NULL; + /* RFC2616 tells us to forward this. * * OTOH, an interim response here may mean the backend @@ -1558,19 +1560,32 @@ int ap_proxy_http_process_response(proxy_http_req_t *req) * * We need to set "r->expecting_100 = 1" otherwise origin * server behaviour will apply. + * + * 101 Switching Protocol has its own configuration which + * shouldn't be interfered by "proxy-interim-response". */ - const char *policy = apr_table_get(r->subprocess_env, - "proxy-interim-response"); + if (proxy_status != HTTP_SWITCHING_PROTOCOLS) { + policy = apr_table_get(r->subprocess_env, + "proxy-interim-response"); + } ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, - "HTTP: received interim %d response", r->status); + "HTTP: received interim %d response (policy: %s)", + r->status, policy ? policy : "n/a"); if (!policy - || upgrade || (!strcasecmp(policy, "RFC") && (proxy_status != HTTP_CONTINUE || (req->expecting_100 = 1)))) { - if (proxy_status == HTTP_CONTINUE) { + switch (proxy_status) { + case HTTP_CONTINUE: r->expecting_100 = req->expecting_100; req->expecting_100 = 0; + break; + case HTTP_SWITCHING_PROTOCOLS: + AP_DEBUG_ASSERT(upgrade != NULL); + apr_table_setn(r->headers_out, "Connection", "Upgrade"); + apr_table_setn(r->headers_out, "Upgrade", + apr_pstrdup(p, upgrade)); + break; } ap_send_interim_response(r, 1); } @@ -1761,7 +1776,10 @@ int ap_proxy_http_process_response(proxy_http_req_t *req) return proxy_status; } - /* Forward back Upgrade header if it matches the configured one(s). */ + /* Forward back Upgrade header if it matches the configured one(s), it + * may be an HTTP_UPGRADE_REQUIRED response or some other status where + * Upgrade makes sense to negotiate the protocol by other means. + */ if (upgrade && ap_proxy_worker_can_upgrade(p, worker, upgrade)) { apr_table_setn(r->headers_out, "Connection", "Upgrade"); apr_table_setn(r->headers_out, "Upgrade", apr_pstrdup(p, upgrade));