Re: Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502
Hi, On Tue, Mar 26, Christopher Faulet wrote: > Le 26/03/2019 à 08:48, Jarno Huuskonen a écrit : > >Testing with 2.0-dev2(2.0-dev2 2019/03/26) I get kind of strange results > >with http2: > >- curl seems to retry in a infinite loop > >- firefox tries few times with both H2 / HTTP1.1 and then shows > > "Secure Connection Failed" > >- chrome tries few times (3 times w/H2 and 3 times w/HTTP/1.1) and > > then shows "ERR_SPDY_SERVER_REFUSED_STREAM" > > > >(With HTTP/1.1 all three show 502 error page). > > > > Hi Jarno, > > The 502 response code in HTTP/1.1 is detected by curl as a transient > error (timeout, 408/5xx response code). If you add the option > '--retry 1', curl will retry to perform the request one time. My > Firefox seems to retry 1 time before giving up. Note that in > HTTP/1.1, such retries are only possible on idempotent request. > > In HTTP/2, because nothing was sent to the client, HAProxy closes > the stream sending a RST_STREAM frame with the error code > REFUSED_STREAM. It is a guarantee that a request has not been > processed. So the client may automatically retry it (see RFC7540 - # > 8.1.4) . My Firefox retries 9 times before giving up. But curl > retries in loop. The option "--retry" is ignored. So I guess it is a > bug from curl. > > So everything seems to work as expected from the HAproxy point of view. Thank you for the explanation, makes sense. (And also thank you for working on this:) -Jarno -- Jarno Huuskonen
Re: Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502
Le 26/03/2019 à 08:48, Jarno Huuskonen a écrit : Testing with 2.0-dev2(2.0-dev2 2019/03/26) I get kind of strange results with http2: - curl seems to retry in a infinite loop - firefox tries few times with both H2 / HTTP1.1 and then shows "Secure Connection Failed" - chrome tries few times (3 times w/H2 and 3 times w/HTTP/1.1) and then shows "ERR_SPDY_SERVER_REFUSED_STREAM" (With HTTP/1.1 all three show 502 error page). Hi Jarno, The 502 response code in HTTP/1.1 is detected by curl as a transient error (timeout, 408/5xx response code). If you add the option '--retry 1', curl will retry to perform the request one time. My Firefox seems to retry 1 time before giving up. Note that in HTTP/1.1, such retries are only possible on idempotent request. In HTTP/2, because nothing was sent to the client, HAProxy closes the stream sending a RST_STREAM frame with the error code REFUSED_STREAM. It is a guarantee that a request has not been processed. So the client may automatically retry it (see RFC7540 - # 8.1.4) . My Firefox retries 9 times before giving up. But curl retries in loop. The option "--retry" is ignored. So I guess it is a bug from curl. So everything seems to work as expected from the HAproxy point of view. -- Christopher Faulet
Re: Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502
Hello, On Fri, Mar 01, Christopher Faulet wrote: > Le 01/03/2019 à 14:36, Jarno Huuskonen a écrit : > >Hi, > > > >Pinging this thread incase if this an actual error/bug and not > >a configuration error. > >(current 2.0-dev1-8dca19-40 2019/03/01 sends 400 error to client when > >http/2 is used). > > > > It is not an expected behavior, of course. And after a quick check, > it is a bug. Instead of catching an error from the server side, we > handle it as an abort from the client. > > I have to investigate a bit more because abortonclose seems to be > broken too. And when HTX is enable, the H1 is buggy too. Testing with 2.0-dev2(2.0-dev2 2019/03/26) I get kind of strange results with http2: - curl seems to retry in a infinite loop - firefox tries few times with both H2 / HTTP1.1 and then shows "Secure Connection Failed" - chrome tries few times (3 times w/H2 and 3 times w/HTTP/1.1) and then shows "ERR_SPDY_SERVER_REFUSED_STREAM" (With HTTP/1.1 all three show 502 error page). (Also the vtest attached to the start of this thread shows refused stream). Here's the test config: defaults mode http option http-use-htx timeout connect 1s timeout client 2s timeout server 4s timeout tarpit 3s listen HTTPS_in mode http bind 127.0.0.1:8443 ssl crt common.pem alpn h2,http/1.1 server tmpserver abns@proc1 send-proxy-v2 frontend fe bind abns@proc1 accept-proxy http-request reject if TRUE default_backend be backend be server h1srv 127.0.0.1:8082 listen H2_server bind 127.0.0.1:8082 -- Jarno Huuskonen - System Administrator | jarno.huuskonen atsign uef.fi
Re: Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502
Le 01/03/2019 à 14:36, Jarno Huuskonen a écrit : Hi, Pinging this thread incase if this an actual error/bug and not a configuration error. (current 2.0-dev1-8dca19-40 2019/03/01 sends 400 error to client when http/2 is used). Hi Jarno, It is not an expected behavior, of course. And after a quick check, it is a bug. Instead of catching an error from the server side, we handle it as an abort from the client. I have to investigate a bit more because abortonclose seems to be broken too. And when HTX is enable, the H1 is buggy too. -- Christopher Faulet
Re: Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502
Hi, Pinging this thread incase if this an actual error/bug and not a configuration error. (current 2.0-dev1-8dca19-40 2019/03/01 sends 400 error to client when http/2 is used). -Jarno On Sat, Feb 02, Jarno Huuskonen wrote: > (This is kind of related to this thread: > https://www.mail-archive.com/haproxy@formilux.org/msg32255.html). > > I'm seeing different behaviour between http1.1 / http2 when chaining > two frontends with mode http and the last frontend closes > connection with http-request reject (or tcp-request content reject). > > When client uses http/1.1 then client receives 502 error (I think > this is expected because the "server" for the first frontend just closes > connection). > > But when client uses http/2 then client will receive error 400. > (Tested with latest 2.0dev (2.0-dev0-32211a-258)). > I'm not sure if this is a bug, but at least seems to be different behaviour > between http/1.1 and http/2. (option http-use-htx doesn't seem to make > difference). > > The attached varnishtest should explain what I mean. I put some debug > printf output to proto_htx and with http/2 the status 400 comes > from /* 3: client abort with an abortonclose */ > (proto_htx.c line 1535, s->req.flags 0x9c42020). > > With http/1.1 status 502 comes from /* 4: close from server, capture > the response if the server has started to respond */ > (proto_htx.c line 1559, s->req.flags 0x9842000). > (If I interpret s->req.flags correctly then http/2 has > CF_READ_DONTWAIT and CF_SHUTR set and http/1.1 doesn't). > > -Jarno > > varnishtest "h2 chaining 400 error" > #REQUIRE_VERSION=1.9 > feature ignore_unknown_macro > > haproxy h1 -conf { > defaults > mode http > ${no-htx} option http-use-htx > timeout connect 1s > timeout client 1s > timeout server 1s > > listen HTTP_in > bind "fd@${HTTP_in}" > server tmpserver abns@proc1 send-proxy-v2 > > listen HTTP2_in > bind "fd@${HTTP2_in}" proto h2 > server tmpserver abns@proc1 send-proxy-v2 > > frontend fe > bind abns@proc1 accept-proxy > http-request reject if TRUE > default_backend be > > backend be > server s1 ${s1_addr}:${s1_port} > > } -start > > client c1h1 -connect ${h1_HTTP_in_sock} { > txreq > rxresp > expect resp.status == 502 > } -run > > client c1h2 -connect ${h1_HTTP2_in_sock} { > txpri > stream 0 { > txsettings > rxsettings > txsettings -ack > rxsettings > expect settings.ack == true > } -run > stream 1 { > # warning: -req, -scheme, -url MUST be placed first otherwise > # the H2 protocol is invalid since they are pseudo-headers > txreq \ > -req GET \ > -scheme "https" \ > -url /path/to/file.ext > > rxhdrs > expect resp.status == 502 > #rxdata -all > } -run > } -run > -- Jarno Huuskonen
Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502 Reply-To:
Hi, (This is kind of related to this thread: https://www.mail-archive.com/haproxy@formilux.org/msg32255.html). I'm seeing different behaviour between http1.1 / http2 when chaining two frontends with mode http and the last frontend closes connection with http-request reject (or tcp-request content reject). When client uses http/1.1 then client receives 502 error (I think this is expected because the "server" for the first frontend just closes connection). But when client uses http/2 then client will receive error 400. (Tested with latest 2.0dev (2.0-dev0-32211a-258)). I'm not sure if this is a bug, but at least seems to be different behaviour between http/1.1 and http/2. (option http-use-htx doesn't seem to make difference). The attached varnishtest should explain what I mean. I put some debug printf output to proto_htx and with http/2 the status 400 comes from /* 3: client abort with an abortonclose */ (proto_htx.c line 1535, s->req.flags 0x9c42020). With http/1.1 status 502 comes from /* 4: close from server, capture the response if the server has started to respond */ (proto_htx.c line 1559, s->req.flags 0x9842000). (If I interpret s->req.flags correctly then http/2 has CF_READ_DONTWAIT and CF_SHUTR set and http/1.1 doesn't). -Jarno varnishtest "h2 chaining 400 error" #REQUIRE_VERSION=1.9 feature ignore_unknown_macro haproxy h1 -conf { defaults mode http ${no-htx} option http-use-htx timeout connect 1s timeout client 1s timeout server 1s listen HTTP_in bind "fd@${HTTP_in}" server tmpserver abns@proc1 send-proxy-v2 listen HTTP2_in bind "fd@${HTTP2_in}" proto h2 server tmpserver abns@proc1 send-proxy-v2 frontend fe bind abns@proc1 accept-proxy http-request reject if TRUE default_backend be backend be server s1 ${s1_addr}:${s1_port} } -start client c1h1 -connect ${h1_HTTP_in_sock} { txreq rxresp expect resp.status == 502 } -run client c1h2 -connect ${h1_HTTP2_in_sock} { txpri stream 0 { txsettings rxsettings txsettings -ack rxsettings expect settings.ack == true } -run stream 1 { # warning: -req, -scheme, -url MUST be placed first otherwise # the H2 protocol is invalid since they are pseudo-headers txreq \ -req GET \ -scheme "https" \ -url /path/to/file.ext rxhdrs expect resp.status == 502 #rxdata -all } -run } -run -- Jarno Huuskonen