Skip to content

Commit 5dbdd79

Browse files
gruszczybradfitz
authored andcommitted
net/http: Don't write 'Connection: close' header multiple times.
When writing the 'Connection: close' header based on response Close attribute we also check if it is already in the headers scheduled to be written and skip if necessary. Fixes #19499 Change-Id: I92357344a37ae385454ec8006114fa4cfa585810 Reviewed-on: https://go-review.googlesource.com/38076 Run-TryBot: Brad Fitzpatrick <[email protected]> Reviewed-by: Emmanuel Odeke <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 3b69c3b commit 5dbdd79

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/net/http/response_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,3 +949,29 @@ func TestNeedsSniff(t *testing.T) {
949949
t.Errorf("needsSniff empty Content-Type = %t; want %t", got, want)
950950
}
951951
}
952+
953+
// A response should only write out single Connection: close header. Tests #19499.
954+
func TestResponseWritesOnlySingleConnectionClose(t *testing.T) {
955+
const connectionCloseHeader = "Connection: close"
956+
957+
res, err := ReadResponse(bufio.NewReader(strings.NewReader("HTTP/1.0 200 OK\r\n\r\nAAAA")), nil)
958+
if err != nil {
959+
t.Fatalf("ReadResponse failed %v", err)
960+
}
961+
962+
var buf1 bytes.Buffer
963+
if err = res.Write(&buf1); err != nil {
964+
t.Fatalf("Write failed %v", err)
965+
}
966+
if res, err = ReadResponse(bufio.NewReader(&buf1), nil); err != nil {
967+
t.Fatalf("ReadResponse failed %v", err)
968+
}
969+
970+
var buf2 bytes.Buffer
971+
if err = res.Write(&buf2); err != nil {
972+
t.Fatalf("Write failed %v", err)
973+
}
974+
if count := strings.Count(buf2.String(), connectionCloseHeader); count != 1 {
975+
t.Errorf("Found %d %q header", count, connectionCloseHeader)
976+
}
977+
}

src/net/http/transfer.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type transferWriter struct {
7575
ContentLength int64 // -1 means unknown, 0 means exactly none
7676
Close bool
7777
TransferEncoding []string
78+
Header Header
7879
Trailer Header
7980
IsResponse bool
8081
bodyReadError error // any non-EOF error from reading Body
@@ -96,6 +97,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
9697
t.Method = valueOrDefault(rr.Method, "GET")
9798
t.Close = rr.Close
9899
t.TransferEncoding = rr.TransferEncoding
100+
t.Header = rr.Header
99101
t.Trailer = rr.Trailer
100102
atLeastHTTP11 = rr.protoAtLeastOutgoing(1, 1)
101103
t.Body = rr.Body
@@ -114,6 +116,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
114116
t.ContentLength = rr.ContentLength
115117
t.Close = rr.Close
116118
t.TransferEncoding = rr.TransferEncoding
119+
t.Header = rr.Header
117120
t.Trailer = rr.Trailer
118121
atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
119122
t.ResponseToHEAD = noResponseBodyExpected(t.Method)
@@ -266,7 +269,7 @@ func (t *transferWriter) shouldSendContentLength() bool {
266269
}
267270

268271
func (t *transferWriter) WriteHeader(w io.Writer) error {
269-
if t.Close {
272+
if t.Close && !hasToken(t.Header.get("Connection"), "close") {
270273
if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
271274
return err
272275
}

0 commit comments

Comments
 (0)