Skip to content

Commit 9bad995

Browse files
committed
net/http: enable HTTP/2 on all Transports, not just the DefaultTransport
This mirrors the same behavior and API from the server code to the client side: if TLSNextProto is nil, HTTP/2 is on by default for both. If it's non-nil, the user was trying to do something fancy and step out of their way. Updates golang#6891 Change-Id: Ia31808b71f336a8d5b44b985591d72113429e1d4 Reviewed-on: https://go-review.googlesource.com/17300 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 3b3f422 commit 9bad995

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

src/net/http/transport.go

+19-9
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,6 @@ var DefaultTransport RoundTripper = &Transport{
4040
ExpectContinueTimeout: 1 * time.Second,
4141
}
4242

43-
func init() {
44-
if !strings.Contains(os.Getenv("GODEBUG"), "h2client=0") {
45-
err := http2ConfigureTransport(DefaultTransport.(*Transport))
46-
if err != nil {
47-
panic(err)
48-
}
49-
}
50-
}
51-
5243
// DefaultMaxIdleConnsPerHost is the default value of Transport's
5344
// MaxIdleConnsPerHost.
5445
const DefaultMaxIdleConnsPerHost = 2
@@ -138,12 +129,30 @@ type Transport struct {
138129
// called with the request's authority (such as "example.com"
139130
// or "example.com:1234") and the TLS connection. The function
140131
// must return a RoundTripper that then handles the request.
132+
// If TLSNextProto is nil, HTTP/2 support is enabled automatically.
141133
TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
142134

135+
nextProtoOnce sync.Once // guards initialization of TLSNextProto (onceSetNextProtoDefaults)
136+
143137
// TODO: tunable on global max cached connections
144138
// TODO: tunable on timeout on cached connections
145139
}
146140

141+
// onceSetNextProtoDefaults initializes TLSNextProto.
142+
// It must be called via t.nextProtoOnce.Do.
143+
func (t *Transport) onceSetNextProtoDefaults() {
144+
if strings.Contains(os.Getenv("GODEBUG"), "h2client=0") {
145+
return
146+
}
147+
if t.TLSNextProto != nil {
148+
return
149+
}
150+
err := http2ConfigureTransport(t)
151+
if err != nil {
152+
log.Printf("Error enabling Transport HTTP/2 support: %v", err)
153+
}
154+
}
155+
147156
// ProxyFromEnvironment returns the URL of the proxy to use for a
148157
// given request, as indicated by the environment variables
149158
// HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the lowercase versions
@@ -216,6 +225,7 @@ func (tr *transportRequest) extraHeaders() Header {
216225
// For higher-level HTTP client support (such as handling of cookies
217226
// and redirects), see Get, Post, and the Client type.
218227
func (t *Transport) RoundTrip(req *Request) (*Response, error) {
228+
t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
219229
if req.URL == nil {
220230
req.closeBody()
221231
return nil, errors.New("http: nil Request.URL")

src/net/http/transport_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,27 @@ func TestTransportPrefersResponseOverWriteError(t *testing.T) {
29212921
}
29222922
}
29232923

2924+
func TestTransportAutomaticHTTP2(t *testing.T) {
2925+
tr := &Transport{}
2926+
_, err := tr.RoundTrip(new(Request))
2927+
if err == nil {
2928+
t.Error("expected error from RoundTrip")
2929+
}
2930+
if tr.TLSNextProto["h2"] == nil {
2931+
t.Errorf("HTTP/2 not registered.")
2932+
}
2933+
2934+
// Now with TLSNextProto set:
2935+
tr = &Transport{TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper)}
2936+
_, err = tr.RoundTrip(new(Request))
2937+
if err == nil {
2938+
t.Error("expected error from RoundTrip")
2939+
}
2940+
if tr.TLSNextProto["h2"] != nil {
2941+
t.Errorf("HTTP/2 registered, despite non-nil TLSNextProto field")
2942+
}
2943+
}
2944+
29242945
func wantBody(res *Response, err error, want string) error {
29252946
if err != nil {
29262947
return err

0 commit comments

Comments
 (0)