diff --git a/http2/server.go b/http2/server.go index 396d53b9..033b6e6d 100644 --- a/http2/server.go +++ b/http2/server.go @@ -2569,7 +2569,8 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { clen = "" } } - if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) { + _, hasContentLength := rws.snapHeader["Content-Length"] + if !hasContentLength && clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) { clen = strconv.Itoa(len(p)) } _, hasContentType := rws.snapHeader["Content-Type"] diff --git a/http2/server_test.go b/http2/server_test.go index 40ab750f..cd73291e 100644 --- a/http2/server_test.go +++ b/http2/server_test.go @@ -3555,6 +3555,30 @@ func TestServerNoDuplicateContentType(t *testing.T) { } } +func TestServerContentLengthCanBeDisabled(t *testing.T) { + st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { + w.Header()["Content-Length"] = nil + fmt.Fprintf(w, "OK") + }) + defer st.Close() + st.greet() + st.writeHeaders(HeadersFrameParam{ + StreamID: 1, + BlockFragment: st.encodeHeader(), + EndStream: true, + EndHeaders: true, + }) + h := st.wantHeaders() + headers := st.decodeHeader(h.HeaderBlockFragment()) + want := [][2]string{ + {":status", "200"}, + {"content-type", "text/plain; charset=utf-8"}, + } + if !reflect.DeepEqual(headers, want) { + t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want) + } +} + func disableGoroutineTracking() (restore func()) { old := DebugGoroutines DebugGoroutines = false