diff options
-rw-r--r-- | docs/manual/mod/mod_proxy_wstunnel.xml | 20 | ||||
-rw-r--r-- | modules/proxy/mod_proxy_wstunnel.c | 53 |
2 files changed, 67 insertions, 6 deletions
diff --git a/docs/manual/mod/mod_proxy_wstunnel.xml b/docs/manual/mod/mod_proxy_wstunnel.xml index 519523080c..2c1c2748e6 100644 --- a/docs/manual/mod/mod_proxy_wstunnel.xml +++ b/docs/manual/mod/mod_proxy_wstunnel.xml @@ -72,6 +72,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> <syntax>ProxyWebsocketAsync ON|OFF</syntax> diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c index caf79e784d..0037bfc577 100644 --- a/modules/proxy/mod_proxy_wstunnel.c +++ b/modules/proxy/mod_proxy_wstunnel.c @@ -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 */ |