Skip to content

Commit 4dc08bd

Browse files
committed
Fix panic in DebugPrinter when printing body twice (#444)
1 parent 6eb565c commit 4dc08bd

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

e2e/printer_test.go

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,92 @@ func (p *mockPrinter) Response(resp *http.Response, rtt time.Duration) {
3232
p.rtt = rtt
3333
}
3434

35-
func createPrinterHandler() http.Handler {
35+
func createPrinterHandler(request, response string) http.Handler {
3636
mux := http.NewServeMux()
3737

3838
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
3939
body, _ := io.ReadAll(r.Body)
40-
if string(body) != "test_request" {
40+
if string(body) != request {
4141
panic("unexpected request body " + string(body))
4242
}
4343
w.Header().Set("Content-Type", "text/plain")
44-
_, _ = w.Write([]byte(`test_response`))
44+
_, _ = w.Write([]byte(response))
4545
})
4646

4747
return mux
4848
}
4949

50+
func TestE2EPrinter_Smoke(t *testing.T) {
51+
cases := []struct {
52+
name string
53+
printers []httpexpect.Printer
54+
}{
55+
{
56+
name: "CompactPrinter",
57+
printers: []httpexpect.Printer{
58+
httpexpect.NewCompactPrinter(t),
59+
},
60+
},
61+
{
62+
name: "CurlPrinter",
63+
printers: []httpexpect.Printer{
64+
httpexpect.NewCurlPrinter(t),
65+
},
66+
},
67+
{
68+
name: "DebugPrinter with body",
69+
printers: []httpexpect.Printer{
70+
httpexpect.NewDebugPrinter(t, true),
71+
},
72+
},
73+
{
74+
name: "DebugPrinter without body",
75+
printers: []httpexpect.Printer{
76+
httpexpect.NewDebugPrinter(t, false),
77+
},
78+
},
79+
{
80+
name: "print body twice",
81+
printers: []httpexpect.Printer{
82+
httpexpect.NewDebugPrinter(t, true),
83+
httpexpect.NewDebugPrinter(t, true),
84+
},
85+
},
86+
{
87+
name: "all printers",
88+
printers: []httpexpect.Printer{
89+
httpexpect.NewCompactPrinter(t),
90+
httpexpect.NewCurlPrinter(t),
91+
httpexpect.NewDebugPrinter(t, false),
92+
httpexpect.NewDebugPrinter(t, true),
93+
},
94+
},
95+
}
96+
97+
for _, tc := range cases {
98+
t.Run(tc.name, func(t *testing.T) {
99+
handler := createPrinterHandler("test_request", "test_response")
100+
101+
server := httptest.NewServer(handler)
102+
defer server.Close()
103+
104+
e := httpexpect.WithConfig(httpexpect.Config{
105+
BaseURL: server.URL,
106+
Reporter: httpexpect.NewAssertReporter(t),
107+
Printers: tc.printers,
108+
})
109+
110+
e.POST("/test").
111+
WithText("test_request").
112+
Expect().
113+
Text().
114+
IsEqual("test_response")
115+
})
116+
}
117+
}
118+
50119
func TestE2EPrinter_Single(t *testing.T) {
51-
handler := createPrinterHandler()
120+
handler := createPrinterHandler("test_request", "test_response")
52121

53122
server := httptest.NewServer(handler)
54123
defer server.Close()
@@ -74,7 +143,7 @@ func TestE2EPrinter_Single(t *testing.T) {
74143
}
75144

76145
func TestE2EPrinter_Multiple(t *testing.T) {
77-
handler := createPrinterHandler()
146+
handler := createPrinterHandler("test_request", "test_response")
78147

79148
server := httptest.NewServer(handler)
80149
defer server.Close()

request.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,13 @@ func (r *Request) retryRequest(reqFunc func() (*http.Response, error)) (
24572457
if reqBody != nil {
24582458
reqBody.Rewind()
24592459
}
2460-
printer.Request(r.httpReq)
2460+
// Make a copy to avoid accidental modification of request.
2461+
// In particular, httputil.DumpRequest reads sets request body into a buffer
2462+
// and set req.Body to a wrapper that will re-read body from buffer.
2463+
// It breaks our bodyWrapper logic as we don't expect that someone will
2464+
// replace bodyWrapper with something else.
2465+
httpReqCopy := *r.httpReq
2466+
printer.Request(&httpReqCopy)
24612467
}
24622468

24632469
if reqBody != nil {
@@ -2492,7 +2498,10 @@ func (r *Request) retryRequest(reqFunc func() (*http.Response, error)) (
24922498
if resp.Body != nil {
24932499
resp.Body.(*bodyWrapper).Rewind()
24942500
}
2495-
printer.Response(resp, elapsed)
2501+
// Make a copy to avoid accidental modification of request.
2502+
// See comment above.
2503+
httpRespCopy := *resp
2504+
printer.Response(&httpRespCopy, elapsed)
24962505
}
24972506
}
24982507

0 commit comments

Comments
 (0)