"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "context.go" between
gin-1.7.6.tar.gz and gin-1.7.7.tar.gz

About: Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API (with much better performance).

context.go  (gin-1.7.6):context.go  (gin-1.7.7)
skipping to change at line 12 skipping to change at line 12
// Use of this source code is governed by a MIT style // Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package gin package gin
import ( import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"math" "math"
"mime/multipart" "mime/multipart"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"strings" "strings"
"sync" "sync"
"time" "time"
skipping to change at line 56 skipping to change at line 57
type Context struct { type Context struct {
writermem responseWriter writermem responseWriter
Request *http.Request Request *http.Request
Writer ResponseWriter Writer ResponseWriter
Params Params Params Params
handlers HandlersChain handlers HandlersChain
index int8 index int8
fullPath string fullPath string
engine *Engine engine *Engine
params *Params params *Params
skippedNodes *[]skippedNode
// This mutex protect Keys map // This mutex protect Keys map
mu sync.RWMutex mu sync.RWMutex
// Keys is a key/value pair exclusively for the context of each request. // Keys is a key/value pair exclusively for the context of each request.
Keys map[string]interface{} Keys map[string]interface{}
// Errors is a list of errors attached to all the handlers/middlewares wh o used this context. // Errors is a list of errors attached to all the handlers/middlewares wh o used this context.
Errors errorMsgs Errors errorMsgs
skipping to change at line 99 skipping to change at line 101
c.Params = c.Params[0:0] c.Params = c.Params[0:0]
c.handlers = nil c.handlers = nil
c.index = -1 c.index = -1
c.fullPath = "" c.fullPath = ""
c.Keys = nil c.Keys = nil
c.Errors = c.Errors[0:0] c.Errors = c.Errors[0:0]
c.Accepted = nil c.Accepted = nil
c.queryCache = nil c.queryCache = nil
c.formCache = nil c.formCache = nil
*c.params = (*c.params)[0:0] *c.params = (*c.params)[:0]
*c.skippedNodes = (*c.skippedNodes)[:0]
} }
// Copy returns a copy of the current context that can be safely used outside th e request's scope. // Copy returns a copy of the current context that can be safely used outside th e request's scope.
// This has to be used when the context has to be passed to a goroutine. // This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context { func (c *Context) Copy() *Context {
cp := Context{ cp := Context{
writermem: c.writermem, writermem: c.writermem,
Request: c.Request, Request: c.Request,
Params: c.Params, Params: c.Params,
engine: c.engine, engine: c.engine,
skipping to change at line 728 skipping to change at line 731
if body == nil { if body == nil {
body, err = ioutil.ReadAll(c.Request.Body) body, err = ioutil.ReadAll(c.Request.Body)
if err != nil { if err != nil {
return err return err
} }
c.Set(BodyBytesKey, body) c.Set(BodyBytesKey, body)
} }
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's it will then try to parse the headers defined in Engine.RemoteIPHeade // If it is it will then try to parse the headers defined in Engine.RemoteIPHead
rs (defaulting to [X-Forwarded-For, X-Real-Ip]). ers (defaulting to [X-Forwarded-For, X-Real-Ip]).
// If the headers are nots syntactically valid OR the remote IP does not corresp // If the headers are not syntactically valid OR the remote IP does not correspo
ong to a trusted proxy, nd 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, continue running backwar
ds if error
if c.engine.TrustedPlatform != "" {
// Developers can define their own header of Trusted Platform or
use predefined constants
if addr := c.requestHeader(c.engine.TrustedPlatform); addr != ""
{
return addr
}
}
// Legacy "AppEngine" flag
if c.engine.AppEngine { if c.engine.AppEngine {
log.Println(`The AppEngine flag is going to be deprecated. Please check issues #2723 and #2739 and use 'TrustedPlatform: gin.PlatformGoogleAppEng ine' instead.`)
if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" { if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
return addr return addr
} }
} }
remoteIP, trusted := c.RemoteIP() remoteIP, trusted := c.RemoteIP()
if remoteIP == nil { if remoteIP == nil {
return "" return ""
} }
if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil { if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil {
for _, headerName := range c.engine.RemoteIPHeaders { for _, headerName := range c.engine.RemoteIPHeaders {
ip, valid := validateHeader(c.requestHeader(headerName)) ip, valid := c.engine.validateHeader(c.requestHeader(head erName))
if valid { if valid {
return ip return ip
} }
} }
} }
return remoteIP.String() return remoteIP.String()
} }
func (e *Engine) isTrustedProxy(ip net.IP) bool {
if e.trustedCIDRs != nil {
for _, cidr := range e.trustedCIDRs {
if cidr.Contains(ip) {
return true
}
}
}
return false
}
// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port). // RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
// It also checks if the remoteIP is a trusted proxy or not. // It also checks if the remoteIP is a trusted proxy or not.
// In order to perform this validation, it will see if the IP is contained withi n at least one of the CIDR blocks // In order to perform this validation, it will see if the IP is contained withi n at least one of the CIDR blocks
// defined in Engine.TrustedProxies // defined by Engine.SetTrustedProxies()
func (c *Context) RemoteIP() (net.IP, bool) { func (c *Context) RemoteIP() (net.IP, bool) {
ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr)) ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr))
if err != nil { if err != nil {
return nil, false return nil, false
} }
remoteIP := net.ParseIP(ip) remoteIP := net.ParseIP(ip)
if remoteIP == nil { if remoteIP == nil {
return nil, false return nil, false
} }
if c.engine.trustedCIDRs != nil { return remoteIP, c.engine.isTrustedProxy(remoteIP)
for _, cidr := range c.engine.trustedCIDRs {
if cidr.Contains(remoteIP) {
return remoteIP, true
}
}
}
return remoteIP, false
} }
func validateHeader(header string) (clientIP string, valid bool) { func (e *Engine) validateHeader(header string) (clientIP string, valid bool) {
if header == "" { if header == "" {
return "", false return "", false
} }
items := strings.Split(header, ",") items := strings.Split(header, ",")
for i, ipStr := range items { for i := len(items) - 1; i >= 0; i-- {
ipStr = strings.TrimSpace(ipStr) ipStr := strings.TrimSpace(items[i])
ip := net.ParseIP(ipStr) ip := net.ParseIP(ipStr)
if ip == nil { if ip == nil {
return "", false return "", false
} }
// We need to return the first IP in the list, but, // X-Forwarded-For is appended by proxy
// we should not early return since we need to validate that // Check IPs in reverse order and stop when find untrusted proxy
// the rest of the header is syntactically valid if (i == 0) || (!e.isTrustedProxy(ip)) {
if i == 0 { return ipStr, true
clientIP = ipStr
valid = true
} }
} }
return return
} }
// ContentType returns the Content-Type header of the request. // ContentType returns the Content-Type header of the request.
func (c *Context) ContentType() string { func (c *Context) ContentType() string {
return filterFlags(c.requestHeader("Content-Type")) return filterFlags(c.requestHeader("Content-Type"))
} }
 End of changes. 14 change blocks. 
28 lines changed or deleted 45 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)