Go has support for both HTTP/1.x and HTTP/2 in the web server available in net/http. Unfortunately, in order support HTTP/2, the net.Conn returned by the net.Listener must be of type *tls.Conn. If it is not, the web server will refuse to upgrade the connection.

This makes it impossible to use HTTP/2 if you’re using a listener that may be returning different net.Conn implementations.

One could argue that this appropriate, given that HTTP/2 must be performed over a TLS connection. I’m not so sure I agree on this front. Is it up to the standard library to enforce this, or should there be enough room available to the developer to choose how this should be enforced? What if TLS is being terminated at a load balancer?

Anyway, this article provides a way to enable HTTP/2 without requiring a *tls.Conn. The basic mechanism of doing so involves the following:

  1. Use h2c.NewHandler(). This function takes a normal HTTP handler — which will most likely be the one you wrote for your HTTP/1.x service — and a HTTP/2 server configuration; and will return a new HTTP handler.
  2. Use the returned HTTP handler with a standard http.Server.

This new HTTP handler will hijack the original HTTP/1.x connection and upgrade it to a HTTP/2 connection.