Commit b3bf2e78 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: update bundled http2

Updates x/net/http2 to git rev 8a52c78 for golang.org/cl/23258
(http2: fix Transport.CloseIdleConnections when http1+http2 are wired together)

Fixes #14607

Change-Id: I038badc69e230715b8ce4e398eb5e6ede73af918
Reviewed-on: https://go-review.googlesource.com/23280Reviewed-by: default avatarAndrew Gerrand <adg@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 1ded9fdc
......@@ -1196,6 +1196,35 @@ func TestH12_AutoGzipWithDumpResponse(t *testing.T) {
}.run(t)
}
// Issue 14607
func TestCloseIdleConnections_h1(t *testing.T) { testCloseIdleConnections(t, h1Mode) }
func TestCloseIdleConnections_h2(t *testing.T) { testCloseIdleConnections(t, h2Mode) }
func testCloseIdleConnections(t *testing.T, h2 bool) {
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("X-Addr", r.RemoteAddr)
}))
defer cst.close()
get := func() string {
res, err := cst.c.Get(cst.ts.URL)
if err != nil {
t.Fatal(err)
}
res.Body.Close()
v := res.Header.Get("X-Addr")
if v == "" {
t.Fatal("didn't get X-Addr")
}
return v
}
a1 := get()
cst.tr.CloseIdleConnections()
a2 := get()
if a1 == a2 {
t.Errorf("didn't close connection")
}
}
type noteCloseConn struct {
net.Conn
closeFunc func()
......
......@@ -15,17 +15,16 @@ import (
)
var (
DefaultUserAgent = defaultUserAgent
NewLoggingConn = newLoggingConn
ExportAppendTime = appendTime
ExportRefererForURL = refererForURL
ExportServerNewConn = (*Server).newConn
ExportCloseWriteAndWait = (*conn).closeWriteAndWait
ExportErrRequestCanceled = errRequestCanceled
ExportErrRequestCanceledConn = errRequestCanceledConn
ExportServeFile = serveFile
ExportHttp2ConfigureTransport = http2ConfigureTransport
ExportHttp2ConfigureServer = http2ConfigureServer
DefaultUserAgent = defaultUserAgent
NewLoggingConn = newLoggingConn
ExportAppendTime = appendTime
ExportRefererForURL = refererForURL
ExportServerNewConn = (*Server).newConn
ExportCloseWriteAndWait = (*conn).closeWriteAndWait
ExportErrRequestCanceled = errRequestCanceled
ExportErrRequestCanceledConn = errRequestCanceledConn
ExportServeFile = serveFile
ExportHttp2ConfigureServer = http2ConfigureServer
)
func init() {
......@@ -152,3 +151,12 @@ func hookSetter(dst *func()) func(func()) {
*dst = fn
}
}
func ExportHttp2ConfigureTransport(t *Transport) error {
t2, err := http2configureTransport(t)
if err != nil {
return err
}
t.h2transport = t2
return nil
}
......@@ -50,6 +50,18 @@ type http2ClientConnPool interface {
MarkDead(*http2ClientConn)
}
// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
// implementations which can close their idle connections.
type http2clientConnPoolIdleCloser interface {
http2ClientConnPool
closeIdleConnections()
}
var (
_ http2clientConnPoolIdleCloser = (*http2clientConnPool)(nil)
_ http2clientConnPoolIdleCloser = http2noDialClientConnPool{}
)
// TODO: use singleflight for dialing and addConnCalls?
type http2clientConnPool struct {
t *http2Transport
......@@ -250,6 +262,15 @@ func http2filterOutClientConn(in []*http2ClientConn, exclude *http2ClientConn) [
return out
}
// noDialClientConnPool is an implementation of http2.ClientConnPool
// which never dials. We let the HTTP/1.1 client dial and use its TLS
// connection instead.
type http2noDialClientConnPool struct{ *http2clientConnPool }
func (p http2noDialClientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) {
return p.getClientConn(req, addr, http2noDialOnMiss)
}
func http2configureTransport(t1 *Transport) (*http2Transport, error) {
connPool := new(http2clientConnPool)
t2 := &http2Transport{
......@@ -302,15 +323,6 @@ func http2registerHTTPSProtocol(t *Transport, rt RoundTripper) (err error) {
return nil
}
// noDialClientConnPool is an implementation of http2.ClientConnPool
// which never dials. We let the HTTP/1.1 client dial and use its TLS
// connection instead.
type http2noDialClientConnPool struct{ *http2clientConnPool }
func (p http2noDialClientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) {
return p.getClientConn(req, addr, http2noDialOnMiss)
}
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
// if there's already has a cached connection to the host.
type http2noDialH2RoundTripper struct{ t *http2Transport }
......@@ -5054,7 +5066,7 @@ func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Res
// connected from previous requests but are now sitting idle.
// It does not interrupt any connections currently in use.
func (t *http2Transport) CloseIdleConnections() {
if cp, ok := t.connPool().(*http2clientConnPool); ok {
if cp, ok := t.connPool().(http2clientConnPoolIdleCloser); ok {
cp.closeIdleConnections()
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment