summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/manual/mod/mod_proxy_wstunnel.xml20
-rw-r--r--modules/proxy/mod_proxy_wstunnel.c53
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 */