Skip to content

Commit

Permalink
fix timeout middleware not sending status code when handler returns a…
Browse files Browse the repository at this point in the history
…n error (fix #1804) (#1805)
  • Loading branch information
aldas authored Mar 12, 2021
1 parent 4c2fd1f commit dec96f0
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
5 changes: 5 additions & 0 deletions middleware/timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func (t echoHandlerFuncWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Reques
// so on timeout writer stays what http.TimeoutHandler uses and prevents writing headers/body
t.ctx.Response().Writer = originalWriter
if err != nil {
// call global error handler to write error to the client. This is needed or `http.TimeoutHandler` will send status code by itself
// and after that our tries to write status code will not work anymore
t.ctx.Error(err)
// we pass error from handler to middlewares up in handler chain to act on it if needed. But this means that
// global error handler is probably be called twice as `t.ctx.Error` already does that.
t.errChan <- err
}
}
26 changes: 25 additions & 1 deletion middleware/timeout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,34 @@ func TestTimeoutErrorOutInHandler(t *testing.T) {
c := e.NewContext(req, rec)

err := m(func(c echo.Context) error {
return errors.New("err")
return echo.NewHTTPError(http.StatusTeapot, "err")
})(c)

assert.Error(t, err)
assert.Equal(t, http.StatusTeapot, rec.Code)
assert.Equal(t, "{\"message\":\"err\"}\n", rec.Body.String())
}

func TestTimeoutSuccessfulRequest(t *testing.T) {
t.Parallel()
m := TimeoutWithConfig(TimeoutConfig{
// Timeout has to be defined or the whole flow for timeout middleware will be skipped
Timeout: 50 * 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 {
return c.JSON(http.StatusCreated, map[string]string{"data": "ok"})
})(c)

assert.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
assert.Equal(t, "{\"data\":\"ok\"}\n", rec.Body.String())
}

func TestTimeoutOnTimeoutRouteErrorHandler(t *testing.T) {
Expand Down

0 comments on commit dec96f0

Please sign in to comment.