Repository: gin-gonic/gin
Pull request #2760 (2021-06-23 15:22:46)

fix typo and add comments
In `recovery.go`:
- Fix typo in `CustomRecovery` comments.
- Add comments for `timeFormat`.


codecov[bot]: # [Codecov](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) Report
> Merging [#2760](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) (5944f8d) into [master](https://codecov.io/gh/gin-gonic/gin/commit/fb8a113f8d2d526e57d3623dbd4b9fa12c40d0f7?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) (fb8a113) will **decrease** coverage by `0.02%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/gin-gonic/gin/pull/2760/graphs/tree.svg?width=650&height=150&src=pr&token=Qpqxhwery8&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic)](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic)

```diff
@@            Coverage Diff             @@
##           master    #2760      +/-   ##
==========================================
- Coverage   98.69%   98.67%   -0.03%     
==========================================
  Files          41       38       -3     
  Lines        2072     2040      -32     
==========================================
- Hits         2045     2013      -32     
  Misses         15       15              
  Partials       12       12              
```


| [Impacted Files](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | Coverage Δ | |
|---|---|---|
| [recovery.go](https://codecov.io/gh/gin-gonic/gin/pull/2760/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic#diff-cmVjb3ZlcnkuZ28=) | `97.18% <ø> (ø)` | |
| [binding/binding.go](https://codecov.io/gh/gin-gonic/gin/pull/2760/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic#diff-YmluZGluZy9iaW5kaW5nLmdv) | | |
| [render/msgpack.go](https://codecov.io/gh/gin-gonic/gin/pull/2760/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic#diff-cmVuZGVyL21zZ3BhY2suZ28=) | | |
| [binding/msgpack.go](https://codecov.io/gh/gin-gonic/gin/pull/2760/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic#diff-YmluZGluZy9tc2dwYWNrLmdv) | | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic). Last update [fb8a113...5944f8d](https://codecov.io/gh/gin-gonic/gin/pull/2760?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic).


Patch:
diff --git a/context.go b/context.go
index 0c1fb07..5c1aba5 100644
--- a/context.go
+++ b/context.go
@@ -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 ""
diff --git a/context_appengine.go b/context_appengine.go
index d565843..8bf9389 100644
--- a/context_appengine.go
+++ b/context_appengine.go
@@ -8,5 +8,5 @@
 package gin
 
 func init() {
-	defaultAppEngine = true
+	defaultPlatform = PlatformGoogleAppEngine
 }
diff --git a/gin.go b/gin.go
index 00686e7..fd4fa51 100644
--- a/gin.go
+++ b/gin.go
@@ -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,
diff --git a/recovery.go b/recovery.go
index 563f5aa..8519959 100644
--- a/recovery.go
+++ b/recovery.go
@@ -34,7 +34,7 @@ func Recovery() HandlerFunc {
 	return RecoveryWithWriter(DefaultErrorWriter)
 }
 
-//CustomRecovery returns a middleware that recovers from any panics and calls the provided handle func to handle it.
+// CustomRecovery returns a middleware that recovers from any panics and calls the provided handle func to handle it.
 func CustomRecovery(handle RecoveryFunc) HandlerFunc {
 	return RecoveryWithWriter(DefaultErrorWriter, handle)
 }
@@ -165,6 +165,7 @@ func function(pc uintptr) []byte {
 	return name
 }
 
+// timeFormat returns a customized time string for logger.
 func timeFormat(t time.Time) string {
 	timeString := t.Format("2006/01/02 - 15:04:05")
 	return timeString


Test patch:
diff --git a/context_test.go b/context_test.go
index e0de717..93b58ee 100644
--- a/context_test.go
+++ b/context_test.go
@@ -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
 }