Setting trusted platform using an enum-like (#2739)

This commit is contained in:
Alessandro (Ale) Segala 2021-06-23 17:58:10 -07:00 committed by GitHub
parent fb8a113f8d
commit dd8a27c0b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 13 deletions

View File

@ -9,6 +9,7 @@ import (
"fmt"
"io"
"io/ioutil"
"log"
"math"
"mime/multipart"
"net"
@ -731,17 +732,26 @@ 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 {
switch {
case c.engine.AppEngine:
// Check if we're running on a tursted platform
switch c.engine.TrustedPlatform {
case PlatformGoogleAppEngine:
if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
return addr
}
case c.engine.CloudflareProxy:
case PlatformCloudflare:
if addr := c.requestHeader("CF-Connecting-IP"); addr != "" {
return addr
}
}
// Legacy "AppEngine" flag
if c.engine.AppEngine {
log.Println(`The AppEngine flag is going to be deprecated. Please check issues #2723 and #2739 and use 'TrustedPlatform: gin.PlatformGoogleAppEngine' instead.`)
if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
return addr
}
}
remoteIP, trusted := c.RemoteIP()
if remoteIP == nil {
return ""

View File

@ -8,5 +8,5 @@
package gin
func init() {
defaultAppEngine = true
defaultPlatform = PlatformGoogleAppEngine
}

View File

@ -1410,7 +1410,7 @@ func TestContextClientIP(t *testing.T) {
c.Request.Header.Del("X-Forwarded-For")
c.Request.Header.Del("X-Real-IP")
c.engine.AppEngine = true
c.engine.TrustedPlatform = PlatformGoogleAppEngine
assert.Equal(t, "50.50.50.50", c.ClientIP())
c.Request.Header.Del("X-Appengine-Remote-Addr")
@ -1470,19 +1470,27 @@ func TestContextClientIP(t *testing.T) {
assert.Equal(t, "10.10.10.10", c.ClientIP())
c.engine.RemoteIPHeaders = []string{}
c.engine.TrustedPlatform = PlatformGoogleAppEngine
assert.Equal(t, "50.50.50.50", c.ClientIP())
// Test the legacy flag
c.engine.TrustedPlatform = ""
c.engine.AppEngine = true
assert.Equal(t, "50.50.50.50", c.ClientIP())
c.engine.AppEngine = false
c.engine.TrustedPlatform = PlatformGoogleAppEngine
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
c.engine.TrustedPlatform = PlatformCloudflare
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())
c.engine.TrustedPlatform = ""
// no port
c.Request.RemoteAddr = "50.50.50.50"
assert.Empty(t, c.ClientIP())
@ -1494,6 +1502,7 @@ func resetContextForClientIPTests(c *Context) {
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.TrustedPlatform = ""
c.engine.AppEngine = false
}

23
gin.go
View File

@ -25,7 +25,7 @@ var (
default405Body = []byte("405 method not allowed")
)
var defaultAppEngine bool
var defaultPlatform string
// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)
@ -52,6 +52,16 @@ type RouteInfo struct {
// RoutesInfo defines a RouteInfo array.
type RoutesInfo []RouteInfo
// Trusted platforms
const (
// When running on Google App Engine. Trust X-Appengine-Remote-Addr
// for determining the client's IP
PlatformGoogleAppEngine = "google-app-engine"
// When using Cloudflare's CDN. Trust CF-Connecting-IP for determining
// the client's IP
PlatformCloudflare = "cloudflare"
)
// Engine is the framework's instance, it contains the muxer, middleware and configuration settings.
// Create an instance of Engine, by using New() or Default()
type Engine struct {
@ -101,14 +111,15 @@ type Engine struct {
// `true`.
TrustedProxies []string
// If set to a constant of value gin.Platform*, trusts the headers set by
// that platform, for example to determine the client IP
TrustedPlatform string
// DEPRECATED: USE `TrustedPlatform` WITH VALUE `gin.GoogleAppEngine` INSTEAD
// #726 #755 If enabled, it will trust some headers starting with
// '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
@ -164,7 +175,7 @@ func New() *Engine {
ForwardedByClientIP: true,
RemoteIPHeaders: []string{"X-Forwarded-For", "X-Real-IP"},
TrustedProxies: []string{"0.0.0.0/0"},
AppEngine: defaultAppEngine,
TrustedPlatform: defaultPlatform,
UseRawPath: false,
RemoveExtraSlash: false,
UnescapePathValues: true,