summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2023-04-04 14:10:24 +0200
committerMartin Polden <mpolden@mpolden.no>2023-04-11 10:27:09 +0200
commit0784bd1d2b2c887897b7750281a54ab57cb6badf (patch)
treea990a265a41ed23d5ca2df1c19b375a37641722c
parent572c7aca0aa865fb9ae3c211156dfa9efb8e548f (diff)
Always use HTTP/2 when feeding
-rw-r--r--client/go/internal/cli/cmd/feed.go1
-rw-r--r--client/go/internal/util/http.go66
-rw-r--r--client/go/internal/vespa/target.go9
3 files changed, 46 insertions, 30 deletions
diff --git a/client/go/internal/cli/cmd/feed.go b/client/go/internal/cli/cmd/feed.go
index c8e032929b8..97bee293077 100644
--- a/client/go/internal/cli/cmd/feed.go
+++ b/client/go/internal/cli/cmd/feed.go
@@ -56,6 +56,7 @@ func feed(r io.Reader, cli *CLI, concurrency int) error {
if err != nil {
return err
}
+ service.ForceHTTP2() // Feeding should always use HTTP/2
client := document.NewClient(document.ClientOptions{
BaseURL: service.BaseURL,
}, service)
diff --git a/client/go/internal/util/http.go b/client/go/internal/util/http.go
index cb35932c8e7..b1646b06a80 100644
--- a/client/go/internal/util/http.go
+++ b/client/go/internal/util/http.go
@@ -2,9 +2,10 @@
package util
import (
- "bytes"
+ "context"
"crypto/tls"
"fmt"
+ "net"
"net/http"
"time"
@@ -36,45 +37,50 @@ func SetCertificate(client HTTPClient, certificates []tls.Certificate) {
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{
+ var tlsConfig *tls.Config = nil
+ if certificates != nil {
+ tlsConfig = &tls.Config{
Certificates: certificates,
MinVersion: tls.VersionTLS12,
}
}
+ if tr, ok := c.client.Transport.(*http.Transport); ok {
+ tr.TLSClientConfig = tlsConfig
+ } else if tr, ok := c.client.Transport.(*http2.Transport); ok {
+ tr.TLSClientConfig = tlsConfig
+ } else {
+ panic(fmt.Sprintf("unknown transport type: %T", c.client.Transport))
+ }
}
-func (c *defaultHTTPClient) hasCertificates(tlsConfig *tls.Config, certs []tls.Certificate) bool {
- if tlsConfig == nil {
- return false
- }
- if len(tlsConfig.Certificates) != len(certs) {
- return false
+func ForceHTTP2(client HTTPClient, certificates []tls.Certificate) {
+ c, ok := client.(*defaultHTTPClient)
+ if !ok {
+ return
}
- for i := 0; i < len(certs); i++ {
- if len(tlsConfig.Certificates[i].Certificate) != len(certs[i].Certificate) {
- return false
+ var tlsConfig *tls.Config = nil
+ var dialFunc func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error)
+ if certificates != nil {
+ tlsConfig = &tls.Config{
+ Certificates: certificates,
+ MinVersion: tls.VersionTLS12,
}
- for j := 0; j < len(certs[i].Certificate); j++ {
- if !bytes.Equal(tlsConfig.Certificates[i].Certificate[j], certs[i].Certificate[j]) {
- return false
- }
+ } else {
+ // No certificate, so force H2C (HTTP/2 over clear-text) by using a non-TLS Dialer
+ dialer := net.Dialer{}
+ dialFunc = func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
+ return dialer.DialContext(ctx, network, addr)
}
}
- return true
+ // 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
+ c.client.Transport = &http2.Transport{
+ AllowHTTP: true,
+ TLSClientConfig: tlsConfig,
+ DialTLSContext: dialFunc,
+ }
}
func CreateClient(timeout time.Duration) HTTPClient {
diff --git a/client/go/internal/vespa/target.go b/client/go/internal/vespa/target.go
index 51861eb12ab..1ad36b1d799 100644
--- a/client/go/internal/vespa/target.go
+++ b/client/go/internal/vespa/target.go
@@ -119,6 +119,15 @@ func (s *Service) Wait(timeout time.Duration) (int, error) {
return waitForOK(s.httpClient, url, s.TLSOptions.KeyPair, timeout)
}
+// ForceHTTP2 forces the underlying HTTP client to use HTTP/2.
+func (s *Service) ForceHTTP2() {
+ var certs []tls.Certificate
+ if s.TLSOptions.KeyPair != nil {
+ certs = []tls.Certificate{*s.TLSOptions.KeyPair}
+ }
+ util.ForceHTTP2(s.httpClient, certs)
+}
+
func (s *Service) Description() string {
switch s.Name {
case QueryService: