gohttp2

How to disable HTTP/2 using Server.TLSNextProto


I have a Go server handling https requests:

package main
import (
        "fmt"
        "net/http"
        "log"
)
const (
        port       = "5966"
        cert       = "/tmp/cert.pem"
        key        = "/tmp/key.pem"
)
func main() {

        listen_at := ":" + port
        fmt.Println("Listening at", listen_at)
        go http.HandleFunc("/job_handler/", job_handler)
        log.Fatal(http.ListenAndServeTLS(listen_at, cert, key, nil))
}
func job_handler(w http.ResponseWriter, r *http.Request) {
       // do somework
}

Turns out in https mode, Go has transparent support for the HTTP/2 protocol. We've some clients that noticeably misbehave in HTTP/2, and hence we need to disable HTTP/2 on the server side.

Unfortunately, I can't use ENV variable GODEBUG=http2server=0 to disable HTTP/2. What's left is Server.TLSNextProto as documented here.

How can I use Server.TLSNextProto on my server code above to disable https/2?


Solution

  • The simplest setup that disables HTTP/2 is

    package main
    
    import (
        "log"
        "net/http"
        "crypto/tls"
    )
    
    func main() {
    
        m := http.NewServeMux()
    
        srv := &http.Server{
            Handler:      m,
            Addr:         "127.0.0.1:8080",
            TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
        }
    
        log.Fatal(srv.ListenAndServe())
    
    }
    

    You can verify the support with

    curl -v --http2-prior-knowledge http://localhost:8080