From: Jean-Frederic Clere Date: Thu, 20 Apr 2017 17:07:32 +0000 (+0000) Subject: Add upgrade parameter to mod_proxy_wstunnel. X-Git-Tag: 2.5.0-alpha~463 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=61ca36599d3bdedb89221508c16e888f3e9e107d;p=thirdparty%2Fapache%2Fhttpd.git Add upgrade parameter to mod_proxy_wstunnel. That allows to upgrade to jboss-remoting for example or to run an HTTP/1.1 backend that needs to upgrade to WebSocket. See also: https://issues.jboss.org/browse/JBCS-254 https://issues.jboss.org/browse/JBCS-291 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1792092 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 7df69b09348..2d9f5367c35 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_proxy_wstunnel: Add "upgrade" parameter to allow upgrade to other + protocols. [Jean-Frederic Clere] + *) mod_substitute: Fix spurious AH01328 (Line too long) errors on EBCDIC systems. [Eric Covener] diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml index 02ae4869462..d9b894cf447 100644 --- a/docs/manual/mod/mod_proxy.xml +++ b/docs/manual/mod/mod_proxy.xml @@ -1208,6 +1208,16 @@ ProxyPass "/example" "http://backend.example.com" max=20 ttl=120 retry=300

Name of the provider used by mod_proxy_fdpass. See the documentation of this module for more details.

+ secret + - +

Value of secret used by mod_proxy_ajp. + See the documentation of this module for more details.

+ + upgrade + WebSocket +

Protocol accepted in the Upgrade header by mod_proxy_wstunnel. + See the documentation of this module for more details.

+ diff --git a/docs/manual/mod/mod_proxy_wstunnel.xml b/docs/manual/mod/mod_proxy_wstunnel.xml index 903f65589c0..354b0bb2ad5 100644 --- a/docs/manual/mod/mod_proxy_wstunnel.xml +++ b/docs/manual/mod/mod_proxy_wstunnel.xml @@ -51,6 +51,11 @@ ProxyPass "/wss2/" "wss://echo.websocket.org/"

Load balancing for multiple backends can be achieved using mod_proxy_balancer.

+ +

In fact the module can be used to upgrade to other protocols, you can set the upgrade +parameter in the ProxyPass +directive to allow the module to accept other protocol. +NONE means you bypass the check for the header but still upgrade to WebSocket.

mod_proxy diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 8004650e6c8..a0b08788cf0 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -317,6 +317,12 @@ static const char *set_worker_param(apr_pool_t *p, (int)sizeof(worker->s->secret)); } } + else if (!strcasecmp(key, "upgrade")) { + if (PROXY_STRNCPY(worker->s->upgrade, val) != APR_SUCCESS) { + return apr_psprintf(p, "upgrade protocol length must be < %d characters", + (int)sizeof(worker->s->upgrade)); + } + } else { if (set_worker_hc_param_f) { return set_worker_hc_param_f(p, s, worker, key, val, NULL); diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index ba78317bbe6..0ea7b3fc3d3 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -450,6 +450,7 @@ typedef struct { unsigned int was_malloced:1; unsigned int is_name_matchable:1; char secret[PROXY_WORKER_MAX_SECRET_SIZE]; /* authentication secret (e.g. AJP13) */ + char upgrade[PROXY_WORKER_MAX_SCHEME_SIZE];/* upgrade protocol used by mod_proxy_wstunnel */ } proxy_worker_shared; #define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared))) diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c index c94c082d615..31398d5fc9b 100644 --- a/modules/proxy/mod_proxy_wstunnel.c +++ b/modules/proxy/mod_proxy_wstunnel.c @@ -313,6 +313,7 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, ws_baton_t *baton = apr_pcalloc(r->pool, sizeof(ws_baton_t)); int status; proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_wstunnel_module); + const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : "WebSocket"; header_brigade = apr_brigade_create(p, backconn->bucket_alloc); @@ -325,7 +326,11 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, return rv; } - buf = apr_pstrdup(p, "Upgrade: WebSocket" CRLF "Connection: Upgrade" CRLF CRLF); + if (ap_cstr_casecmp(upgrade_method, "NONE") == 0) { + buf = apr_pstrdup(p, "Upgrade: WebSocket" CRLF "Connection: Upgrade" CRLF CRLF); + } else { + buf = apr_pstrcat(p, "Upgrade: ", upgrade_method, CRLF "Connection: Upgrade" CRLF 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); @@ -445,12 +450,12 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker, int status; char server_portstr[32]; proxy_conn_rec *backend = NULL; - const char *upgrade; char *scheme; apr_pool_t *p = r->pool; char *locurl = url; apr_uri_t *uri; int is_ssl = 0; + const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : "WebSocket"; if (ap_cstr_casecmpn(url, "wss:", 4) == 0) { scheme = "WSS"; @@ -464,12 +469,15 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker, return DECLINED; } - upgrade = apr_table_get(r->headers_in, "Upgrade"); - if (!upgrade || ap_cstr_casecmp(upgrade, "WebSocket") != 0) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02900) - "declining URL %s (not WebSocket, Upgrade: header is %s)", - url, upgrade ? upgrade : "missing"); - return DECLINED; + if (ap_cstr_casecmp(upgrade_method, "NONE") != 0) { + const char *upgrade; + upgrade = apr_table_get(r->headers_in, "Upgrade"); + if (!upgrade || ap_cstr_casecmp(upgrade, upgrade_method) != 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02900) + "declining URL %s (not %s, Upgrade: header is %s)", + url, upgrade_method, upgrade ? upgrade : "missing"); + return DECLINED; + } } uri = apr_palloc(p, sizeof(*uri));