Skip to content

HTTPS and HTTP/2

A router is an http.Handler, so TLS and HTTP/2 are the server’s job and need nothing from the router. net/http negotiates HTTP/2 on TLS connections by itself: serve with ListenAndServeTLS and HTTP/2 clients get HTTP/2.

examples/tls/main.go
// Command tls serves over HTTPS. net/http negotiates HTTP/2 on TLS connections by itself,
// so the router serves HTTP/2 clients with no extra setup.
//
// Behind a proxy that terminates TLS, run it with -h2c to accept HTTP/2 without TLS as well.
package main
import (
"flag"
"fmt"
"log"
"net/http"
"time"
"github.com/vardius/gorouter/v5"
)
func newRouter() *gorouter.Router {
r := gorouter.New()
r.GET("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello over %s\n", r.Proto)
})
return r
}
func main() {
addr := flag.String("addr", ":8443", "address to listen on")
cert := flag.String("cert", "cert.pem", "TLS certificate file")
key := flag.String("key", "key.pem", "TLS key file")
h2c := flag.Bool("h2c", false, "serve HTTP/1 and unencrypted HTTP/2 without TLS")
flag.Parse()
srv := &http.Server{Addr: *addr, Handler: newRouter(), ReadHeaderTimeout: 5 * time.Second}
if *h2c {
var protocols http.Protocols
protocols.SetHTTP1(true)
protocols.SetUnencryptedHTTP2(true)
srv.Protocols = &protocols
log.Fatal(srv.ListenAndServe())
}
log.Fatal(srv.ListenAndServeTLS(*cert, *key))
}

Create a self-signed certificate with the helper that ships with Go, then start the server:

Terminal window
go run "$(go env GOROOT)/src/crypto/tls/generate_cert.go" --host localhost
go run ./examples/tls
curl -k --http2 https://localhost:8443/
hello over HTTP/2.0

When a proxy or load balancer terminates TLS, the server can still accept HTTP/2 from it without TLS. Run the example with -h2c: it sets http.Server.Protocols to accept HTTP/1 and unencrypted HTTP/2 on the same port.

fasthttp itself serves HTTP/1.x. Serve it over TLS with ListenAndServeTLS on a fasthttp.Server, or put it behind a proxy that speaks HTTP/2 to clients.