-
-
Save nguyentienlong/8c73b7ff72894c16866fc587e5ee711c to your computer and use it in GitHub Desktop.
Revisions
-
montanaflynn revised this gist
Apr 7, 2019 . 1 changed file with 18 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -35,15 +35,8 @@ func timeoutMiddleware(timeout time.Duration) func(c *gin.Context) { } } func timedHandler(duration time.Duration) func(c *gin.Context) { return func(c *gin.Context) { // get the underlying request context ctx := c.Request.Context() @@ -61,7 +54,7 @@ func main() { // and then send the doneChan with the status and body // to finish the request by writing the response go func() { time.Sleep(duration) doneChan <- responseData{ status: 200, body: gin.H{"hello": "world"}, @@ -82,7 +75,21 @@ func main() { case res := <-doneChan: c.JSON(res.status, res.body) } } } func main() { // create new gin without any middleware engine := gin.New() // add timeout middleware with 2 second duration engine.Use(timeoutMiddleware(time.Second * 2)) // create a handler that will last 1 seconds engine.GET("/short", timedHandler(time.Second)) // create a route that will last 5 seconds engine.GET("/long", timedHandler(time.Second*5)) // run the server log.Fatal(engine.Run(":8080")) -
montanaflynn created this gist
Apr 7, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,89 @@ package main import ( "context" "log" "net/http" "time" "github.com/gin-gonic/gin" ) // timeout middleware wraps the request context with a timeout func timeoutMiddleware(timeout time.Duration) func(c *gin.Context) { return func(c *gin.Context) { // wrap the request context with a timeout ctx, cancel := context.WithTimeout(c.Request.Context(), timeout) defer func() { // check if context timeout was reached if ctx.Err() == context.DeadlineExceeded { // write response and abort the request c.Writer.WriteHeader(http.StatusGatewayTimeout) c.Abort() } //cancel to clear resources after finished cancel() }() // replace request with context wrapped request c.Request = c.Request.WithContext(ctx) c.Next() } } func main() { // create new gin without any middleware engine := gin.New() // add timeout middleware with 2 second duration engine.Use(timeoutMiddleware(time.Second * 2)) // create a route that will last 5 seconds engine.GET("/long", func(c *gin.Context) { // get the underlying request context ctx := c.Request.Context() // create the response data type to use as a channel type type responseData struct { status int body map[string]interface{} } // create a done channel to tell the request it's done doneChan := make(chan responseData) // here you put the actual work needed for the request // and then send the doneChan with the status and body // to finish the request by writing the response go func() { time.Sleep(time.Second * 5) doneChan <- responseData{ status: 200, body: gin.H{"hello": "world"}, } }() // non-blocking select on two channels see if the request // times out or finishes select { // if the context is done it timed out or was cancelled // so don't return anything case <-ctx.Done(): return // if the request finished then finish the request by // writing the response case res := <-doneChan: c.JSON(res.status, res.body) } }) // run the server log.Fatal(engine.Run(":8080")) }