Skip to content

Commit 725ca6d

Browse files
committed
handle errors in body dump middleware
1 parent e26d2d2 commit 725ca6d

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

middleware/body_dump.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,12 @@ func BodyDumpWithConfig(config BodyDumpConfig) echo.MiddlewareFunc {
6666

6767
// Request
6868
reqBody := []byte{}
69-
if c.Request().Body != nil { // Read
70-
reqBody, _ = io.ReadAll(c.Request().Body)
69+
if c.Request().Body != nil {
70+
var readErr error
71+
reqBody, readErr = io.ReadAll(c.Request().Body)
72+
if readErr != nil {
73+
return readErr
74+
}
7175
}
7276
c.Request().Body = io.NopCloser(bytes.NewBuffer(reqBody)) // Reset
7377

middleware/body_dump_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,65 @@ func TestBodyDumpResponseWriter_CanNotHijack(t *testing.T) {
140140
_, _, err := bdrw.Hijack()
141141
assert.EqualError(t, err, "feature not supported")
142142
}
143+
144+
func TestBodyDump_ReadError(t *testing.T) {
145+
e := echo.New()
146+
147+
// Create a reader that fails during read
148+
failingReader := &failingReadCloser{
149+
data: []byte("partial data"),
150+
failAt: 7, // Fail after 7 bytes
151+
failWith: errors.New("connection reset"),
152+
}
153+
154+
req := httptest.NewRequest(http.MethodPost, "/", failingReader)
155+
rec := httptest.NewRecorder()
156+
c := e.NewContext(req, rec)
157+
158+
h := func(c echo.Context) error {
159+
// This handler should not be reached if body read fails
160+
body, _ := io.ReadAll(c.Request().Body)
161+
return c.String(http.StatusOK, string(body))
162+
}
163+
164+
requestBodyReceived := ""
165+
mw := BodyDump(func(c echo.Context, reqBody, resBody []byte) {
166+
requestBodyReceived = string(reqBody)
167+
})
168+
169+
err := mw(h)(c)
170+
171+
// Verify error is propagated
172+
assert.Error(t, err)
173+
assert.Contains(t, err.Error(), "connection reset")
174+
175+
// Verify handler was not executed (callback wouldn't have received data)
176+
assert.Empty(t, requestBodyReceived)
177+
}
178+
179+
// failingReadCloser is a helper type for testing read errors
180+
type failingReadCloser struct {
181+
data []byte
182+
pos int
183+
failAt int
184+
failWith error
185+
}
186+
187+
func (f *failingReadCloser) Read(p []byte) (n int, err error) {
188+
if f.pos >= f.failAt {
189+
return 0, f.failWith
190+
}
191+
192+
n = copy(p, f.data[f.pos:])
193+
f.pos += n
194+
195+
if f.pos >= f.failAt {
196+
return n, f.failWith
197+
}
198+
199+
return n, nil
200+
}
201+
202+
func (f *failingReadCloser) Close() error {
203+
return nil
204+
}

0 commit comments

Comments
 (0)