gin-contrib / timeout

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

fix: fix rewrite status code warning #51

Closed sasakiyori closed 11 months ago

sasakiyori commented 1 year ago

gin warning:

[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 200 with 401

reproduced by following code:

func main() {
    g := gin.New()
    g.Use(TimeoutMiddleware(), AbortHandler())
    g.GET("/test", func(c *gin.Context) {
        time.Sleep(time.Second * 1000)
        c.Data(200, "text/plain", []byte("test"))
    })

    server := &http.Server{
        Addr:         ":6666",
        Handler:      g,
        ReadTimeout:  10 * time.Second,
        WriteTimeout: 0,
        IdleTimeout:  10 * time.Second,
    }

    _ = server.ListenAndServe()
}

func TimeoutMiddleware() gin.HandlerFunc {
    return timeout.New(
        timeout.WithTimeout(1500*time.Second),
        timeout.WithHandler(func(c *gin.Context) {
            c.Next()
        }),
        timeout.WithResponse(func(c *gin.Context) {
            c.String(404, "timeout")
        }),
    )
}

func AbortHandler() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.AbortWithStatus(401)
    }
}

The reason is AbortWithStatus will firstly call WriteHeader and then call WriteHeaderNow for double check (confirm the header already be written and the http status code is not modified).

In the master branch, WriteHeader implemented by timeout repo, but WriteHeaderNow implemented by gin repo. And this cause the double write for http status code and the failure.