Commit 5dbdd798 authored by Filip Gruszczyński's avatar Filip Gruszczyński Committed by Brad Fitzpatrick

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 <bradfitz@golang.org>
Reviewed-by: default avatarEmmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 3b69c3bb
......@@ -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)
}
}
......@@ -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
}
......
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