After reading both HTTP/2 RFC (#7540) and TLS-ALPN RFC (#7301), I'm still unable to figure out the expected behavior when ALPN is lacking in one end.
Assuming I have a client that uses HTTP/2 "h2" (over TLS) that talks to a server that support HTTP/2 but does not send the ALPN extension in the "server hello". What is the expected behavior from the client?
Most clients I've seen so far consider that HTTP/2 is not supported by the server and downgrade the connection to http/1.1, but few ignore (go-gRPC) continue with HTTP/2.
This scenario can be more practical if using AWS classic LB that does SSL termination between a client ("h2") to the server ("h2c"). In this example, the client sends the ALPN extension with value of "h2", the LB performs SSL handshake without ALPN (as expected from his part), and eventually the JAVA gRPC fails due to HTTP/1.1 downgrade.
It depends entirely on the client and server. Many still support the older NPN TLS extension for SPDY and HTTP/2 Support, though officially the spec says to use ALPN only.
On the browser side, for example, Chrome, Firefox and Opera now only support HTTP/2 over ALPN though they all used to support it over NPN. At the time of writing Safari, IE and Edge still allow either NPN or ALPN to be used.
On the server side some (e.g. Nginx) Support both, while some (e.g. Apache) only Support ALPN.
I would also question the terminology of “downgrade”. The ALPN extension is a request to use h2 and happens as part of the TLS negotiation before a single HTTP message has been sent. So it’s not really a downgrade anymore than an unsuccessful upgrade request.