- With issues: I have already checked the issues and could not find this in current issues.
Description
I have a saas project which is based upon Rest APIs. All apis are developed in GO using gin package. When the user logs in then I set current user details in the request context so that I can access these details furthere to display some data. However I had a case in which 2 requests hits in parallel & the context values for the 1st request are override with the context values in the 2nd request. Due to this, my data is displaying wrong.
How to reproduce
package main
import (
"github.com/gin-gonic/gin"
"fmt"
)
func main() {
g := gin.Default()
g.GET("/hello/:name", hello)
g.Run(":9000")
}
func hello(c *gin.Context) {
c.Keys = make(map[string]interface{})
c.Keys["current_user_id"] = 10
c.Keys["current_user_name"] = c.Param("name")
fmt.Println(c.Keys)
c.String(200, "Hello %s", c.Param("name"))
}
This issues is not produced every time for parallel requests.
Expectations
It should not override the values.
Environment
- go version: 1.19
- gin version (or commit ref): 1.8.1
- operating system: Ubuntu
Comment From: MikeJackOne
Can't reproduce with the code you provide,can you give me more detail?
Comment From: MikeJackOne
Can you share more detailed code of the problem you encounter?
Comment From: MikeJackOne
Actually you should use following method to set a key to a map.
c.Set("current_user_id",10)
Comment From: MikeJackOne
I check the source code and c.Keys is not automaticly initialized before use, So I suspect the code you provide would panic.
You should use c.Set("current_user_id",10)
as a way of setting value. It will handle initialization and lock for you.
Comment From: amankaur27
I have updated the code. I have initialized the keys before assigning some value to it
Comment From: amankaur27
Is assigning values like I provided & using c.Set() is behaviorally different ?
Comment From: MikeJackOne
I have updated the code. I have initialized the keys before assigning some value to it
you shouldn't use this way.
Comment From: MikeJackOne
use it this way, `package main
import ( "fmt"
"github.com/gin-gonic/gin"
)
func main() { g := gin.Default() g.GET("/hello/:name", hello) g.Run(":9000") }
func hello(c *gin.Context) { //c.Keys = make(map[string]any) c.Set("current_user_id", 10) c.Set("current_user_name", c.Param("name")) fmt.Println(c.Keys) c.String(200, "Hello %s", c.Param("name")) } `
Comment From: amankaur27
Whats the difference between two ?
Comment From: MikeJackOne
Is assigning values like I provided & using c.Set() is behaviorally different ?
yes, it handle initialization and lock for you, I think multiple goroutine changing the map cause the issue you encounter.
Comment From: MikeJackOne
Whats the difference between two ?
This is how Set is defined. it's pretty straightforwad and it answers you questions.
`func (c *Context) Set(key string, value any) { c.mu.Lock() if c.Keys == nil { c.Keys = make(map[string]any) }
c.Keys[key] = value
c.mu.Unlock()
}`
Comment From: MikeJackOne
Any other questions?
Comment From: amankaur27
Actually I am running this system from last 5 years. And I did not encounter problem except for 2-3 times. I doubt it does not break the current system.
Comment From: amankaur27
Also I provided you the sample. But actually the values are set in context in a middleware which is called before main(). Does it make any difference ?
Comment From: MikeJackOne
Actually I am running this system from last 5 years. And I did not encounter problem except for 2-3 times. I doubt it does not break the current system.
It may make some difference, you can share with me the middleware code and I will analyse it for you if you want to dig more.
Comment From: amankaur27
@MikeJackOne Please find the complete router code here (along with middleware): https://go.dev/play/p/8fFE7FTjkiv
Comment From: MikeJackOne
@MikeJackOne Please find the complete router code here (along with middleware): https://go.dev/play/p/8fFE7FTjkiv
I see where you problem is, you shouldn't use userName as a global variable.
Comment From: MikeJackOne
you may now close this issue, as this issue is not related to gin.
Comment From: amankaur27
Thanks @MikeJackOne I got it. Closing this issue.
Comment From: MikeJackOne
I am looking for a remote golang job, do you have any position that you can refer me to?
Comment From: amankaur27
Currently we have no vacancy for remote job. But I will let you know if there wil be any.
---- On Thu, 15 Dec 2022 14:29:17 +0530 Yan Mao @.***> wrote ---
I am looking for a remote golang job, do you have any position that you can refer me to?
— Reply to this email directly, https://github.com/gin-gonic/gin/issues/3437#issuecomment-1352744782, or https://github.com/notifications/unsubscribe-auth/AHX2B2KQXKZ3RBUROB6CBWLWNLMWLANCNFSM6AAAAAAS6BVGLE. You are receiving this because you modified the open/close state.