]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: enable HTTP/2 support in DefaultTransport
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 5 Nov 2015 09:28:28 +0000 (10:28 +0100)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sat, 7 Nov 2015 13:35:36 +0000 (13:35 +0000)
The GODEBUG option remains, for now, but only for turning it off.
We'll decide what to do with it before release.

This CL includes the dependent http2 change (https://golang.org/cl/16692)
in the http2 bundle (h2_bundle.go).

Updates golang/go#6891

Change-Id: If9723ef627c7ba4f7343dc8cb89ca88ef0fbcb10
Reviewed-on: https://go-review.googlesource.com/16693
Reviewed-by: Blake Mizerany <blake.mizerany@gmail.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/net/http/h2_bundle.go
src/net/http/transport.go

index 9a722e752ae67d88662cc60cd53f7dced6c0bf4d..d6e749f8cdafe587e9250de23efd577138bbbf87 100644 (file)
@@ -3585,7 +3585,23 @@ func (sew http2stickyErrWriter) Write(p []byte) (n int, err error) {
        return
 }
 
+var http2ErrNoCachedConn = errors.New("http2: no cached connection was available")
+
+// RoundTripOpt are options for the Transport.RoundTripOpt method.
+type http2RoundTripOpt struct {
+       // OnlyCachedConn controls whether RoundTripOpt may
+       // create a new TCP connection. If set true and
+       // no cached connection is available, RoundTripOpt
+       // will return ErrNoCachedConn.
+       OnlyCachedConn bool
+}
+
 func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
+       return t.RoundTripOpt(req, http2RoundTripOpt{})
+}
+
+// RoundTripOpt is like RoundTrip, but takes options.
+func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Response, error) {
        if req.URL.Scheme != "https" {
                return nil, errors.New("http2: unsupported scheme")
        }
@@ -3597,7 +3613,7 @@ func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
        }
 
        for {
-               cc, err := t.getClientConn(host, port)
+               cc, err := t.getClientConn(host, port, opt.OnlyCachedConn)
                if err != nil {
                        return nil, err
                }
@@ -3692,7 +3708,7 @@ func (t *http2Transport) addConn(key string, cc *http2clientConn) {
        t.conns[key] = append(t.conns[key], cc)
 }
 
-func (t *http2Transport) getClientConn(host, port string) (*http2clientConn, error) {
+func (t *http2Transport) getClientConn(host, port string, onlyCached bool) (*http2clientConn, error) {
        key := net.JoinHostPort(host, port)
 
        t.connMu.Lock()
@@ -3703,6 +3719,9 @@ func (t *http2Transport) getClientConn(host, port string) (*http2clientConn, err
                }
        }
        t.connMu.Unlock()
+       if onlyCached {
+               return nil, http2ErrNoCachedConn
+       }
 
        cc, err := t.dialClientConn(host, port, key)
        if err != nil {
index ad8aa19c2e49af7fe35e2bacef6e4cf084fcadeb..809f6de2892bf10e991f6bafdc19a698db693393 100644 (file)
@@ -44,23 +44,21 @@ var DefaultTransport RoundTripper = &Transport{
        ExpectContinueTimeout: 1 * time.Second,
 }
 
+// Wire up HTTP/2 support to the DefaultTransport, unless GODEBUG=h2client=0.
 func init() {
-       // TODO(bradfitz,adg): remove the following line before Go 1.6
-       // ships.  This just gives us a mechanism to temporarily
-       // enable the http2 client during development.
-       if !strings.Contains(os.Getenv("GODEBUG"), "h2client=1") {
+       if strings.Contains(os.Getenv("GODEBUG"), "h2client=0") {
                return
        }
-
        t := DefaultTransport.(*Transport)
-
-       // TODO(bradfitz,adg): move all this up to DefaultTransport before Go 1.6:
        t.RegisterProtocol("https", noDialH2Transport{h2DefaultTransport})
        t.TLSClientConfig = &tls.Config{
                NextProtos: []string{"h2"},
        }
        t.TLSNextProto = map[string]func(string, *tls.Conn) RoundTripper{
-               "h2": http2TransportForConn,
+               "h2": func(authority string, c *tls.Conn) RoundTripper {
+                       h2DefaultTransport.AddIdleConn(authority, c)
+                       return h2DefaultTransport
+               },
        }
 }
 
@@ -69,14 +67,11 @@ func init() {
 type noDialH2Transport struct{ rt *http2Transport }
 
 func (t noDialH2Transport) RoundTrip(req *Request) (*Response, error) {
-       // TODO(bradfitz): wire up http2.Transport
-       return nil, ErrSkipAltProtocol
-}
-
-func http2TransportForConn(authority string, c *tls.Conn) RoundTripper {
-       // TODO(bradfitz): donate c to h2DefaultTransport:
-       // h2DefaultTransport.AddIdleConn(authority, c)
-       return h2DefaultTransport
+       res, err := t.rt.RoundTripOpt(req, http2RoundTripOpt{OnlyCachedConn: true})
+       if err == http2ErrNoCachedConn {
+               return nil, ErrSkipAltProtocol
+       }
+       return res, err
 }
 
 // DefaultMaxIdleConnsPerHost is the default value of Transport's