山田剛司
山田剛司

Reputation: 1

What makes http.server use HTTP/2?

I have made two Go programs, each of them tries to send a request to each other over TLS. In other words, two programs act as both client and server. However, first client host tries to connect to the server host using HTTP/1.1, whereas server host listens using HTTP/2, which leads to an error.

Program A

client := &http.Client{
    Transport: &http.Transport{
        TLSClientConfig: tlsConfig,
    },
}
mux := httprouter.New()
mux.GET("/test", test)
serverTLS := &http.Server{
    Addr:      "127.0.0.1:8081",
    Handler:   mux,
    TLSConfig: tlsConfig,
}

go func() {
    serverTLS.ListenAndServeTLS("", "")
}()

fmt.Println("test")
r, err := client.Get("https://127.0.0.1:8080/test")
if err != nil {
    log.Fatalln("Failed to connect testService over TLS : ", err)
}
defer r.Body.Close()
b, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(b))

time.Sleep(time.Second * 15)

Program B

client := &http.Client{
    Transport: &http.Transport{
        TLSClientConfig: tlsConfig,
    },
}

mux := httprouter.New()
mux.GET("/test", test)
serverTLS := &http.Server{
    Addr:      "127.0.0.1:8080",
    Handler:   mux,
    TLSConfig: tlsConfig,
}

go func() {
    serverTLS.ListenAndServeTLS("", "")
}()

time.Sleep(time.Second * 10)

r, err := client.Get("https://127.0.0.1:8081/test")
if err != nil {
    log.Fatalln("Failed to connect testService over TLS : ", err)
}
defer r.Body.Close()
b, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(b))

error message from program B (server)

http2: server: error reading preface from client 127.0.0.1:34854: bogus greeting "GET /test HTTP/1.1\r\nHost"

Then, to specify bugs, I made two programs shorter by limiting their jobs to either of client or server.

Program A' (Server)

//setup server
mux := httprouter.New()
mux.GET("/test", test)
serverTLS := &http.Server{
    Addr:      "127.0.0.1:8080",
    Handler:   mux,
    TLSConfig: tlsConfig,
}

go func() {
    serverTLS.ListenAndServeTLS("", "")
}()

time.Sleep(time.Second * 10)

Program B' (Client)

//setup client
client := &http.Client{
    Transport: &http.Transport{
        TLSClientConfig: tlsConfig,
    },
}

fmt.Println("test")
r, err := client.Get("https://127.0.0.1:8080/test")
if err != nil {
    log.Fatalln("Failed to connect testService over TLS : ", err)
}
defer r.Body.Close()
b, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(b))

This time, they work without an error. The communication between two hosts are done by HTTP/1.1. Could someone explain what changed the situation? What did force the Program B to use HTTP/2?

Upvotes: 0

Views: 2100

Answers (1)

Ketul
Ketul

Reputation: 31

As per net/http:

Starting with Go 1.6, the http package has transparent support for the HTTP/2 protocol when using HTTPS. Programs that must disable HTTP/2 can do so by setting Transport.TLSNextProto (for clients) or Server.TLSNextProto (for servers) to a non-nil, empty map. Alternatively, the following GODEBUG environment variables are currently supported:

Upvotes: 2

Related Questions