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  ```