Re: Chained http -> http frontends: http/2 error 400 vs http/1.1 error 502

2019-03-26 Thread Jarno Huuskonen
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

2019-03-26 Thread Christopher Faulet

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

2019-03-26 Thread Jarno Huuskonen
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

2019-03-01 Thread Christopher Faulet

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

2019-03-01 Thread Jarno Huuskonen
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:

2019-02-02 Thread Jarno Huuskonen
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