git » go-net » commit be28236

http2: make Transport treat "Connection: close" the same as Request.Close

author Brad Fitzpatrick
2016-07-16 21:40:20 UTC
committer Brad Fitzpatrick
2016-07-17 05:54:02 UTC
parent 45b61eaf18dd5c1b942e7666ff170b77dbbaf87b

http2: make Transport treat "Connection: close" the same as Request.Close

Both "Connection: close" and Request.Close should mean the same thing:
to use the same connection.

The Request.Close case was fixed in https://golang.org/cl/24810 for
Request.Close but I forgot about "Connection: close". Unify the code.

Fixes flaky failures such as:
https://storage.googleapis.com/go-build-log/6adb97bd/freebsd-amd64-gce101_5c331c2a.log
(noticed by Ian on a https://golang.org/cl/24977 trybot run)

Updates golang/go#15612

Change-Id: I3ab5175b8bc528ee240370c906b00cc691651bb4
Reviewed-on: https://go-review.googlesource.com/24982
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

http2/client_conn_pool.go +1 -1
http2/transport.go +7 -1

diff --git a/http2/client_conn_pool.go b/http2/client_conn_pool.go
index 547e238..cb34cc2 100644
--- a/http2/client_conn_pool.go
+++ b/http2/client_conn_pool.go
@@ -53,7 +53,7 @@ const (
 )
 
 func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
-	if req.Close && dialOnMiss {
+	if isConnectionCloseRequest(req) && dialOnMiss {
 		// It gets its own connection.
 		cc, err := p.t.dialClientConn(addr)
 		if err != nil {
diff --git a/http2/transport.go b/http2/transport.go
index fb8dd99..de3f5fe 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -1593,7 +1593,7 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
 	}
 	cs.bufPipe.closeWithErrorAndCode(err, code)
 	delete(rl.activeRes, cs.ID)
-	if cs.req.Close || cs.req.Header.Get("Connection") == "close" {
+	if isConnectionCloseRequest(cs.req) {
 		rl.closeWhenIdle = true
 	}
 }
@@ -1866,3 +1866,9 @@ func (s bodyWriterState) scheduleBodyWrite() {
 		s.timer.Reset(s.delay)
 	}
 }
+
+// isConnectionCloseRequest reports whether req should use its own
+// connection for a single request and then close the connection.
+func isConnectionCloseRequest(req *http.Request) bool {
+	return req.Close || httplex.HeaderValuesContainsToken(req.Header["Connection"], "close")
+}