Skip to content

Commit 4837fbe

Browse files
committed
net/http/httptest: check whether response bodies are allowed
Fixes golang#75471 Change-Id: Ie8fc5fae4b2a9285501198d8379bbffe51ee63f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/709335 Reviewed-by: Damien Neil <[email protected]> Reviewed-by: Michael Pratt <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent ee16319 commit 4837fbe

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/net/http/httptest/recorder.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ func (rw *ResponseRecorder) writeHeader(b []byte, str string) {
105105
// Write implements http.ResponseWriter. The data in buf is written to
106106
// rw.Body, if not nil.
107107
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
108+
code := rw.Code
109+
if !bodyAllowedForStatus(code) {
110+
return 0, http.ErrBodyNotAllowed
111+
}
108112
rw.writeHeader(buf, "")
109113
if rw.Body != nil {
110114
rw.Body.Write(buf)
@@ -115,13 +119,31 @@ func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
115119
// WriteString implements [io.StringWriter]. The data in str is written
116120
// to rw.Body, if not nil.
117121
func (rw *ResponseRecorder) WriteString(str string) (int, error) {
122+
code := rw.Code
123+
if !bodyAllowedForStatus(code) {
124+
return 0, http.ErrBodyNotAllowed
125+
}
118126
rw.writeHeader(nil, str)
119127
if rw.Body != nil {
120128
rw.Body.WriteString(str)
121129
}
122130
return len(str), nil
123131
}
124132

133+
// bodyAllowedForStatus reports whether a given response status code
134+
// permits a body. See RFC 7230, section 3.3.
135+
func bodyAllowedForStatus(status int) bool {
136+
switch {
137+
case status >= 100 && status <= 199:
138+
return false
139+
case status == 204:
140+
return false
141+
case status == 304:
142+
return false
143+
}
144+
return true
145+
}
146+
125147
func checkWriteHeaderCode(code int) {
126148
// Issue 22880: require valid WriteHeader status codes.
127149
// For now we only enforce that it's three digits.

src/net/http/httptest/recorder_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package httptest
66

77
import (
8+
"errors"
89
"fmt"
910
"io"
1011
"net/http"
@@ -309,6 +310,21 @@ func TestRecorder(t *testing.T) {
309310
}
310311
}
311312

313+
func TestBodyNotAllowed(t *testing.T) {
314+
rw := NewRecorder()
315+
rw.WriteHeader(204)
316+
317+
_, err := rw.Write([]byte("hello world"))
318+
if !errors.Is(err, http.ErrBodyNotAllowed) {
319+
t.Errorf("expected BodyNotAllowed for Write after 204, got: %v", err)
320+
}
321+
322+
_, err = rw.WriteString("hello world")
323+
if !errors.Is(err, http.ErrBodyNotAllowed) {
324+
t.Errorf("expected BodyNotAllowed for WriteString after 204, got: %v", err)
325+
}
326+
}
327+
312328
// issue 39017 - disallow Content-Length values such as "+3"
313329
func TestParseContentLength(t *testing.T) {
314330
tests := []struct {

0 commit comments

Comments
 (0)