gin-contrib / timeout

Timeout middleware for Gin
MIT License
177 stars 37 forks source link

Extend default timeout on certain path patterns #53

Open etiennemarais opened 1 year ago

etiennemarais commented 1 year ago

Summary

We ran into a use case where certain longer running endpoints needed their timeout to be extended beyond what the rest of the API required due to longer running legacy processes that couldn't be changed for backwards compatibility. There was a limitation in this middleware package that we couldn't easily extend certain paths from the normal timeout.

Extending certain paths, path patterns or lists of paths allows us to configure endpoints in a more controlled way, instead of updating the whole app to allow longer running timeouts.

Changes

func WithExtendedTimeout(extendedTimeout time.Duration) Option
func WithExtendedPaths(extendedPaths []string) Option

Example Usage

package main

import (
    "log"
    "net/http"
    "time"

    "github.com/gin-contrib/timeout"
    "github.com/gin-gonic/gin"
)

func testResponse(c *gin.Context) {
    c.String(http.StatusRequestTimeout, "timeout")
}

func extendedTimeoutMiddleware() gin.HandlerFunc {
    return timeout.New(
        timeout.WithTimeout(200*time.Millisecond),          // Default timeout on all routes
        timeout.WithExtendedTimeout(1000*time.Millisecond), // Extended timeout on pattern based routes
        timeout.WithExtendedPaths([]string{"/ext.*"}),      // List of patterns to allow extended timeouts
        timeout.WithHandler(func(c *gin.Context) {
            c.Next()
        }),
        timeout.WithResponse(testResponse),
    )
}

func main() {
    r := gin.New()
    r.Use(extendedTimeoutMiddleware())
    r.GET("/extended", func(c *gin.Context) {
        time.Sleep(800 * time.Millisecond)
        c.Status(http.StatusOK)
    })

    if err := r.Run(":8080"); err != nil {
        log.Fatal(err)
    }
}