github.com/gofiber/fiber/v2@v2.47.0/docs/api/middleware/timeout.md (about) 1 --- 2 id: timeout 3 title: Timeout 4 --- 5 6 There exist two distinct implementations of timeout middleware [Fiber](https://github.com/gofiber/fiber). 7 8 **New** 9 10 Wraps a `fiber.Handler` with a timeout. If the handler takes longer than the given duration to return, the timeout error is set and forwarded to the centralized [ErrorHandler](https://docs.gofiber.io/error-handling). 11 12 :::caution 13 This has been deprecated since it raises race conditions. 14 ::: 15 16 **NewWithContext** 17 18 As a `fiber.Handler` wrapper, it creates a context with `context.WithTimeout` and pass it in `UserContext`. 19 20 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`. 21 22 23 It does not cancel long running executions. Underlying executions must handle timeout by using `context.Context` parameter. 24 25 ## Signatures 26 27 ```go 28 func New(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler 29 func NewWithContext(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler 30 ``` 31 32 ## Examples 33 34 Import the middleware package that is part of the Fiber web framework 35 36 ```go 37 import ( 38 "github.com/gofiber/fiber/v2" 39 "github.com/gofiber/fiber/v2/middleware/timeout" 40 ) 41 ``` 42 43 After you initiate your Fiber app, you can use the following possibilities: 44 45 ```go 46 func main() { 47 app := fiber.New() 48 49 h := func(c *fiber.Ctx) error { 50 sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms") 51 if err := sleepWithContext(c.UserContext(), sleepTime); err != nil { 52 return fmt.Errorf("%w: execution error", err) 53 } 54 return nil 55 } 56 57 app.Get("/foo/:sleepTime", timeout.New(h, 2*time.Second)) 58 log.Fatal(app.Listen(":3000")) 59 } 60 61 func sleepWithContext(ctx context.Context, d time.Duration) error { 62 timer := time.NewTimer(d) 63 64 select { 65 case <-ctx.Done(): 66 if !timer.Stop() { 67 <-timer.C 68 } 69 return context.DeadlineExceeded 70 case <-timer.C: 71 } 72 return nil 73 } 74 ``` 75 76 Test http 200 with curl: 77 78 ```bash 79 curl --location -I --request GET 'http://localhost:3000/foo/1000' 80 ``` 81 82 Test http 408 with curl: 83 84 ```bash 85 curl --location -I --request GET 'http://localhost:3000/foo/3000' 86 ``` 87 88 Use with custom error: 89 90 ```go 91 var ErrFooTimeOut = errors.New("foo context canceled") 92 93 func main() { 94 app := fiber.New() 95 h := func(c *fiber.Ctx) error { 96 sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms") 97 if err := sleepWithContextWithCustomError(c.UserContext(), sleepTime); err != nil { 98 return fmt.Errorf("%w: execution error", err) 99 } 100 return nil 101 } 102 103 app.Get("/foo/:sleepTime", timeout.NewWithContext(h, 2*time.Second, ErrFooTimeOut)) 104 log.Fatal(app.Listen(":3000")) 105 } 106 107 func sleepWithContextWithCustomError(ctx context.Context, d time.Duration) error { 108 timer := time.NewTimer(d) 109 select { 110 case <-ctx.Done(): 111 if !timer.Stop() { 112 <-timer.C 113 } 114 return ErrFooTimeOut 115 case <-timer.C: 116 } 117 return nil 118 } 119 ``` 120 121 Sample usage with a DB call: 122 123 ```go 124 func main() { 125 app := fiber.New() 126 db, _ := gorm.Open(postgres.Open("postgres://localhost/foodb"), &gorm.Config{}) 127 128 handler := func(ctx *fiber.Ctx) error { 129 tran := db.WithContext(ctx.UserContext()).Begin() 130 131 if tran = tran.Exec("SELECT pg_sleep(50)"); tran.Error != nil { 132 return tran.Error 133 } 134 135 if tran = tran.Commit(); tran.Error != nil { 136 return tran.Error 137 } 138 139 return nil 140 } 141 142 app.Get("/foo", timeout.NewWithContext(handler, 10*time.Second)) 143 log.Fatal(app.Listen(":3000")) 144 } 145 ```