diff --git a/context.go b/context.go index df001a40..ffda5ab1 100644 --- a/context.go +++ b/context.go @@ -353,9 +353,17 @@ func (c *Context) ClientIP() string { return clientIP } } + + if c.engine.AppEngine { + if addr := c.Request.Header.Get("X-Appengine-Remote-Addr"); addr != "" { + return addr + } + } + if ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr)); err == nil { return ip } + return "" } diff --git a/context_appengine.go b/context_appengine.go new file mode 100644 index 00000000..d9cb22f3 --- /dev/null +++ b/context_appengine.go @@ -0,0 +1,7 @@ +// +build appengine + +package gin + +func init() { + defaultAppEngine = true +} diff --git a/context_test.go b/context_test.go index 01ee6b83..d46be714 100644 --- a/context_test.go +++ b/context_test.go @@ -650,6 +650,7 @@ func TestContextClientIP(t *testing.T) { 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.RemoteAddr = " 40.40.40.40:42123 " assert.Equal(t, c.ClientIP(), "10.10.10.10") @@ -661,7 +662,15 @@ func TestContextClientIP(t *testing.T) { assert.Equal(t, c.ClientIP(), "30.30.30.30") c.Request.Header.Del("X-Forwarded-For") + c.engine.AppEngine = true + assert.Equal(t, c.ClientIP(), "50.50.50.50") + + c.Request.Header.Del("X-Appengine-Remote-Addr") assert.Equal(t, c.ClientIP(), "40.40.40.40") + + // no port + c.Request.RemoteAddr = "50.50.50.50" + assert.Equal(t, c.ClientIP(), "") } func TestContextContentType(t *testing.T) { diff --git a/gin.go b/gin.go index 60f4ab29..70cc11b6 100644 --- a/gin.go +++ b/gin.go @@ -19,6 +19,7 @@ const Version = "v1.0rc2" var default404Body = []byte("404 page not found") var default405Body = []byte("405 method not allowed") +var defaultAppEngine bool type HandlerFunc func(*Context) type HandlersChain []HandlerFunc @@ -78,6 +79,10 @@ type ( // handler. HandleMethodNotAllowed bool ForwardedByClientIP bool + + // #726 #755 If enabled, it will thrust some headers starting with + // 'X-AppEngine...' for better integration with that PaaS. + AppEngine bool } ) @@ -101,6 +106,7 @@ func New() *Engine { RedirectFixedPath: false, HandleMethodNotAllowed: false, ForwardedByClientIP: true, + AppEngine: defaultAppEngine, trees: make(methodTrees, 0, 9), } engine.RouterGroup.engine = engine