mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-03 02:32:03 +00:00
MINOR: server: add ws keyword
Implement parsing for the server keyword 'ws'. This is used to configure the mode of selection for websocket protocol. The configuration documentation has been updated. A new regtest has been created to test the proper behavior of the keyword.
This commit is contained in:
parent
9c3251d108
commit
f9d5957cd9
@ -14329,6 +14329,8 @@ alpn <protocols>
|
|||||||
|
|
||||||
server 127.0.0.1:443 ssl crt pub.pem alpn h2,http/1.1
|
server 127.0.0.1:443 ssl crt pub.pem alpn h2,http/1.1
|
||||||
|
|
||||||
|
See also "ws" to use an alternative ALPN for websocket streams.
|
||||||
|
|
||||||
backup
|
backup
|
||||||
When "backup" is present on a server line, the server is only used in load
|
When "backup" is present on a server line, the server is only used in load
|
||||||
balancing when all other non-backup servers are unavailable. Requests coming
|
balancing when all other non-backup servers are unavailable. Requests coming
|
||||||
@ -14942,6 +14944,8 @@ proto <name>
|
|||||||
Idea behind this option is to bypass the selection of the best multiplexer's
|
Idea behind this option is to bypass the selection of the best multiplexer's
|
||||||
protocol for all connections established to this server.
|
protocol for all connections established to this server.
|
||||||
|
|
||||||
|
See also "ws" to use an alternative protocol for websocket streams.
|
||||||
|
|
||||||
redir <prefix>
|
redir <prefix>
|
||||||
The "redir" parameter enables the redirection mode for all GET and HEAD
|
The "redir" parameter enables the redirection mode for all GET and HEAD
|
||||||
requests addressing this server. This means that instead of having HAProxy
|
requests addressing this server. This means that instead of having HAProxy
|
||||||
@ -15274,6 +15278,26 @@ weight <weight>
|
|||||||
can both grow and shrink, for instance between 10 and 100 to leave enough
|
can both grow and shrink, for instance between 10 and 100 to leave enough
|
||||||
room above and below for later adjustments.
|
room above and below for later adjustments.
|
||||||
|
|
||||||
|
ws { auto | h1 | h2 }
|
||||||
|
This option allows to configure the protocol used when relaying websocket
|
||||||
|
streams. This is most notably useful when using an HTTP/2 backend without the
|
||||||
|
support for H2 websockets through the RFC8441.
|
||||||
|
|
||||||
|
The default mode is "auto". This will reuse the same protocol as the main
|
||||||
|
one. The only difference is when using ALPN. In this case, it can try to
|
||||||
|
downgrade the ALPN to "http/1.1" only for websocket streams if the configured
|
||||||
|
server ALPN contains it.
|
||||||
|
|
||||||
|
The value "h1" is used to force HTTP/1.1 for websockets streams, through ALPN
|
||||||
|
if SSL ALPN is activated for the server. Similarly, "h2" can be used to
|
||||||
|
force HTTP/2.0 websockets. Use this value with care : the server must support
|
||||||
|
RFC8441 or an error will be reported by haproxy when relaying websockets.
|
||||||
|
|
||||||
|
Note that NPN is not taken into account as its usage has been deprecated in
|
||||||
|
favor of the ALPN extension.
|
||||||
|
|
||||||
|
See also "alpn" and "proto".
|
||||||
|
|
||||||
|
|
||||||
5.3. Server IP address resolution using DNS
|
5.3. Server IP address resolution using DNS
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
@ -1561,6 +1561,7 @@ add server <backend>/<server> [args]*
|
|||||||
- verify
|
- verify
|
||||||
- verifyhost
|
- verifyhost
|
||||||
- weight
|
- weight
|
||||||
|
- ws
|
||||||
|
|
||||||
Their syntax is similar to the server line from the configuration file,
|
Their syntax is similar to the server line from the configuration file,
|
||||||
please refer to their individual documentation for details.
|
please refer to their individual documentation for details.
|
||||||
|
1
reg-tests/http-messaging/common.pem
Symbolic link
1
reg-tests/http-messaging/common.pem
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../ssl/common.pem
|
181
reg-tests/http-messaging/srv_ws.vtc
Normal file
181
reg-tests/http-messaging/srv_ws.vtc
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
# This reg-test checks websocket support in regards with the server keyword
|
||||||
|
# 'ws'
|
||||||
|
|
||||||
|
varnishtest "h2 backend websocket management via server keyword"
|
||||||
|
|
||||||
|
feature ignore_unknown_macro
|
||||||
|
|
||||||
|
#REQUIRE_VERSION=2.5
|
||||||
|
#REQUIRE_OPTION=OPENSSL
|
||||||
|
|
||||||
|
# haproxy server
|
||||||
|
haproxy hapsrv -conf {
|
||||||
|
defaults
|
||||||
|
mode http
|
||||||
|
timeout connect 5s
|
||||||
|
timeout client 5s
|
||||||
|
timeout server 5s
|
||||||
|
|
||||||
|
frontend fe
|
||||||
|
bind "fd@${fe}"
|
||||||
|
bind "fd@${fessl}" ssl crt ${testdir}/common.pem alpn h2,http/1.1
|
||||||
|
capture request header sec-websocket-key len 128
|
||||||
|
http-request set-var(txn.ver) req.ver
|
||||||
|
use_backend be
|
||||||
|
|
||||||
|
backend be
|
||||||
|
# define websocket ACL
|
||||||
|
acl ws_handshake hdr(upgrade) -m str websocket
|
||||||
|
|
||||||
|
# handle non-ws streams
|
||||||
|
http-request return status 200 if !ws_handshake
|
||||||
|
|
||||||
|
# handle ws streams
|
||||||
|
#capture request header sec-websocket-key len 128
|
||||||
|
http-request return status 200 hdr connection upgrade hdr upgrade websocket hdr sec-websocket-accept "%[capture.req.hdr(0),concat(258EAFA5-E914-47DA-95CA-C5AB0DC85B11,,),sha1,base64]" if ws_handshake
|
||||||
|
http-after-response set-status 101 if { status eq 200 } { res.hdr(upgrade) -m str websocket }
|
||||||
|
http-after-response set-header x-backend-protocol "%[var(txn.ver)]"
|
||||||
|
} -start
|
||||||
|
|
||||||
|
# haproxy LB
|
||||||
|
haproxy hap -conf {
|
||||||
|
defaults
|
||||||
|
mode http
|
||||||
|
timeout connect 1s
|
||||||
|
timeout client 1s
|
||||||
|
timeout server 1s
|
||||||
|
|
||||||
|
# proto X ws h1 -> websocket on h1
|
||||||
|
listen li
|
||||||
|
bind "fd@${li}"
|
||||||
|
server hap_srv ${hapsrv_fe_addr}:${hapsrv_fe_port} proto h2 ws h1
|
||||||
|
|
||||||
|
# proto X ws h2 -> websocket on h2
|
||||||
|
listen lih2
|
||||||
|
bind "fd@${lih2}"
|
||||||
|
server hap_srv ${hapsrv_fe_addr}:${hapsrv_fe_port} proto h2 ws h2
|
||||||
|
|
||||||
|
# alpn h2,http/1.1 ws h2 -> websocket on h2
|
||||||
|
listen lisslh2
|
||||||
|
bind "fd@${lisslh2}"
|
||||||
|
server hap_srv ${hapsrv_fessl_addr}:${hapsrv_fessl_port} ssl verify none alpn h2,http/1.1 ws h2
|
||||||
|
http-response set-header x-alpn "%[ssl_bc_alpn]"
|
||||||
|
|
||||||
|
# ws auto -> websocket on h1
|
||||||
|
listen liauto
|
||||||
|
bind "fd@${liauto}"
|
||||||
|
server hap_srv ${hapsrv_fe_addr}:${hapsrv_fe_port}
|
||||||
|
|
||||||
|
# alpn h2,http/1.1 ws auto -> websocket on h1
|
||||||
|
listen lissl
|
||||||
|
bind "fd@${lissl}"
|
||||||
|
server hap_srv ${hapsrv_fessl_addr}:${hapsrv_fessl_port} ssl verify none alpn h2,http/1.1 ws auto
|
||||||
|
http-response set-header x-alpn "%[ssl_bc_alpn]"
|
||||||
|
# alpn h2,http/1.1 ws auto -> websocket on h1
|
||||||
|
listen lisslauto
|
||||||
|
bind "fd@${lisslauto}"
|
||||||
|
server hap_srv ${hapsrv_fessl_addr}:${hapsrv_fessl_port} ssl verify none alpn h2,http/1.1
|
||||||
|
http-response set-header x-alpn "%[ssl_bc_alpn]"
|
||||||
|
|
||||||
|
# proto h2 ws auto -> websocket on h2
|
||||||
|
listen liauto2
|
||||||
|
bind "fd@${liauto2}"
|
||||||
|
server hap_srv ${hapsrv_fe_addr}:${hapsrv_fe_port} proto h2
|
||||||
|
|
||||||
|
# alpn h2 ws auto -> websocket on h2
|
||||||
|
listen lisslauto2
|
||||||
|
bind "fd@${lisslauto2}"
|
||||||
|
server hap_srv ${hapsrv_fessl_addr}:${hapsrv_fessl_port} ssl verify none alpn h2 ws auto
|
||||||
|
http-response set-header x-alpn "%[ssl_bc_alpn]"
|
||||||
|
} -start
|
||||||
|
|
||||||
|
client c1 -connect ${hap_li_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-backend-protocol == "1.1"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
client c1.2 -connect ${hap_lih2_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-backend-protocol == "2.0"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
client c1.3 -connect ${hap_liauto_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-backend-protocol == "1.1"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
client c1.4 -connect ${hap_liauto2_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-backend-protocol == "2.0"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
client c2 -connect ${hap_lisslauto_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-alpn == "http/1.1"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
client c2.2 -connect ${hap_lisslauto2_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-alpn == "h2"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
client c2.3 -connect ${hap_lisslh2_sock} {
|
||||||
|
txreq \
|
||||||
|
-req "GET" \
|
||||||
|
-url "/" \
|
||||||
|
-hdr "host: 127.0.0.1" \
|
||||||
|
-hdr "connection: upgrade" \
|
||||||
|
-hdr "upgrade: websocket" \
|
||||||
|
-hdr "sec-websocket-key: dGhlIHNhbXBsZSBub25jZQ=="
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 101
|
||||||
|
expect resp.http.x-alpn == "h2"
|
||||||
|
} -run
|
28
src/server.c
28
src/server.c
@ -505,6 +505,33 @@ static int srv_parse_error_limit(char **args, int *cur_arg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse the "ws" keyword */
|
||||||
|
static int srv_parse_ws(char **args, int *cur_arg,
|
||||||
|
struct proxy *curproxy, struct server *newsrv, char **err)
|
||||||
|
{
|
||||||
|
if (!args[*cur_arg + 1]) {
|
||||||
|
memprintf(err, "'%s' expects 'auto', 'h1' or 'h2' value", args[*cur_arg]);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(args[*cur_arg + 1], "h1") == 0) {
|
||||||
|
newsrv->ws = SRV_WS_H1;
|
||||||
|
}
|
||||||
|
else if (strcmp(args[*cur_arg + 1], "h2") == 0) {
|
||||||
|
newsrv->ws = SRV_WS_H2;
|
||||||
|
}
|
||||||
|
else if (strcmp(args[*cur_arg + 1], "auto") == 0) {
|
||||||
|
newsrv->ws = SRV_WS_AUTO;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memprintf(err, "'%s' has to be 'auto', 'h1' or 'h2'", args[*cur_arg]);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the "init-addr" server keyword */
|
/* Parse the "init-addr" server keyword */
|
||||||
static int srv_parse_init_addr(char **args, int *cur_arg,
|
static int srv_parse_init_addr(char **args, int *cur_arg,
|
||||||
struct proxy *curproxy, struct server *newsrv, char **err)
|
struct proxy *curproxy, struct server *newsrv, char **err)
|
||||||
@ -1733,6 +1760,7 @@ static struct srv_kw_list srv_kws = { "ALL", { }, {
|
|||||||
{ "disabled", srv_parse_disabled, 0, 1, 1 }, /* Start the server in 'disabled' state */
|
{ "disabled", srv_parse_disabled, 0, 1, 1 }, /* Start the server in 'disabled' state */
|
||||||
{ "enabled", srv_parse_enabled, 0, 1, 1 }, /* Start the server in 'enabled' state */
|
{ "enabled", srv_parse_enabled, 0, 1, 1 }, /* Start the server in 'enabled' state */
|
||||||
{ "error-limit", srv_parse_error_limit, 1, 1, 1 }, /* Configure the consecutive count of check failures to consider a server on error */
|
{ "error-limit", srv_parse_error_limit, 1, 1, 1 }, /* Configure the consecutive count of check failures to consider a server on error */
|
||||||
|
{ "ws", srv_parse_ws, 1, 1, 1 }, /* websocket protocol */
|
||||||
{ "id", srv_parse_id, 1, 0, 1 }, /* set id# of server */
|
{ "id", srv_parse_id, 1, 0, 1 }, /* set id# of server */
|
||||||
{ "init-addr", srv_parse_init_addr, 1, 1, 0 }, /* */
|
{ "init-addr", srv_parse_init_addr, 1, 1, 0 }, /* */
|
||||||
{ "log-proto", srv_parse_log_proto, 1, 1, 0 }, /* Set the protocol for event messages, only relevant in a ring section */
|
{ "log-proto", srv_parse_log_proto, 1, 1, 0 }, /* Set the protocol for event messages, only relevant in a ring section */
|
||||||
|
Loading…
Reference in New Issue
Block a user