Description
What version of Go are you using (go version
)?
1.7.3
What operating system and processor architecture are you using (go env
)?
darwin amd64
What did you do?
My first attempt to use a TLS client certificate for authenticating towards a http/2 only server looked something like this:
cert, err := tls.LoadX509KeyPair(pub, key)
if err != nil {
return err
}
config := &tls.Config{
Certificates: []tls.Certificate{cert},
}
config.BuildNameToCertificate()
tr := http.Transport{
TLSClientConfig: config,
}
client := &http.Client{
Transport: &tr,
}
res, err := client.Do(req)
This code results in a HTTP/1.1 transport.
My 2nd attempt was to also define the NextProto
:
config := &tls.Config{
Certificates: []tls.Certificate{cert},
NextProtos: []string{"h2"},
}
What did you expect to see?
I expected the http/2 upgrade to work seamlessly even with my custom client certificate specified.
This is how I've been authenticating with previous HTTP versions, I didn't expect the API to change.
What did you see instead?
Since the targeted server only supports HTTP/2, the returned request error was rather confusing:
malformed HTTP status code "client"
.
After reading the source of how the transport handling works for h2, I found these lines in net/http/transport.go:
200 if t.TLSClientConfig != nil || t.Dial != nil || t.DialTLS != nil {
201 // Be conservative and don't automatically enable
202 // http2 if they've specified a custom TLS config or
203 // custom dialers. Let them opt-in themselves via
204 // http2.ConfigureTransport so we don't surprise them
205 // by modifying their tls.Config. Issue 14275.
206 return
207 }
It refers to http2.ConfigureTransport, which is part of the external import golang.org/x/net/http2
.
Importing and using this on my transport indeed fixed my problem.
To my surprise, I could not find any exported functionality in the standard library like this. I feel that it should be there, to make the http/2 client support complete.