gin-gonic / gin

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
https://gin-gonic.com/
MIT License
79.3k stars 8.03k forks source link

c.ClientIP() is incorrect under goroutine #3231

Open leeqvip opened 2 years ago

leeqvip commented 2 years ago

Description

c.ClientIP() is incorrect under goroutine

How to reproduce

func Handler(c *gin.Context){
    ip1 := c.ClientIP()
    go func(ip1 string) {
        ip2 := c.ClientIP()
        fmt.Println(ip1, ip2) // Under high concurrency, the two are not equal
    }(ip1)

        c.JSON(200, nil)
}

Expectations

fmt.Println(ip1, ip2) // Under high concurrency, the two are not equal

In most cases, the two are equal, but under high concurrency, the two are not equal, and the ip is rewritten by other requests

Actual result

Environment

eleven26 commented 2 years ago

You should pass context as first parameter to your goroutine,otherwise, you will get a different context in the goroutine, and the ip will naturally be different,that's what context exists for.

timandy commented 2 years ago

@leeqvip context is pooled object, pass context.Copy as first param.

func Handler(c *gin.Context) {
    ip1 := c.ClientIP()
    go func(cc *gin.Context) {
        ip2 := cc.ClientIP()
        fmt.Println(ip1, ip2)
    }(c.Copy())

    c.JSON(200, nil)
}