Skip to content

Commit b2444d8

Browse files
committed
Fix #1794: panics in timeout middleware are not recovered and cause application to crash
1 parent c79ffed commit b2444d8

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

middleware/timeout.go

+12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package middleware
44

55
import (
66
"context"
7+
"fmt"
78
"github.com/labstack/echo/v4"
89
"time"
910
)
@@ -62,6 +63,17 @@ func TimeoutWithConfig(config TimeoutConfig) echo.MiddlewareFunc {
6263

6364
done := make(chan error, 1)
6465
go func() {
66+
defer func() {
67+
if r := recover(); r != nil {
68+
err, ok := r.(error)
69+
if !ok {
70+
err = fmt.Errorf("panic recovered in timeout middleware: %v", r)
71+
}
72+
c.Logger().Error(err)
73+
done <- err
74+
}
75+
}()
76+
6577
// This goroutine will keep running even if this middleware times out and
6678
// will be stopped when ctx.Done() is called down the next(c) call chain
6779
done <- next(c)

middleware/timeout_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,22 @@ func TestTimeoutTestRequestClone(t *testing.T) {
175175
assert.NoError(t, err)
176176

177177
}
178+
179+
func TestTimeoutRecoversPanic(t *testing.T) {
180+
t.Parallel()
181+
m := TimeoutWithConfig(TimeoutConfig{
182+
Timeout: 25 * time.Millisecond,
183+
})
184+
185+
req := httptest.NewRequest(http.MethodGet, "/", nil)
186+
rec := httptest.NewRecorder()
187+
188+
e := echo.New()
189+
c := e.NewContext(req, rec)
190+
191+
err := m(func(c echo.Context) error {
192+
panic("panic in handler")
193+
})(c)
194+
195+
assert.Error(t, err, "panic recovered in timeout middleware: panic in handler")
196+
}

0 commit comments

Comments
 (0)