github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/http2/configure_transport.go (about) 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. 4 5 // +build go1.6 6 7 package http2 8 9 import ( 10 "crypto/tls" 11 "fmt" 12 "net/http" 13 ) 14 15 func configureTransport(t1 *http.Transport) error { 16 connPool := new(clientConnPool) 17 t2 := &Transport{ConnPool: noDialClientConnPool{connPool}} 18 if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil { 19 return err 20 } 21 if t1.TLSClientConfig == nil { 22 t1.TLSClientConfig = new(tls.Config) 23 } 24 if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") { 25 t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...) 26 } 27 if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") { 28 t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1") 29 } 30 upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper { 31 cc, err := t2.NewClientConn(c) 32 if err != nil { 33 c.Close() 34 return erringRoundTripper{err} 35 } 36 connPool.addConn(authorityAddr(authority), cc) 37 return t2 38 } 39 if m := t1.TLSNextProto; len(m) == 0 { 40 t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{ 41 "h2": upgradeFn, 42 } 43 } else { 44 m["h2"] = upgradeFn 45 } 46 return nil 47 } 48 49 // registerHTTPSProtocol calls Transport.RegisterProtocol but 50 // convering panics into errors. 51 func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) { 52 defer func() { 53 if e := recover(); e != nil { 54 err = fmt.Errorf("%v", e) 55 } 56 }() 57 t.RegisterProtocol("https", rt) 58 return nil 59 } 60 61 // noDialClientConnPool is an implementation of http2.ClientConnPool 62 // which never dials. We let the HTTP/1.1 client dial and use its TLS 63 // connection instead. 64 type noDialClientConnPool struct{ *clientConnPool } 65 66 func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) { 67 const doDial = false 68 return p.getClientConn(req, addr, doDial) 69 } 70 71 // noDialH2RoundTripper is a RoundTripper which only tries to complete the request 72 // if there's already has a cached connection to the host. 73 type noDialH2RoundTripper struct{ t *Transport } 74 75 func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { 76 res, err := rt.t.RoundTrip(req) 77 if err == ErrNoCachedConn { 78 return nil, http.ErrSkipAltProtocol 79 } 80 return res, err 81 }