From: Laurent Senta Date: Fri, 10 Mar 2023 12:33:59 +0000 (+0000) Subject: net/http: do not force the Content-Length header if nilled X-Git-Tag: go1.21rc1~523 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=949d0f4f99c15541d7cd43f3e9812fb7ac9c73db;p=gostls13.git net/http: do not force the Content-Length header if nilled According to the ResponseWriter documentation: To suppress automatic response headers (such as "Date"), set their value to nil. In some cases, this documentation is incorrect: chunkWriter writes a Content-Length header even if the value was set to nil. Meaning there is no way to suppress this header. This patch replaces the empty string comparison with a call to `header.has` which takes into account nil values as expected. This is similar to the way we handle the "Date" header. Change-Id: Ie10d54ab0bb7d41270bc944ff867e035fe2bd0c5 GitHub-Last-Rev: e0616dd46388a724df7c6ea821b3808ed1663cab GitHub-Pull-Request: golang/go#58578 Reviewed-on: https://go-review.googlesource.com/c/go/+/469095 Reviewed-by: Heschi Kreinick TryBot-Result: Gopher Robot Auto-Submit: Damien Neil Run-TryBot: Jorropo Reviewed-by: Damien Neil --- diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 819152658b..a21518b563 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -6756,3 +6756,37 @@ func testHeadBody(t *testing.T, mode testMode, chunked bool, method string) { } } } + +// TestContentLengthResponseCanBeNilled verifies that the Content-Length is set by default +// or disabled when the header is set to nil. +func TestDisableContentLength(t *testing.T) { run(t, testDisableContentLength) } +func testDisableContentLength(t *testing.T, mode testMode) { + if mode == http2Mode { + t.Skip("skipping until h2_bundle.go is updated; see https://go-review.googlesource.com/c/net/+/471535") + } + + noCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header()["Content-Length"] = nil // disable the default Content-Length response + fmt.Fprintf(w, "OK") + })) + + res, err := noCL.c.Get(noCL.ts.URL) + if err != nil { + t.Error(err) + } + if got, haveCL := res.Header["Content-Length"]; haveCL { + t.Errorf("Unexpected Content-Length: %q", got) + } + + withCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + fmt.Fprintf(w, "OK") + })) + + res, err = withCL.c.Get(withCL.ts.URL) + if err != nil { + t.Error(err) + } + if got := res.Header.Get("Content-Length"); got != "2" { + t.Errorf("Content-Length: %q; want 2", got) + } +} diff --git a/src/net/http/server.go b/src/net/http/server.go index 9bd381ff48..e82669a180 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1317,7 +1317,7 @@ func (cw *chunkWriter) writeHeader(p []byte) { // send a Content-Length header. // Further, we don't send an automatic Content-Length if they // set a Transfer-Encoding, because they're generally incompatible. - if w.handlerDone.Load() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) { + if w.handlerDone.Load() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && !header.has("Content-Length") && (!isHEAD || len(p) > 0) { w.contentLength = int64(len(p)) setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10) }