diff --git a/context.go b/context.go index 3d6b56d6..b55dfe01 100644 --- a/context.go +++ b/context.go @@ -729,6 +729,10 @@ func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (e // X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy. // Use X-Forwarded-For before X-Real-Ip as nginx uses X-Real-Ip with the proxy's IP. func (c *Context) ClientIP() string { + if c.engine.ClientIPExtractor != nil { + // if you don't trust your proxies, you can define your own extractor for client IP + return c.engine.ClientIPExtractor(c.Request) + } if c.engine.ForwardedByClientIP { clientIP := c.requestHeader("X-Forwarded-For") clientIP = strings.TrimSpace(strings.Split(clientIP, ",")[0]) diff --git a/context_test.go b/context_test.go index 8e1e3b57..4d7122de 100644 --- a/context_test.go +++ b/context_test.go @@ -1416,6 +1416,14 @@ func TestContextClientIP(t *testing.T) { // no port c.Request.RemoteAddr = "50.50.50.50" assert.Empty(t, c.ClientIP()) + + // custome client IP extractor + c.engine.ClientIPExtractor = func(req *http.Request) string { + clientIP := c.requestHeader("My-Client-IP") + return clientIP + } + c.Request.Header.Set("My-Client-IP", "10.10.10.10") + assert.Equal(t, "10.10.10.10", c.ClientIP()) } func TestContextContentType(t *testing.T) { diff --git a/gin.go b/gin.go index 1e126179..e6973dc3 100644 --- a/gin.go +++ b/gin.go @@ -83,6 +83,9 @@ type Engine struct { HandleMethodNotAllowed bool ForwardedByClientIP bool + // Custom extractor for extracting client IP from request + ClientIPExtractor func(*http.Request) string + // #726 #755 If enabled, it will thrust some headers starting with // 'X-AppEngine...' for better integration with that PaaS. AppEngine bool