mirror of
https://github.com/gofiber/fiber.git
synced 2025-08-14 12:40:04 +00:00
4.0 KiB
4.0 KiB
id
id |
---|
timeout |
Timeout
The timeout middleware limits how long a handler can take to complete. When the
deadline is exceeded, Fiber responds with 408 Request Timeout
. The middleware
uses context.WithTimeout
and makes the context available through
c.Context()
so that your code can listen for cancellation.
:::caution
timeout.New
wraps your final handler and can't be added with app.Use
or
used in a middleware chain. Register it per route and avoid calling
c.Next()
inside the wrapped handler—doing so will panic.
:::
Signatures
func New(handler fiber.Handler, config ...timeout.Config) fiber.Handler
Examples
Basic example
The following program times out any request that takes longer than two seconds.
The handler simulates work with sleepWithContext
, which stops when the
request's context is canceled:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/timeout"
)
func sleepWithContext(ctx context.Context, d time.Duration) error {
select {
case <-time.After(d):
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
app := fiber.New()
handler := func(c fiber.Ctx) error {
delay, _ := time.ParseDuration(c.Params("delay") + "ms")
if err := sleepWithContext(c.Context(), delay); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return c.SendString("finished")
}
app.Get("/sleep/:delay", timeout.New(handler, timeout.Config{
Timeout: 2 * time.Second,
}))
log.Fatal(app.Listen(":3000"))
}
Test it with curl:
curl -i http://localhost:3000/sleep/1000 # finishes within the timeout
curl -i http://localhost:3000/sleep/3000 # returns 408 Request Timeout
Config
Property | Type | Description | Default |
---|---|---|---|
Next | func(fiber.Ctx) bool |
Function to skip the middleware. | nil |
Timeout | time.Duration |
Timeout duration for requests. 0 or a negative value disables the timeout. |
0 |
OnTimeout | fiber.Handler |
Handler executed when a timeout occurs. Defaults to returning fiber.ErrRequestTimeout . |
nil |
Errors | []error |
Custom errors treated as timeout errors. | nil |
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.Context(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.New(h, timeout.Config{Timeout: 2 * time.Second, Errors: []error{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 database 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.Context()).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, timeout.Config{Timeout: 10 * time.Second}))
log.Fatal(app.Listen(":3000"))
}