0

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?

1
  • tlsConfig which you don't list here might be part of the problem. The client might announce via ALPN that it wants to speak HTTP/2, where in reality it doesn't do. Apart from that there looks nothing wrong with that code. Commented Aug 2, 2019 at 16:52

1 Answer 1

2

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:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.