]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_proxy_wstunnel: Add ProxyWebsocketFallbackToProxyHttp.
authorYann Ylavic <ylavic@apache.org>
Wed, 12 May 2021 10:10:36 +0000 (10:10 +0000)
committerYann Ylavic <ylavic@apache.org>
Wed, 12 May 2021 10:10:36 +0000 (10:10 +0000)
Allows to opt-out the fallback to mod_proxy_http to handle WebSocket upgrade,
and let mod_proxy_wstunnel handle the requests as in 2.4.46 and earlier.

Update docs.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1889792 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_proxy_wstunnel.xml
modules/proxy/mod_proxy_wstunnel.c

index 519523080c09f0cc20debecf937afeff01e81877..2c1c2748e675bc1d1daf1bdcdf307123b732a5cf 100644 (file)
@@ -71,6 +71,26 @@ in the response <code>Upgrade</code></p>
 
 <seealso><module>mod_proxy</module></seealso>
 
+<directivesynopsis>
+<name>ProxyWebsocketFallbackToProxyHttp</name>
+<description>Instructs this module to let <module>mod_proxy_http</module> handle the request</description>
+<syntax>ProxyWebsocketFallbackToProxyHttp On|Off</syntax>
+<default>ProxyWebsocketFallbackToProxyHttp On</default>
+<compatibility>Available in httpd 2.4.48 and later</compatibility>
+<contextlist><context>server config</context>
+<context>virtual host</context>
+</contextlist>
+
+<usage>
+    <p>Since httpd 2.4.47, <module>mod_proxy_http</module> can handle WebSocket
+    upgrading and tunneling in accordance to RFC 7230, this directive controls
+    whether <module>mod_proxy_wstunnel</module> should hand over to
+    <module>mod_proxy_http</module> to this, which is the case by default.</p>
+    <p>Setting to <em>Off</em> lets <module>mod_proxy_wstunnel</module> handle
+    WebSocket requests as in httpd 2.4.46 and earlier.</p>
+</usage>
+</directivesynopsis>
+
 <directivesynopsis>
 <name>ProxyWebsocketAsync</name>
 <description>Instructs this module to try to create an asynchronous tunnel</description>
index caf79e784d0723ae5364671fab1958fbb65d7d8b..0037bfc57738901180ab9d74c16ac95186ba7b9b 100644 (file)
@@ -21,6 +21,8 @@
 module AP_MODULE_DECLARE_DATA proxy_wstunnel_module;
 
 typedef struct {
+    unsigned int fallback_to_proxy_http     :1,
+                 fallback_to_proxy_http_set :1;
     int mpm_can_poll;
     apr_time_t idle_timeout;
     apr_time_t async_delay;
@@ -34,7 +36,7 @@ typedef struct ws_baton_t {
     const char *scheme;
 } ws_baton_t;
 
-static int fallback_to_mod_proxy_http;
+static int can_fallback_to_proxy_http;
 
 static void proxy_wstunnel_callback(void *b);
 
@@ -111,7 +113,10 @@ static void proxy_wstunnel_callback(void *b)
 
 static int proxy_wstunnel_check_trans(request_rec *r, const char *url)
 {
-    if (fallback_to_mod_proxy_http) {
+    proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+                                                   &proxy_wstunnel_module);
+
+    if (can_fallback_to_proxy_http && dconf->fallback_to_proxy_http) {
         ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "check_trans fallback");
         return DECLINED;
     }
@@ -140,13 +145,15 @@ static int proxy_wstunnel_check_trans(request_rec *r, const char *url)
  */
 static int proxy_wstunnel_canon(request_rec *r, char *url)
 {
+    proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+                                                   &proxy_wstunnel_module);
     char *host, *path, sport[7];
     char *search = NULL;
     const char *err;
     char *scheme;
     apr_port_t port, def_port;
 
-    if (fallback_to_mod_proxy_http) {
+    if (can_fallback_to_proxy_http && dconf->fallback_to_proxy_http) {
         ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "canon fallback");
         return DECLINED;
     }
@@ -328,6 +335,8 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker,
                              char *url, const char *proxyname,
                              apr_port_t proxyport)
 {
+    proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+                                                   &proxy_wstunnel_module);
     int status;
     char server_portstr[32];
     proxy_conn_rec *backend = NULL;
@@ -338,7 +347,7 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker,
     apr_uri_t *uri;
     int is_ssl = 0;
 
-    if (fallback_to_mod_proxy_http) {
+    if (can_fallback_to_proxy_http && dconf->fallback_to_proxy_http) {
         ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "handler fallback");
         return DECLINED;
     }
@@ -426,6 +435,7 @@ static void *create_proxyws_dir_config(apr_pool_t *p, char *dummy)
     proxyws_dir_conf *new =
         (proxyws_dir_conf *) apr_pcalloc(p, sizeof(proxyws_dir_conf));
 
+    new->fallback_to_proxy_http = 1;
     new->idle_timeout = -1; /* no timeout */
 
     ap_mpm_query(AP_MPMQ_CAN_POLL, &new->mpm_can_poll);
@@ -433,6 +443,23 @@ static void *create_proxyws_dir_config(apr_pool_t *p, char *dummy)
     return (void *) new;
 }
 
+static void *merge_proxyws_dir_config(apr_pool_t *p, void *vbase, void *vadd)
+{
+    proxyws_dir_conf *new = apr_pcalloc(p, sizeof(proxyws_dir_conf)),
+                     *add = vadd, *base = vbase;
+
+    new->fallback_to_proxy_http = (add->fallback_to_proxy_http_set)
+                                  ? add->fallback_to_proxy_http
+                                  : base->fallback_to_proxy_http;
+    new->fallback_to_proxy_http_set = (add->fallback_to_proxy_http_set
+                                       || base->fallback_to_proxy_http_set);
+    new->mpm_can_poll = add->mpm_can_poll;
+    new->idle_timeout = add->idle_timeout;
+    new->async_delay = add->async_delay;
+
+    return new;
+}
+
 static const char * proxyws_set_idle(cmd_parms *cmd, void *conf, const char *val)
 {
     proxyws_dir_conf *dconf = conf;
@@ -449,10 +476,18 @@ static const char * proxyws_set_asynch_delay(cmd_parms *cmd, void *conf, const c
     return NULL;
 }
 
+static const char * proxyws_fallback_to_proxy_http(cmd_parms *cmd, void *conf, int arg)
+{
+    proxyws_dir_conf *dconf = conf;
+    dconf->fallback_to_proxy_http = !!arg;
+    dconf->fallback_to_proxy_http_set = 1;
+    return NULL;
+}
+
 static int proxy_wstunnel_post_config(apr_pool_t *pconf, apr_pool_t *plog,
                                       apr_pool_t *ptemp, server_rec *s)
 {
-    fallback_to_mod_proxy_http =
+    can_fallback_to_proxy_http =
         (ap_find_linked_module("mod_proxy_http.c") != NULL);
 
     return OK;
@@ -460,6 +495,11 @@ static int proxy_wstunnel_post_config(apr_pool_t *pconf, apr_pool_t *plog,
 
 static const command_rec ws_proxy_cmds[] =
 {
+    AP_INIT_FLAG("ProxyWebsocketFallbackToProxyHttp",
+                 proxyws_fallback_to_proxy_http, NULL, RSRC_CONF|ACCESS_CONF,
+                 "whether to let mod_proxy_http handle the upgrade and tunneling, "
+                 "On by default"),
+
     AP_INIT_TAKE1("ProxyWebsocketIdleTimeout", proxyws_set_idle, NULL,
                   RSRC_CONF|ACCESS_CONF,
                   "timeout for activity in either direction, unlimited by default"),
@@ -467,6 +507,7 @@ static const command_rec ws_proxy_cmds[] =
     AP_INIT_TAKE1("ProxyWebsocketAsyncDelay", proxyws_set_asynch_delay, NULL,
                  RSRC_CONF|ACCESS_CONF,
                  "amount of time to poll before going asynchronous"),
+
     {NULL}
 };
 
@@ -482,7 +523,7 @@ static void ws_proxy_hooks(apr_pool_t *p)
 AP_DECLARE_MODULE(proxy_wstunnel) = {
     STANDARD20_MODULE_STUFF,
     create_proxyws_dir_config,  /* create per-directory config structure */
-    NULL,                       /* merge per-directory config structures */
+    merge_proxyws_dir_config,   /* merge per-directory config structures */
     NULL,                       /* create per-server config structure */
     NULL,                       /* merge per-server config structures */
     ws_proxy_cmds,              /* command apr_table_t */