lib/discover: Enable HTTP/2 for global discovery requests (#9059)

By creating the http.Transport and tls.Configuration ourselves we
override some default behavior and end up with a client that speaks only
HTTP/1.1.

This adds a call to http.ConfigureTransport to do the relevant magic to
enable HTTP/2.

Also tweaks the keepalive settings to be a little kinder to the
server(s).
This commit is contained in:
Jakob Borg 2023-08-30 21:58:05 +02:00 committed by GitHub
parent a80e6be353
commit abd89f15f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -25,6 +25,7 @@ import (
"github.com/syncthing/syncthing/lib/dialer" "github.com/syncthing/syncthing/lib/dialer"
"github.com/syncthing/syncthing/lib/events" "github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
"golang.org/x/net/http2"
) )
type globalClient struct { type globalClient struct {
@ -107,14 +108,16 @@ func NewGlobal(server string, cert tls.Certificate, addrList AddressLister, evLo
} }
var announceClient httpClient = &contextClient{&http.Client{ var announceClient httpClient = &contextClient{&http.Client{
Timeout: requestTimeout, Timeout: requestTimeout,
Transport: &http.Transport{ Transport: http2EnabledTransport(&http.Transport{
DialContext: dialContext, DialContext: dialContext,
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
DisableKeepAlives: true, // announcements are few and far between, so don't keep the connection open
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: opts.insecure, InsecureSkipVerify: opts.insecure,
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
}, },
}, }),
}} }}
if opts.id != "" { if opts.id != "" {
announceClient = newIDCheckingHTTPClient(announceClient, devID) announceClient = newIDCheckingHTTPClient(announceClient, devID)
@ -124,13 +127,15 @@ func NewGlobal(server string, cert tls.Certificate, addrList AddressLister, evLo
// certificate here, so lets not include it. May be insecure if requested. // certificate here, so lets not include it. May be insecure if requested.
var queryClient httpClient = &contextClient{&http.Client{ var queryClient httpClient = &contextClient{&http.Client{
Timeout: requestTimeout, Timeout: requestTimeout,
Transport: &http.Transport{ Transport: http2EnabledTransport(&http.Transport{
DialContext: dialer.DialContext, DialContext: dialer.DialContext,
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
IdleConnTimeout: time.Second,
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: opts.insecure, InsecureSkipVerify: opts.insecure,
MinVersion: tls.VersionTLS12,
}, },
}, }),
}} }}
if opts.id != "" { if opts.id != "" {
queryClient = newIDCheckingHTTPClient(queryClient, devID) queryClient = newIDCheckingHTTPClient(queryClient, devID)
@ -176,7 +181,7 @@ func (c *globalClient) Lookup(ctx context.Context, device protocol.DeviceID) (ad
l.Debugln("globalClient.Lookup", qURL, err) l.Debugln("globalClient.Lookup", qURL, err)
return nil, err return nil, err
} }
if resp.StatusCode != 200 { if resp.StatusCode != http.StatusOK {
resp.Body.Close() resp.Body.Close()
l.Debugln("globalClient.Lookup", qURL, resp.Status) l.Debugln("globalClient.Lookup", qURL, resp.Status)
err := errors.New(resp.Status) err := errors.New(resp.Status)
@ -437,7 +442,7 @@ type contextClient struct {
} }
func (c *contextClient) Get(ctx context.Context, url string) (*http.Response, error) { func (c *contextClient) Get(ctx context.Context, url string) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -445,7 +450,7 @@ func (c *contextClient) Get(ctx context.Context, url string) (*http.Response, er
} }
func (c *contextClient) Post(ctx context.Context, url, ctype string, data io.Reader) (*http.Response, error) { func (c *contextClient) Post(ctx context.Context, url, ctype string, data io.Reader) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, "POST", url, data) req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -464,3 +469,8 @@ func ipv4Identity(port int) string {
func ipv6Identity(addr string) string { func ipv6Identity(addr string) string {
return fmt.Sprintf("IPv6 local multicast discovery on address %s", addr) return fmt.Sprintf("IPv6 local multicast discovery on address %s", addr)
} }
func http2EnabledTransport(t *http.Transport) *http.Transport {
_ = http2.ConfigureTransport(t)
return t
}