mirror of
https://github.com/gofiber/fiber.git
synced 2025-05-28 10:23:36 +00:00
* Add support for consistent documentation using markdownlint * Only run workflow during changes to markdown files * Fix more inconsistencies * Fixes to markdown under .github/ * More fixes * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Fix typo in limiter docs * Add missing space before code-block * Add check for dead-links * Add write-good * Remove legacy README files * Fix glob for skipping .md files * Use paths-ignore instead --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
3.2 KiB
3.2 KiB
id
id |
---|
timeout |
Timeout
There exist two distinct implementations of timeout middleware Fiber.
New
As a fiber.Handler
wrapper, it creates a context with context.WithTimeout
and pass it in UserContext
.
If the context passed executions (eg. DB ops, Http calls) takes longer than the given duration to return, the timeout error is set and forwarded to the centralized ErrorHandler
.
It does not cancel long running executions. Underlying executions must handle timeout by using context.Context
parameter.
Signatures
func New(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler
Examples
Import the middleware package that is part of the Fiber web framework
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/timeout"
)
After you initiate your Fiber app, you can use the following possibilities:
func main() {
app := fiber.New()
h := func(c fiber.Ctx) error {
sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms")
if err := sleepWithContext(c.UserContext(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.New(h, 2*time.Second))
log.Fatal(app.Listen(":3000"))
}
func sleepWithContext(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
return context.DeadlineExceeded
case <-timer.C:
}
return nil
}
Test http 200 with curl:
curl --location -I --request GET 'http://localhost:3000/foo/1000'
Test http 408 with curl:
curl --location -I --request GET 'http://localhost:3000/foo/3000'
Use with custom error:
var ErrFooTimeOut = errors.New("foo context canceled")
func main() {
app := fiber.New()
h := func(c fiber.Ctx) error {
sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms")
if err := sleepWithContextWithCustomError(c.UserContext(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.New(h, 2*time.Second, ErrFooTimeOut))
log.Fatal(app.Listen(":3000"))
}
func sleepWithContextWithCustomError(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
return ErrFooTimeOut
case <-timer.C:
}
return nil
}
Sample usage with a DB call:
func main() {
app := fiber.New()
db, _ := gorm.Open(postgres.Open("postgres://localhost/foodb"), &gorm.Config{})
handler := func(ctx fiber.Ctx) error {
tran := db.WithContext(ctx.UserContext()).Begin()
if tran = tran.Exec("SELECT pg_sleep(50)"); tran.Error != nil {
return tran.Error
}
if tran = tran.Commit(); tran.Error != nil {
return tran.Error
}
return nil
}
app.Get("/foo", timeout.New(handler, 10*time.Second))
log.Fatal(app.Listen(":3000"))
}