Please take a look and run the test snippet below.
import (
"crypto/tls"
"net/http"
"testing"
)
func TestClient(t *testing.T) {
config := tls.Config{InsecureSkipVerify: true}
transport1 := &http.Transport{
TLSClientConfig: &config,
}
client1 := &http.Client{Transport: transport1}
_, err1 := client1.Get("https://www.google.com")
if err1 != nil {
t.Error(err1)
}
transport2 := &http.Transport{
ForceAttemptHTTP2: true,
TLSClientConfig: &config,
}
client2 := &http.Client{Transport: transport2}
_, err2 := client2.Get("https://www.google.com")
if err2 != nil {
t.Error(err2)
}
_, err3 := client1.Get("https://www.google.com")
if err3 != nil {
t.Error(err3)
}
}
I created a singe tls.Config
object that is shared in two different http.Transport
objects. According to the following comment from the crypto/tls/common.go file, config explicitly allows reuse:
// A Config structure is used to configure a TLS client or server.
// After one has been passed to a TLS function it must not be
// modified. A Config may be reused; the tls package will also not
// modify it.
type Config struct {
One of the transport objects has ForceAttemptHTTP2
field set to true. I use those two http.Transport
objects to create two http.Client
objects and perform a Get request to www.google.com.
First, and second requests succeed. The third request attempt _, err3 := client1.Get("https://www.google.com")
errors out and causes the test to fail. It appears that using the client2
to perform a Get request breaks the client1
for some reason.
This behaviour seems wrong to me. Thoughts?