internal/http3: return error when Write is used after status 304 is set

In our HTTP/1 and HTTP/2 implementations, calling Write in a server
handler after WriteHeader has been called with status 304 will return an
http.ErrBodyNotAllowed error. This change adds the same behavior for the
HTTP/3 server.

For golang/go#70914

Change-Id: I6be926412d51217a8b88b2ad4ce79935dd3e7af7
Reviewed-on: https://go-review.googlesource.com/c/net/+/751140
Reviewed-by: Nicholas Husin <husin@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Nicholas S. Husin
2026-03-03 13:07:09 -05:00
committed by Nicholas Husin
parent 6267c6c4c8
commit 039b87fac4
2 changed files with 24 additions and 0 deletions

View File

@@ -463,6 +463,10 @@ func (rw *responseWriter) Write(b []byte) (n int, err error) {
rw.mu.Lock()
defer rw.mu.Unlock()
if rw.statusCode == http.StatusNotModified {
return 0, http.ErrBodyNotAllowed
}
b, trimmed := rw.trimWriteLocked(b)
if trimmed {
defer func() {

View File

@@ -5,6 +5,7 @@
package http3
import (
"errors"
"io"
"maps"
"net/http"
@@ -912,6 +913,25 @@ func TestServer103EarlyHints(t *testing.T) {
})
}
func TestServer304NotModified(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotModified)
if _, err := w.Write([]byte("body should not be allowed")); !errors.Is(err, http.ErrBodyNotAllowed) {
t.Errorf("got %v error when calling Write after WriteHeader(304), want %v error", err, http.ErrBodyNotAllowed)
}
}))
tc := ts.connect()
tc.greet()
reqStream := tc.newStream(streamTypeRequest)
reqStream.writeHeaders(requestHeader(nil))
synctest.Wait()
reqStream.wantSomeHeaders(http.Header{":status": {"304"}})
reqStream.wantClosed("request is complete")
})
}
type testServer struct {
t testing.TB
s *Server