]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: do not force the Content-Length header if nilled
authorLaurent Senta <laurent@singulargarden.com>
Fri, 10 Mar 2023 12:33:59 +0000 (12:33 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 15 May 2023 17:07:02 +0000 (17:07 +0000)
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 <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Damien Neil <dneil@google.com>
Run-TryBot: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Damien Neil <dneil@google.com>
src/net/http/serve_test.go
src/net/http/server.go

index 819152658bffb89e1207da0c5430570eff30bedd..a21518b56361f44cb17c9658ef08cbbe51905a6f 100644 (file)
@@ -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)
+       }
+}
index 9bd381ff48bf5af543d09bf3a3a624c592f876b7..e82669a18053ee88493e570040fffed26c47bb08 100644 (file)
@@ -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)
        }