Skip to content

Commit

Permalink
Fix #1794: panics in timeout middleware are not recovered and cause a…
Browse files Browse the repository at this point in the history
…pplication to crash
  • Loading branch information
aldas committed Mar 2, 2021
1 parent c79ffed commit b2444d8
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
12 changes: 12 additions & 0 deletions middleware/timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package middleware

import (
"context"
"fmt"
"github.com/labstack/echo/v4"
"time"
)
Expand Down Expand Up @@ -62,6 +63,17 @@ func TimeoutWithConfig(config TimeoutConfig) echo.MiddlewareFunc {

done := make(chan error, 1)
go func() {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic recovered in timeout middleware: %v", r)
}
c.Logger().Error(err)
done <- err
}
}()

// This goroutine will keep running even if this middleware times out and
// will be stopped when ctx.Done() is called down the next(c) call chain
done <- next(c)
Expand Down
19 changes: 19 additions & 0 deletions middleware/timeout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,22 @@ func TestTimeoutTestRequestClone(t *testing.T) {
assert.NoError(t, err)

}

func TestTimeoutRecoversPanic(t *testing.T) {
t.Parallel()
m := TimeoutWithConfig(TimeoutConfig{
Timeout: 25 * time.Millisecond,
})

req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()

e := echo.New()
c := e.NewContext(req, rec)

err := m(func(c echo.Context) error {
panic("panic in handler")
})(c)

assert.Error(t, err, "panic recovered in timeout middleware: panic in handler")
}

0 comments on commit b2444d8

Please sign in to comment.