1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-17 09:57:01 +00:00

Add Configuration.RemoteAddrHeadersForce as requested at #1567 and change RemoteAddrHeaders from map to string slice

Read HISTORY.md entry
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-07-26 14:37:30 +03:00
parent a50f0ed5ba
commit 22a89c12cb
7 changed files with 101 additions and 84 deletions

View File

@@ -351,48 +351,38 @@ func WithPostMaxMemory(limit int64) Configurator {
}
}
// WithRemoteAddrHeader enables or adds a new or existing request header name
// WithRemoteAddrHeader adds a new request header name
// that can be used to validate the client's real IP.
//
// By-default no "X-" header is consired safe to be used for retrieving the
// client's IP address, because those headers can manually change by
// the client. But sometimes are useful e.g., when behind a proxy
// you want to enable the "X-Forwarded-For" or when cloudflare
// you want to enable the "CF-Connecting-IP", inneed you
// can allow the `ctx.RemoteAddr()` to use any header
// that the client may sent.
//
// Defaults to an empty map but an example usage is:
// WithRemoteAddrHeader("X-Forwarded-For", "CF-Connecting-IP")
//
// Look `context.RemoteAddr()` for more.
func WithRemoteAddrHeader(header ...string) Configurator {
return func(app *Application) {
if app.config.RemoteAddrHeaders == nil {
app.config.RemoteAddrHeaders = make(map[string]bool)
}
for _, h := range header {
exists := false
for _, v := range app.config.RemoteAddrHeaders {
if v == h {
exists = true
}
}
for _, k := range header {
app.config.RemoteAddrHeaders[k] = true
if !exists {
app.config.RemoteAddrHeaders = append(app.config.RemoteAddrHeaders, h)
}
}
}
}
// WithoutRemoteAddrHeader disables an existing request header name
// WithoutRemoteAddrHeader removes an existing request header name
// that can be used to validate and parse the client's real IP.
//
//
// Keep note that RemoteAddrHeaders is already defaults to an empty map
// so you don't have to call this Configurator if you didn't
// add allowed headers via configuration or via `WithRemoteAddrHeader` before.
//
// Look `context.RemoteAddr()` for more.
func WithoutRemoteAddrHeader(headerName string) Configurator {
return func(app *Application) {
if app.config.RemoteAddrHeaders == nil {
app.config.RemoteAddrHeaders = make(map[string]bool)
tmp := app.config.RemoteAddrHeaders[:0]
for _, v := range app.config.RemoteAddrHeaders {
if v != headerName {
tmp = append(tmp, v)
}
}
app.config.RemoteAddrHeaders[headerName] = false
app.config.RemoteAddrHeaders = tmp
}
}
@@ -783,21 +773,27 @@ type Configuration struct {
// that can be valid to parse the client's IP based on.
// By-default no "X-" header is consired safe to be used for retrieving the
// client's IP address, because those headers can manually change by
// the client. But sometimes are useful e.g., when behind a proxy
// the client. But sometimes are useful e.g. when behind a proxy
// you want to enable the "X-Forwarded-For" or when cloudflare
// you want to enable the "CF-Connecting-IP", inneed you
// you want to enable the "CF-Connecting-IP", indeed you
// can allow the `ctx.RemoteAddr()` to use any header
// that the client may sent.
//
// Defaults to an empty map but an example usage is:
// Defaults to an empty slice but an example usage is:
// RemoteAddrHeaders {
// "X-Real-Ip": true,
// "X-Forwarded-For": true,
// "CF-Connecting-IP": true,
// "X-Real-Ip",
// "X-Forwarded-For",
// "CF-Connecting-IP",
// }
//
// Look `context.RemoteAddr()` for more.
RemoteAddrHeaders map[string]bool `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
RemoteAddrHeaders []string `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
// RemoteAddrHeadersForce forces the `Context.RemoteAddr()` method
// to return the first entry of a request header as a fallback,
// even if that IP is a part of the `RemoteAddrPrivateSubnets` list.
// The default behavior, if a remote address is part of the `RemoteAddrPrivateSubnets`,
// is to retrieve the IP from the `Request.RemoteAddr` field instead.
RemoteAddrHeadersForce bool `json:"remoteAddrHeadersForce,omitempty" yaml:"RemoteAddrHeadersForce" toml:"RemoteAddrHeadersForce"`
// RemoteAddrPrivateSubnets defines the private sub-networks.
// They are used to be compared against
// IP Addresses fetched through `RemoteAddrHeaders` or `Context.Request.RemoteAddr`.
@@ -960,10 +956,15 @@ func (c Configuration) GetViewDataContextKey() string {
}
// GetRemoteAddrHeaders returns the RemoteAddrHeaders field.
func (c Configuration) GetRemoteAddrHeaders() map[string]bool {
func (c Configuration) GetRemoteAddrHeaders() []string {
return c.RemoteAddrHeaders
}
// GetRemoteAddrHeadersForce returns RemoteAddrHeadersForce field.
func (c Configuration) GetRemoteAddrHeadersForce() bool {
return c.RemoteAddrHeadersForce
}
// GetSSLProxyHeaders returns the SSLProxyHeaders field.
func (c Configuration) GetSSLProxyHeaders() map[string]string {
return c.SSLProxyHeaders
@@ -1102,12 +1103,11 @@ func WithConfiguration(c Configuration) Configurator {
}
if v := c.RemoteAddrHeaders; len(v) > 0 {
if main.RemoteAddrHeaders == nil {
main.RemoteAddrHeaders = make(map[string]bool, len(v))
}
for key, value := range v {
main.RemoteAddrHeaders[key] = value
}
main.RemoteAddrHeaders = v
}
if v := c.RemoteAddrHeadersForce; v {
main.RemoteAddrHeadersForce = v
}
if v := c.RemoteAddrPrivateSubnets; len(v) > 0 {
@@ -1165,13 +1165,14 @@ func DefaultConfiguration() Configuration {
// The request body the size limit
// can be set by the middleware `LimitRequestBodySize`
// or `context#SetMaxRequestBodySize`.
PostMaxMemory: 32 << 20, // 32MB
LocaleContextKey: "iris.locale",
LanguageContextKey: "iris.locale.language",
VersionContextKey: "iris.api.version",
ViewLayoutContextKey: "iris.viewLayout",
ViewDataContextKey: "iris.viewData",
RemoteAddrHeaders: make(map[string]bool),
PostMaxMemory: 32 << 20, // 32MB
LocaleContextKey: "iris.locale",
LanguageContextKey: "iris.locale.language",
VersionContextKey: "iris.api.version",
ViewLayoutContextKey: "iris.viewLayout",
ViewDataContextKey: "iris.viewData",
RemoteAddrHeaders: nil,
RemoteAddrHeadersForce: false,
RemoteAddrPrivateSubnets: []netutil.IPRange{
{
Start: net.ParseIP("10.0.0.0"),