diff options
Diffstat (limited to 'client/go/internal/util/http.go')
-rw-r--r-- | client/go/internal/util/http.go | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/client/go/internal/util/http.go b/client/go/internal/util/http.go index b18f9a00c6a..cb35932c8e7 100644 --- a/client/go/internal/util/http.go +++ b/client/go/internal/util/http.go @@ -2,22 +2,22 @@ package util import ( + "bytes" "crypto/tls" "fmt" "net/http" "time" "github.com/vespa-engine/vespa/client/go/internal/build" + "golang.org/x/net/http2" ) type HTTPClient interface { Do(request *http.Request, timeout time.Duration) (response *http.Response, error error) - Transport() *http.Transport } type defaultHTTPClient struct { - client *http.Client - transport *http.Transport + client *http.Client } func (c *defaultHTTPClient) Do(request *http.Request, timeout time.Duration) (response *http.Response, error error) { @@ -31,24 +31,55 @@ func (c *defaultHTTPClient) Do(request *http.Request, timeout time.Duration) (re return c.client.Do(request) } -func (c *defaultHTTPClient) Transport() *http.Transport { return c.transport } - func SetCertificate(client HTTPClient, certificates []tls.Certificate) { - client.Transport().TLSClientConfig = &tls.Config{ - Certificates: certificates, - MinVersion: tls.VersionTLS12, + c, ok := client.(*defaultHTTPClient) + if !ok { + return + } + // Use HTTP/2 transport explicitly. Connection reuse does not work properly when using regular http.Transport, even + // though it upgrades to HTTP/2 automatically + // https://github.com/golang/go/issues/16582 + // https://github.com/golang/go/issues/22091 + var transport *http2.Transport + if _, ok := c.client.Transport.(*http.Transport); ok { + transport = &http2.Transport{} + c.client.Transport = transport + } else if t, ok := c.client.Transport.(*http2.Transport); ok { + transport = t + } else { + panic(fmt.Sprintf("unknown transport type: %T", c.client.Transport)) + } + if ok && !c.hasCertificates(transport.TLSClientConfig, certificates) { + transport.TLSClientConfig = &tls.Config{ + Certificates: certificates, + MinVersion: tls.VersionTLS12, + } } } -func CreateClient(timeout time.Duration) HTTPClient { - transport := http.Transport{ - ForceAttemptHTTP2: true, +func (c *defaultHTTPClient) hasCertificates(tlsConfig *tls.Config, certs []tls.Certificate) bool { + if tlsConfig == nil { + return false } - return &defaultHTTPClient{ - client: &http.Client{ - Timeout: timeout, - Transport: &transport, - }, - transport: &transport, + if len(tlsConfig.Certificates) != len(certs) { + return false } + for i := 0; i < len(certs); i++ { + if len(tlsConfig.Certificates[i].Certificate) != len(certs[i].Certificate) { + return false + } + for j := 0; j < len(certs[i].Certificate); j++ { + if !bytes.Equal(tlsConfig.Certificates[i].Certificate[j], certs[i].Certificate[j]) { + return false + } + } + } + return true +} + +func CreateClient(timeout time.Duration) HTTPClient { + return &defaultHTTPClient{client: &http.Client{ + Timeout: timeout, + Transport: http.DefaultTransport, + }} } |