mirror of https://github.com/gin-gonic/gin.git
Provide custom options of TrustedPlatform for another CDN services (#2906)
* refine TrustedPlatform and docs * refactor for switch * refactor switch to if statement
This commit is contained in:
parent
3fe928994b
commit
2d3d6d2f13
29
README.md
29
README.md
|
@ -78,6 +78,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi
|
||||||
- [http2 server push](#http2-server-push)
|
- [http2 server push](#http2-server-push)
|
||||||
- [Define format for the log of routes](#define-format-for-the-log-of-routes)
|
- [Define format for the log of routes](#define-format-for-the-log-of-routes)
|
||||||
- [Set and get a cookie](#set-and-get-a-cookie)
|
- [Set and get a cookie](#set-and-get-a-cookie)
|
||||||
|
- [Don't trust all proxies](#don't-trust-all-proxies)
|
||||||
- [Testing](#testing)
|
- [Testing](#testing)
|
||||||
- [Users](#users)
|
- [Users](#users)
|
||||||
|
|
||||||
|
@ -2236,6 +2237,34 @@ func main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Notice:** If you are using a CDN service, you can set the `Engine.TrustedPlatform`
|
||||||
|
to skip TrustedProxies check, it has a higher priority than TrustedProxies.
|
||||||
|
Look at the example below:
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
router := gin.Default()
|
||||||
|
// Use predefined header gin.PlatformXXX
|
||||||
|
router.TrustedPlatform = gin.PlatformGoogleAppEngine
|
||||||
|
// Or set your own trusted request header for another trusted proxy service
|
||||||
|
// Don't set it to any suspect request header, it's unsafe
|
||||||
|
router.TrustedPlatform = "X-CDN-IP"
|
||||||
|
|
||||||
|
router.GET("/", func(c *gin.Context) {
|
||||||
|
// If you set TrustedPlatform, ClientIP() will resolve the
|
||||||
|
// corresponding header and return IP directly
|
||||||
|
fmt.Printf("ClientIP: %s\n", c.ClientIP())
|
||||||
|
})
|
||||||
|
router.Run()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The `net/http/httptest` package is preferable way for HTTP testing.
|
The `net/http/httptest` package is preferable way for HTTP testing.
|
||||||
|
|
14
context.go
14
context.go
|
@ -735,20 +735,16 @@ func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (e
|
||||||
return bb.BindBody(body, obj)
|
return bb.BindBody(body, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientIP implements a best effort algorithm to return the real client IP.
|
// ClientIP implements one best effort algorithm to return the real client IP.
|
||||||
// It called c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not.
|
// It called c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not.
|
||||||
// If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]).
|
// If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]).
|
||||||
// If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy,
|
// If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy,
|
||||||
// the remote IP (coming form Request.RemoteAddr) is returned.
|
// the remote IP (coming form Request.RemoteAddr) is returned.
|
||||||
func (c *Context) ClientIP() string {
|
func (c *Context) ClientIP() string {
|
||||||
// Check if we're running on a trusted platform
|
// Check if we're running on a trusted platform, continue running backwards if error
|
||||||
switch c.engine.TrustedPlatform {
|
if c.engine.TrustedPlatform != "" {
|
||||||
case PlatformGoogleAppEngine:
|
// Developers can define their own header of Trusted Platform or use predefined constants
|
||||||
if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
|
if addr := c.requestHeader(c.engine.TrustedPlatform); addr != "" {
|
||||||
return addr
|
|
||||||
}
|
|
||||||
case PlatformCloudflare:
|
|
||||||
if addr := c.requestHeader("CF-Connecting-IP"); addr != "" {
|
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1458,8 +1458,20 @@ func TestContextClientIP(t *testing.T) {
|
||||||
c.engine.TrustedPlatform = PlatformGoogleAppEngine
|
c.engine.TrustedPlatform = PlatformGoogleAppEngine
|
||||||
assert.Equal(t, "50.50.50.50", c.ClientIP())
|
assert.Equal(t, "50.50.50.50", c.ClientIP())
|
||||||
|
|
||||||
// Test the legacy flag
|
// Use custom TrustedPlatform header
|
||||||
|
c.engine.TrustedPlatform = "X-CDN-IP"
|
||||||
|
c.Request.Header.Set("X-CDN-IP", "80.80.80.80")
|
||||||
|
assert.Equal(t, "80.80.80.80", c.ClientIP())
|
||||||
|
// wrong header
|
||||||
|
c.engine.TrustedPlatform = "X-Wrong-Header"
|
||||||
|
assert.Equal(t, "40.40.40.40", c.ClientIP())
|
||||||
|
|
||||||
|
c.Request.Header.Del("X-CDN-IP")
|
||||||
|
// TrustedPlatform is empty
|
||||||
c.engine.TrustedPlatform = ""
|
c.engine.TrustedPlatform = ""
|
||||||
|
assert.Equal(t, "40.40.40.40", c.ClientIP())
|
||||||
|
|
||||||
|
// Test the legacy flag
|
||||||
c.engine.AppEngine = true
|
c.engine.AppEngine = true
|
||||||
assert.Equal(t, "50.50.50.50", c.ClientIP())
|
assert.Equal(t, "50.50.50.50", c.ClientIP())
|
||||||
c.engine.AppEngine = false
|
c.engine.AppEngine = false
|
||||||
|
|
4
gin.go
4
gin.go
|
@ -59,10 +59,10 @@ type RoutesInfo []RouteInfo
|
||||||
const (
|
const (
|
||||||
// When running on Google App Engine. Trust X-Appengine-Remote-Addr
|
// When running on Google App Engine. Trust X-Appengine-Remote-Addr
|
||||||
// for determining the client's IP
|
// for determining the client's IP
|
||||||
PlatformGoogleAppEngine = "google-app-engine"
|
PlatformGoogleAppEngine = "X-Appengine-Remote-Addr"
|
||||||
// When using Cloudflare's CDN. Trust CF-Connecting-IP for determining
|
// When using Cloudflare's CDN. Trust CF-Connecting-IP for determining
|
||||||
// the client's IP
|
// the client's IP
|
||||||
PlatformCloudflare = "cloudflare"
|
PlatformCloudflare = "CF-Connecting-IP"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Engine is the framework's instance, it contains the muxer, middleware and configuration settings.
|
// Engine is the framework's instance, it contains the muxer, middleware and configuration settings.
|
||||||
|
|
Loading…
Reference in New Issue