Open ksaritek opened 2 years ago
@ksaritek why not use assert to find the bad usage and fix it,
func longQueryWithContext(ctx context.Context) {
if c, ok := ctx.(*gin.Context); ok {
// c.Request.RequestURI
// c.Request.Method
}
}
@luchuanbing123 I am only interested in c.Request.Context(). The problem is you can pass gin.Context and gin.Context.Request.Context() as a parameter to the longQueryWithContext. The problem is I could not find a linter or any check to prevent passing gin.Context instead of gin.Context.Request.Context(). gin.Context.Request.Context() already keeps connection info for incoming request and if the client kills the request, context is canceled. I need that cancel information to stop SQL query.
@ksaritek may workaround as follow ?
func longQueryWithContext(ctx context.Context) {
if c, ok := ctx.(*gin.Context); ok {
ctx = c.Request.Context()
}
}
@luchuanbing123 if more then one developer, it is not easy to track it. We generate the models with https://github.com/volatiletech/sqlboiler with context. if Developers accidentally pass gin.Context, it is end of the game. I tried to write a linter for that but I could not do it.
So is there any feature or work around to prevent not to pass gin.Context instead of c.Request.Context()? It is so easy to make a mistake for that.
I see the fix for this is already merged to master about a month ago, so I would suggest to either wait for the next release or fork it and release it on your own.
// Deadline returns that there is no deadline (ok==false) when c.Request has no Context.
func (c *Context) Deadline() (deadline time.Time, ok bool) {
if c.Request == nil || c.Request.Context() == nil {
return
}
return c.Request.Context().Deadline()
}
// Done returns nil (chan which will wait forever) when c.Request has no Context.
func (c *Context) Done() <-chan struct{} {
if c.Request == nil || c.Request.Context() == nil {
return nil
}
return c.Request.Context().Done()
}
// Err returns nil when c.Request has no Context.
func (c *Context) Err() error {
if c.Request == nil || c.Request.Context() == nil {
return nil
}
return c.Request.Context().Err()
}
ohh nice, thank you @abderan
This should be closed now.
I see the fix for this is already merged to master about a month ago, so I would suggest to either wait for the next release or fork it and release it on your own.
// Deadline returns that there is no deadline (ok==false) when c.Request has no Context. func (c *Context) Deadline() (deadline time.Time, ok bool) { if c.Request == nil || c.Request.Context() == nil { return } return c.Request.Context().Deadline() } // Done returns nil (chan which will wait forever) when c.Request has no Context. func (c *Context) Done() <-chan struct{} { if c.Request == nil || c.Request.Context() == nil { return nil } return c.Request.Context().Done() } // Err returns nil when c.Request has no Context. func (c *Context) Err() error { if c.Request == nil || c.Request.Context() == nil { return nil } return c.Request.Context().Err() }
hi @abde8ng ,
I find that for the newest version, there's one more param called ContextWithFallback
, so I think we need to set it as true manually for this situation? Is it correct? please tell.
func (c *Context) Done() <-chan struct{} {
if !c.engine.ContextWithFallback || c.Request == nil || c.Request.Context() == nil {
return nil
}
return c.Request.Context().Done()
}
router := gin.Default()
router.ContextWithFallback = true
I see the fix for this is already merged to master about a month ago, so I would suggest to either wait for the next release or fork it and release it on your own.
// Deadline returns that there is no deadline (ok==false) when c.Request has no Context. func (c *Context) Deadline() (deadline time.Time, ok bool) { if c.Request == nil || c.Request.Context() == nil { return } return c.Request.Context().Deadline() } // Done returns nil (chan which will wait forever) when c.Request has no Context. func (c *Context) Done() <-chan struct{} { if c.Request == nil || c.Request.Context() == nil { return nil } return c.Request.Context().Done() } // Err returns nil when c.Request has no Context. func (c *Context) Err() error { if c.Request == nil || c.Request.Context() == nil { return nil } return c.Request.Context().Err() }
hi @abde8ng , I find that for the newest version, there's one more param called
ContextWithFallback
, so I think we need to set it as true manually for this situation? Is it correct? please tell.func (c *Context) Done() <-chan struct{} { if !c.engine.ContextWithFallback || c.Request == nil || c.Request.Context() == nil { return nil } return c.Request.Context().Done() }
router := gin.Default() router.ContextWithFallback = true
func main() { r := gin.New() r.ContextWithFallback = true r.Use(cors.Default()) r.GET("/health", health)
r.Run(":8080")
}
func health(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok"}) }
ContextWithFallback is always false ?
version v1.6.2
We have long-running queries and functions. I want to bind those processes to request context. Whenever an incoming request is canceled, It should stop. That is what we try to achieve.
If I pass c.Request.Context(), there is no problem. However, we would like to do that through gin.Context. The reason behind that is, it is possible to pass gin.Context instead of c.Request.Context() accidentally, and we don't want that.
If I do pass c.Request.Context()
It is working fine. But, It is so hard to track who passed which context. for instance:
As stated at the gin.Context source file, the proper way is to pass c.Request.Context(), but I could not find a way to track and fix it at the coding level. Is it possible to bind those methods to c.Request.Context()?