-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Timeout middleware #1684
Comments
I migrate my app from gin to echo, because gin has timeout middleware, but it panics. |
Hi, I hope this example helps you on your Timeout middleware journey package main
import (
"context"
"net/http"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/labstack/gommon/log"
)
func main() {
// Echo instance
e := echo.New()
e.Logger.SetLevel(log.INFO)
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Route
e.GET("/sleep", func(c echo.Context) (err error) {
// This select make the trick of finish this request when the middleware timeouts
select {
case <-time.After(5 * time.Second):
c.Logger().Info("Done")
return c.JSON(http.StatusOK, "Done")
case <-c.Request().Context().Done():
c.Logger().Info("Timeout")
return nil
}
}, timeoutMiddleware)
// Start server
e.Logger.Fatal(e.Start(":8080"))
}
func timeoutMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// Just to play easily with the middleware using a query parameter
timeout := 2 * time.Second
if t, err := time.ParseDuration(c.QueryParam("timeout")); err == nil {
timeout = t
}
// This is the context that controls the timeout. Its parent is the original
// http.Request context
ctx, cancel := context.WithTimeout(c.Request().Context(), timeout)
defer cancel() // releases resources if next(c) completes before timeout elapses
// A channel and a goroutine to run next(c) and know if its ends
done := make(chan error, 1)
go func() {
// This goroutine will not stop even this middleware timeouts,
// unless someone in the next(c) call chain handle ctx.Done() properly
c.SetRequest(c.Request().Clone(ctx))
done <- next(c)
}()
// The real timeout logic
select {
case <-ctx.Done():
return c.JSON(http.StatusGatewayTimeout, ctx.Err())
case err := <-done:
return err
}
}
} Here are some curl that you can use to play with the example # Timeout
curl -i --request GET --url 'http://127.0.0.1:8080/sleep'
# No timeout
curl -i --request GET --url 'http://127.0.0.1:8080/sleep?timeout=6s' Please, when you have your Timeout middleware woking don't forget to submit a PR whit it 😉 |
Hi @jeyldii, Was my comment helpfull? |
Hey! Thank you for your answer! I make something like this:
And i manage context.Deadline in my handlers. I think your decision better. I think i can make a PR with middleware soon. Sorry, for late answer :) |
Hi! I want to create timeout middleware
Checklist
Expected behaviour
middleware.Timeout()
Actual behaviour
middleware package do not produce timeout middleware
Working code to debug
I try something like this, yes i know it's wrong way:)
Version/commit
latest
The text was updated successfully, but these errors were encountered: