1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 func configureTransport(t1 *http.Transport) (*Transport, error) {
16 connPool := new(clientConnPool)
18 ConnPool: noDialClientConnPool{connPool},
22 if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
25 if t1.TLSClientConfig == nil {
26 t1.TLSClientConfig = new(tls.Config)
28 if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
29 t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
31 if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
32 t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
34 upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
35 addr := authorityAddr("https", authority)
36 if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
38 return erringRoundTripper{err}
40 // Turns out we don't need this c.
41 // For example, two goroutines made requests to the same host
42 // at the same time, both kicking off TCP dials. (since protocol
48 if m := t1.TLSNextProto; len(m) == 0 {
49 t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
58 // registerHTTPSProtocol calls Transport.RegisterProtocol but
59 // converting panics into errors.
60 func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
62 if e := recover(); e != nil {
63 err = fmt.Errorf("%v", e)
66 t.RegisterProtocol("https", rt)
70 // noDialH2RoundTripper is a RoundTripper which only tries to complete the request
71 // if there's already has a cached connection to the host.
72 type noDialH2RoundTripper struct{ t *Transport }
74 func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
75 res, err := rt.t.RoundTrip(req)
76 if err == ErrNoCachedConn {
77 return nil, http.ErrSkipAltProtocol