mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-20 10:40:13 +00:00
da93802ffc
When an error occurred during the request parsing, the H1 multiplexer is responsible to sent a response to the client and to release the H1 stream and the H1 connection. In HTTP mode, it is not an issue because at this stage the H1 connection is in embryonic state. Thus it can be released immediately. However, it is a problem if the connection was first upgraded from a TCP connection. In this case, a stream-connector is attached. The H1 stream is not orphan. Thus it must not be released at this stage. It must be detached first. Otherwise a BUG_ON() is triggered in h1s_destroy(). So now, the H1S is destroyed on early errors but only if the H1C is in embryonic state. This patch may be related to #1966. It must be backported to 2.7.
170 lines
3.5 KiB
Plaintext
170 lines
3.5 KiB
Plaintext
varnishtest "Test connection upgrades from TCP to HTTP"
|
|
|
|
#REQUIRE_VERSION=2.4
|
|
|
|
feature ignore_unknown_macro
|
|
|
|
server s1 {
|
|
# TCP > H1 using "switch-mode http"
|
|
rxreq
|
|
expect req.http.x-stream-mode == tcp
|
|
expect req.http.x-name == fe1
|
|
txresp
|
|
rxreq
|
|
expect req.http.x-stream-mode == http
|
|
expect req.http.x-name == fe1
|
|
txresp
|
|
|
|
accept
|
|
|
|
# TCP > H1 using backend mode
|
|
rxreq
|
|
expect req.http.x-name == be
|
|
txresp
|
|
rxreq
|
|
expect req.http.x-name == be
|
|
txresp
|
|
|
|
accept
|
|
|
|
# TCP > H2 using "switch-mode http"
|
|
rxreq
|
|
expect req.http.x-stream-mode == http
|
|
expect req.http.x-name == fe1
|
|
txresp
|
|
rxreq
|
|
expect req.http.x-stream-mode == http
|
|
expect req.http.x-name == fe1
|
|
txresp
|
|
|
|
# To be sure no other request was received
|
|
accept
|
|
rxreq
|
|
txresp
|
|
} -start
|
|
|
|
haproxy h1 -conf {
|
|
frontend fe1
|
|
mode tcp
|
|
bind "fd@${fe1h1}"
|
|
|
|
tcp-request inspect-delay 1s
|
|
tcp-request content set-var(req.stream_mode) internal.strm.is_htx,iif(http,tcp)
|
|
tcp-request content switch-mode http if HTTP
|
|
tcp-request content reject # never reached
|
|
|
|
http-request set-header x-stream-mode %[var(req.stream_mode)]
|
|
http-request set-header x-name %[fe_name]
|
|
|
|
default_backend be
|
|
|
|
frontend fe2
|
|
mode tcp
|
|
bind "fd@${fe2h1}"
|
|
default_backend be
|
|
|
|
backend be
|
|
mode http
|
|
http-request set-header x-name %[be_name] unless { req.fhdr(x-name) -m found }
|
|
server s1 ${s1_addr}:${s1_port}
|
|
|
|
listen li1
|
|
mode http
|
|
bind "fd@${li1h1}"
|
|
server s1 ${h1_fe1h1_addr}:${h1_fe1h1_port} proto h2
|
|
|
|
listen err1
|
|
mode http
|
|
bind "fd@${err1h1}" proto h1
|
|
server s1 ${s1_addr}:${s1_port}
|
|
|
|
listen err2
|
|
mode tcp
|
|
bind "fd@${err2h1}"
|
|
|
|
tcp-request inspect-delay 1s
|
|
tcp-request content switch-mode http proto h1 if HTTP
|
|
tcp-request content reject # never reached
|
|
|
|
default_backend be
|
|
|
|
listen err3
|
|
mode tcp
|
|
bind "fd@${err3h1}" proto none
|
|
|
|
tcp-request inspect-delay 1s
|
|
tcp-request content switch-mode http if HTTP
|
|
tcp-request content reject # never reached
|
|
|
|
default_backend be
|
|
} -start
|
|
|
|
# TCP > H1 using "switch-mode http"
|
|
client c1 -connect ${h1_fe1h1_sock} {
|
|
txreq
|
|
rxresp
|
|
expect resp.status == 200
|
|
|
|
txreq
|
|
rxresp
|
|
expect resp.status == 200
|
|
} -run
|
|
|
|
# TCP > H1 using backend mode
|
|
client c2 -connect ${h1_fe2h1_sock} {
|
|
txreq
|
|
rxresp
|
|
expect resp.status == 200
|
|
|
|
txreq
|
|
rxresp
|
|
expect resp.status == 200
|
|
} -run
|
|
|
|
|
|
# TCP > H2 using "switch-mode http"
|
|
client c3 -connect ${h1_li1h1_sock} {
|
|
txreq
|
|
rxresp
|
|
expect resp.status == 200
|
|
|
|
txreq
|
|
rxresp
|
|
expect resp.status == 200
|
|
} -run
|
|
|
|
# implicit H1 > H2 upgrade not performed
|
|
client c_err1 -connect ${h1_err1h1_sock} {
|
|
send "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
|
rxresp
|
|
expect resp.status == 400
|
|
} -run
|
|
|
|
|
|
# TCP > H1 > H2 upgrade not allowed
|
|
client c_err2 -connect ${h1_err2h1_sock} {
|
|
send "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
|
rxresp
|
|
expect resp.status == 400
|
|
} -run
|
|
|
|
|
|
# TCP > HTTP upgrade not allowed
|
|
client c_err3 -connect ${h1_err3h1_sock} {
|
|
txreq
|
|
expect_close
|
|
} -run
|
|
|
|
# TCP > HTTP upgrade with a parsing error
|
|
client c_err4 -connect ${h1_fe2h1_sock} {
|
|
send "GET / BAD-VERSION\r\n\r\n"
|
|
rxresp
|
|
expect resp.status == 400
|
|
} -run
|
|
|
|
# To be sure no other request was received by the server
|
|
client c_end -connect ${s1_sock} {
|
|
txreq
|
|
rxresp
|
|
} -run
|