I tested with HAProxy 2.0.5 with following basic configuration using curl curl -v --http2-prior-knowledge http://IP
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
#maxconn 65536
defaults
log global
mode http
http-reuse never
no log
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend test
bind :80
mode http
maxconn 65536
default_backend nginx
backend nginx
mode http
balance leastconn
server <IP> <IP>:81 weight 255
When tested with HAProxy 1.9.8, I get the following error: http2 error: Remote peer returned unexpected data while we expected SETTINGS frame. Perhaps, peer does not support HTTP/2 properly.
With HAProxy 2.0, it works without giving proto h2 in bind line. With HAProxy 1.9, it does not work with the same configuration.
With the following command: curl -v --http2-prior-knowledge http://IP
Ok, I guess that’s because 2.0 by default enables HTX mode, and this likely changes how the request is parsed, accepting H2 message.
You can confirm that by putting option http-use-htx into a default section covering both front and backend in 1.9, and the reverse test, no option http-use-htx into a default section covering both front and backend in 2.0.
I’d say the behavior in this case is simply undefined. Is this causing any issues?
In fact, it is expected. An implicit upgrade from h1 to h2 is performed when an H2 preface is detected during the parsing of the first request of an HTTP connection. Once upgraded to h2, there is no way to come back in h1. So, on a non-TLS HTTP connection, it is possible to handle h1 or h2 requests (not mixed). Of course, if proto h2 is mentioned on the bind line, only h2 requests are accepted.
So, that said, I found a bug, there is no check to be sure it’s the first request. I will fix that quickly.