aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/transport_test.go
diff options
context:
space:
mode:
authorMeng Zhuo <mengzhuo1203@gmail.com>2018-11-27 16:16:43 +0800
committerBrad Fitzpatrick <bradfitz@golang.org>2018-11-28 21:33:21 +0000
commit9aadbf5755dc8e3c3b0a224f513c92b804a1a3a7 (patch)
treeb2f0bece0b962e59469027ee43a86c52a08c8009 /src/net/http/transport_test.go
parent4f15b54780af7159732794f9d67c9a8a455bbf61 (diff)
downloadgo-9aadbf5755dc8e3c3b0a224f513c92b804a1a3a7.tar.gz
go-9aadbf5755dc8e3c3b0a224f513c92b804a1a3a7.zip
net/http: prevent transport sends two "Connection: close" headers
There are three functions that do Connection header write: 1. transport.go/ persistConn.roundTrip 2. transfer.go/ transferWriter.writeHeader 3. request.go/ Request.write The root cause is roundTrip didn't lookup into request.Close and transferWriter didn't take care of extraHeaders. Fixes #28886 Change-Id: I1d131019c7cd42eb1bcc972c631b7df7511c1f39 Reviewed-on: https://go-review.googlesource.com/c/150722 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/http/transport_test.go')
-rw-r--r--src/net/http/transport_test.go54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 22ca3f9550..1021ce5aa2 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -41,6 +41,8 @@ import (
"sync/atomic"
"testing"
"time"
+
+ "golang_org/x/net/http/httpguts"
)
// TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
@@ -310,6 +312,58 @@ func TestTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T) {
}
}
+// Test that Transport only sends one "Connection: close", regardless of
+// how "close" was indicated.
+func TestTransportRespectRequestWantsClose(t *testing.T) {
+ tests := []struct {
+ disableKeepAlives bool
+ close bool
+ }{
+ {disableKeepAlives: false, close: false},
+ {disableKeepAlives: false, close: true},
+ {disableKeepAlives: true, close: false},
+ {disableKeepAlives: true, close: true},
+ }
+
+ for _, tc := range tests {
+ t.Run(fmt.Sprintf("DisableKeepAlive=%v,RequestClose=%v", tc.disableKeepAlives, tc.close),
+ func(t *testing.T) {
+ defer afterTest(t)
+ ts := httptest.NewServer(hostPortHandler)
+ defer ts.Close()
+
+ c := ts.Client()
+ c.Transport.(*Transport).DisableKeepAlives = tc.disableKeepAlives
+ req, err := NewRequest("GET", ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ count := 0
+ trace := &httptrace.ClientTrace{
+ WroteHeaderField: func(key string, field []string) {
+ if key != "Connection" {
+ return
+ }
+ if httpguts.HeaderValuesContainsToken(field, "close") {
+ count += 1
+ }
+ },
+ }
+ req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
+ req.Close = tc.close
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if want := tc.disableKeepAlives || tc.close; count > 1 || (count == 1) != want {
+ t.Errorf("expecting want:%v, got 'Connection: close':%d", want, count)
+ }
+ })
+ }
+
+}
+
func TestTransportIdleCacheKeys(t *testing.T) {
defer afterTest(t)
ts := httptest.NewServer(hostPortHandler)