Files
JAYICEandGitHub 662d5298f4 lib/httputl: fix failing to access http2 sd service by the shadow copy of http.DefaultTransport
Clone `http.DefaultTransport` and disable HTTP2 without resetting
`TLSClientConfig.NextProtos` in the shadow copy of
`http.DefaultTransport` will cause the request to HTTP/2 server to fail.
See https://github.com/golang/go/issues/39302.

To reproduce it, use a scrape config like:
```
scrape_configs:
  - job_name: test
    yandexcloud_sd_configs:
      - service: compute
        api_endpoint: https://api.cloud.yandex.net
```
Before the fix, access to the SD service would fail.

A solution is to specify `http/1.1` in  `TLSClientConfig.NextProtos`.

Related golang issue: https://github.com/golang/go/issues/39302

fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9981
2025-11-13 17:19:15 +01:00

39 lines
1.6 KiB
Go

package httputil
import (
"net/http"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/netutil"
)
// NewTransport returns pre-initialized http.Transport with sane defaults.
//
// Data transfer for the returned transport is tracked with metrics, which are exposed with the given metricsPrefix.
//
// It is OK to change settings of the returned transport before its' usage.
//
// If enableHTTP2 is set, then the returned transport is ready for http2 requests.
//
// It is recommended disabling http2 support, since it is too bloated, slow and contains many security breaches.
// See https://www.google.com/search?q=http2+security+issues .
// Also, http2 doesn't bring any advantages over http/1.1 when communicating with server backends.
func NewTransport(enableHTTP2 bool, metricsPrefix string) *http.Transport {
tr := http.DefaultTransport.(*http.Transport).Clone()
tr.DialContext = netutil.NewStatDialFunc(metricsPrefix)
if !enableHTTP2 {
// Disable automatically enabled http2
tr.ForceAttemptHTTP2 = false
tr.TLSNextProto = nil
tr.Protocols = nil
// Clone http.DefaultTransport and disable HTTP/2 without resetting TLSClientConfig.NextProtos will cause the request to HTTP/2 server to fail.
// See https://github.com/golang/go/issues/39302
//
// Explicitly specify client supported protocol here
// The identification sequence for http1.1 and http2 are "http/1.1" and "h2", respectively.
// According https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
tr.TLSClientConfig.NextProtos = []string{"http/1.1"}
}
return tr
}