]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: Don't write 'Connection: close' header multiple times.
authorFilip GruszczyƄski <gruszczy@gmail.com>
Sat, 11 Mar 2017 21:38:14 +0000 (13:38 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 24 May 2017 04:53:50 +0000 (04:53 +0000)
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 <bradfitz@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/net/http/response_test.go
src/net/http/transfer.go

index 8b8c90ef509cfe11dc4f15baef9beec65399b34f..f1a50bd59891ae62dcd890daeced95b6129fb112 100644 (file)
@@ -949,3 +949,29 @@ func TestNeedsSniff(t *testing.T) {
                t.Errorf("needsSniff empty Content-Type = %t; want %t", got, want)
        }
 }
+
+// A response should only write out single Connection: close header. Tests #19499.
+func TestResponseWritesOnlySingleConnectionClose(t *testing.T) {
+       const connectionCloseHeader = "Connection: close"
+
+       res, err := ReadResponse(bufio.NewReader(strings.NewReader("HTTP/1.0 200 OK\r\n\r\nAAAA")), nil)
+       if err != nil {
+               t.Fatalf("ReadResponse failed %v", err)
+       }
+
+       var buf1 bytes.Buffer
+       if err = res.Write(&buf1); err != nil {
+               t.Fatalf("Write failed %v", err)
+       }
+       if res, err = ReadResponse(bufio.NewReader(&buf1), nil); err != nil {
+               t.Fatalf("ReadResponse failed %v", err)
+       }
+
+       var buf2 bytes.Buffer
+       if err = res.Write(&buf2); err != nil {
+               t.Fatalf("Write failed %v", err)
+       }
+       if count := strings.Count(buf2.String(), connectionCloseHeader); count != 1 {
+               t.Errorf("Found %d %q header", count, connectionCloseHeader)
+       }
+}
index 2a021154c95e1986434cd9b74da5c9738766d437..f87f80f51bc1ce27ff5370994aef3600549a52ad 100644 (file)
@@ -75,6 +75,7 @@ type transferWriter struct {
        ContentLength    int64 // -1 means unknown, 0 means exactly none
        Close            bool
        TransferEncoding []string
+       Header           Header
        Trailer          Header
        IsResponse       bool
        bodyReadError    error // any non-EOF error from reading Body
@@ -96,6 +97,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
                t.Method = valueOrDefault(rr.Method, "GET")
                t.Close = rr.Close
                t.TransferEncoding = rr.TransferEncoding
+               t.Header = rr.Header
                t.Trailer = rr.Trailer
                atLeastHTTP11 = rr.protoAtLeastOutgoing(1, 1)
                t.Body = rr.Body
@@ -114,6 +116,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
                t.ContentLength = rr.ContentLength
                t.Close = rr.Close
                t.TransferEncoding = rr.TransferEncoding
+               t.Header = rr.Header
                t.Trailer = rr.Trailer
                atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
                t.ResponseToHEAD = noResponseBodyExpected(t.Method)
@@ -266,7 +269,7 @@ func (t *transferWriter) shouldSendContentLength() bool {
 }
 
 func (t *transferWriter) WriteHeader(w io.Writer) error {
-       if t.Close {
+       if t.Close && !hasToken(t.Header.get("Connection"), "close") {
                if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
                        return err
                }