Skip to content

Commit a9d9347

Browse files
committed
Import changes from golang/go#56151
1 parent ce89ade commit a9d9347

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

go.mod

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ module github.com/Acconut/go-httptest-recorder
22

33
go 1.21.0
44

5-
require (
6-
golang.org/x/net v0.14.0 // indirect
7-
golang.org/x/text v0.12.0 // indirect
8-
)
5+
require golang.org/x/net v0.14.0
6+
7+
require golang.org/x/text v0.12.0 // indirect

recorder.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ import (
1616
"golang.org/x/net/http/httpguts"
1717
)
1818

19+
// InformationalResponse is an HTTP response sent with a [1xx status code].
20+
//
21+
// [1xx status code]: https://httpwg.org/specs/rfc9110.html#status.1xx
22+
type InformationalResponse struct {
23+
// Code is the 1xx HTTP response code of this informational response.
24+
Code int
25+
26+
// Header contains the headers of this informational response.
27+
Header http.Header
28+
}
29+
1930
// ResponseRecorder is an implementation of http.ResponseWriter that
2031
// records its mutations for later inspection in tests.
2132
type ResponseRecorder struct {
@@ -27,6 +38,9 @@ type ResponseRecorder struct {
2738
// method.
2839
Code int
2940

41+
// Informational HTTP responses (1xx status code) sent before the main response.
42+
InformationalResponses []InformationalResponse
43+
3044
// HeaderMap contains the headers explicitly set by the Handler.
3145
// It is an internal detail.
3246
//
@@ -146,11 +160,20 @@ func (rw *ResponseRecorder) WriteHeader(code int) {
146160
}
147161

148162
checkWriteHeaderCode(code)
149-
rw.Code = code
150-
rw.wroteHeader = true
163+
151164
if rw.HeaderMap == nil {
152165
rw.HeaderMap = make(http.Header)
153166
}
167+
168+
if code >= 100 && code < 200 {
169+
ir := InformationalResponse{code, rw.HeaderMap.Clone()}
170+
rw.InformationalResponses = append(rw.InformationalResponses, ir)
171+
172+
return
173+
}
174+
175+
rw.Code = code
176+
rw.wroteHeader = true
154177
rw.snapHeader = rw.HeaderMap.Clone()
155178
}
156179

recorder_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"io"
1010
"net/http"
11+
"reflect"
1112
"testing"
1213
)
1314

@@ -123,6 +124,15 @@ func TestRecorder(t *testing.T) {
123124
return nil
124125
}
125126
}
127+
hasInformationalResponses := func(ir []InformationalResponse) checkFunc {
128+
return func(rec *ResponseRecorder) error {
129+
if !reflect.DeepEqual(ir, rec.InformationalResponses) {
130+
return fmt.Errorf("InformationalResponses = %v; want %v", rec.InformationalResponses, ir)
131+
}
132+
133+
return nil
134+
}
135+
}
126136

127137
for _, tt := range [...]struct {
128138
name string
@@ -294,6 +304,26 @@ func TestRecorder(t *testing.T) {
294304
check(hasResultContents("")), // check we don't crash reading the body
295305

296306
},
307+
{
308+
"1xx status code",
309+
func(rw http.ResponseWriter, _ *http.Request) {
310+
rw.WriteHeader(http.StatusContinue)
311+
rw.Header().Add("Foo", "bar")
312+
313+
rw.WriteHeader(http.StatusEarlyHints)
314+
rw.Header().Add("Baz", "bat")
315+
316+
rw.Header().Del("Foo")
317+
},
318+
check(
319+
hasInformationalResponses([]InformationalResponse{
320+
InformationalResponse{100, http.Header{}},
321+
InformationalResponse{103, http.Header{"Foo": []string{"bar"}}},
322+
}),
323+
hasHeader("Baz", "bat"),
324+
hasNotHeaders("Foo"),
325+
),
326+
},
297327
} {
298328
t.Run(tt.name, func(t *testing.T) {
299329
r, _ := http.NewRequest("GET", "http://foo.com/", nil)

0 commit comments

Comments
 (0)