diff --git a/context.go b/context.go index 12e946d2..0c1fb07f 100644 --- a/context.go +++ b/context.go @@ -731,10 +731,15 @@ func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (e // If the headers are nots syntactically valid OR the remote IP does not correspong to a trusted proxy, // the remote IP (coming form Request.RemoteAddr) is returned. func (c *Context) ClientIP() string { - if c.engine.AppEngine { + switch { + case c.engine.AppEngine: if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" { return addr } + case c.engine.CloudflareProxy: + if addr := c.requestHeader("CF-Connecting-IP"); addr != "" { + return addr + } } remoteIP, trusted := c.RemoteIP() diff --git a/context_test.go b/context_test.go index aaa358e9..e0de717e 100644 --- a/context_test.go +++ b/context_test.go @@ -1476,6 +1476,13 @@ func TestContextClientIP(t *testing.T) { c.Request.Header.Del("X-Appengine-Remote-Addr") assert.Equal(t, "40.40.40.40", c.ClientIP()) + c.engine.AppEngine = false + c.engine.CloudflareProxy = true + assert.Equal(t, "60.60.60.60", c.ClientIP()) + + c.Request.Header.Del("CF-Connecting-IP") + assert.Equal(t, "40.40.40.40", c.ClientIP()) + // no port c.Request.RemoteAddr = "50.50.50.50" assert.Empty(t, c.ClientIP()) @@ -1485,6 +1492,7 @@ func resetContextForClientIPTests(c *Context) { c.Request.Header.Set("X-Real-IP", " 10.10.10.10 ") c.Request.Header.Set("X-Forwarded-For", " 20.20.20.20, 30.30.30.30") c.Request.Header.Set("X-Appengine-Remote-Addr", "50.50.50.50") + c.Request.Header.Set("CF-Connecting-IP", "60.60.60.60") c.Request.RemoteAddr = " 40.40.40.40:42123 " c.engine.AppEngine = false } diff --git a/gin.go b/gin.go index 56e5c768..00686e77 100644 --- a/gin.go +++ b/gin.go @@ -105,6 +105,10 @@ type Engine struct { // 'X-AppEngine...' for better integration with that PaaS. AppEngine bool + // If enabled, it will trust the CF-Connecting-IP header to determine the + // IP of the client. + CloudflareProxy bool + // If enabled, the url.RawPath will be used to find parameters. UseRawPath bool