mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
add 'HostProxyHeaders' Configuration field
Former-commit-id: 067360d8db638d6f268d154b50fd872c465eaf1a
This commit is contained in:
parent
12e61f4456
commit
78a45163e3
|
@ -417,7 +417,7 @@ New Package-level Variables:
|
||||||
|
|
||||||
New Context Methods:
|
New Context Methods:
|
||||||
|
|
||||||
- `Context.IsSSL() bool` reports whether the request is under HTTPS SSL (New `Configuration.SSLProxyHeaders` field too).
|
- `Context.IsSSL() bool` reports whether the request is under HTTPS SSL (New `Configuration.SSLProxyHeaders` and `HostProxyHeaders` fields too).
|
||||||
- `Context.GzipReader(enable bool)` method and `iris.GzipReader` middleware to enable future request read body calls to decompress data using gzip, [example](_examples/request-body/read-gzip).
|
- `Context.GzipReader(enable bool)` method and `iris.GzipReader` middleware to enable future request read body calls to decompress data using gzip, [example](_examples/request-body/read-gzip).
|
||||||
- `Context.RegisterDependency(v interface{})` and `Context.RemoveDependency(typ reflect.Type)` to register/remove struct dependencies on serve-time through a middleware.
|
- `Context.RegisterDependency(v interface{})` and `Context.RemoveDependency(typ reflect.Type)` to register/remove struct dependencies on serve-time through a middleware.
|
||||||
- `Context.SetID(id interface{})` and `Context.GetID() interface{}` added to register a custom unique indetifier to the Context, if necessary.
|
- `Context.SetID(id interface{})` and `Context.GetID() interface{}` added to register a custom unique indetifier to the Context, if necessary.
|
||||||
|
|
|
@ -4,5 +4,13 @@ FireMethodNotAllowed: true
|
||||||
DisableBodyConsumptionOnUnmarshal: true
|
DisableBodyConsumptionOnUnmarshal: true
|
||||||
TimeFormat: Mon, 01 Jan 2006 15:04:05 GMT
|
TimeFormat: Mon, 01 Jan 2006 15:04:05 GMT
|
||||||
Charset: UTF-8
|
Charset: UTF-8
|
||||||
|
SSLProxyHeaders:
|
||||||
|
X-Forwarded-Proto: https
|
||||||
|
HostProxyHeaders:
|
||||||
|
X-Host: true
|
||||||
|
RemoteAddrHeaders:
|
||||||
|
X-Real-Ip: true
|
||||||
|
X-Forwarded-For: true
|
||||||
|
CF-Connecting-IP: true
|
||||||
Other:
|
Other:
|
||||||
Addr: :8080
|
Addr: :8080
|
|
@ -354,15 +354,18 @@ func WithPostMaxMemory(limit int64) Configurator {
|
||||||
// that the client may sent.
|
// that the client may sent.
|
||||||
//
|
//
|
||||||
// Defaults to an empty map but an example usage is:
|
// Defaults to an empty map but an example usage is:
|
||||||
// WithRemoteAddrHeader("X-Forwarded-For")
|
// WithRemoteAddrHeader("X-Forwarded-For", "CF-Connecting-IP")
|
||||||
//
|
//
|
||||||
// Look `context.RemoteAddr()` for more.
|
// Look `context.RemoteAddr()` for more.
|
||||||
func WithRemoteAddrHeader(headerName string) Configurator {
|
func WithRemoteAddrHeader(header ...string) Configurator {
|
||||||
return func(app *Application) {
|
return func(app *Application) {
|
||||||
if app.config.RemoteAddrHeaders == nil {
|
if app.config.RemoteAddrHeaders == nil {
|
||||||
app.config.RemoteAddrHeaders = make(map[string]bool)
|
app.config.RemoteAddrHeaders = make(map[string]bool)
|
||||||
}
|
}
|
||||||
app.config.RemoteAddrHeaders[headerName] = true
|
|
||||||
|
for _, k := range header {
|
||||||
|
app.config.RemoteAddrHeaders[k] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +411,20 @@ func WithSSLProxyHeader(headerKey, headerValue string) Configurator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithHostProxyHeader sets a HostProxyHeaders key value pair.
|
||||||
|
// Example: WithHostProxyHeader("X-Host").
|
||||||
|
// See `Context.Host` for more.
|
||||||
|
func WithHostProxyHeader(headers ...string) Configurator {
|
||||||
|
return func(app *Application) {
|
||||||
|
if app.config.HostProxyHeaders == nil {
|
||||||
|
app.config.HostProxyHeaders = make(map[string]bool)
|
||||||
|
}
|
||||||
|
for _, k := range headers {
|
||||||
|
app.config.HostProxyHeaders[k] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithOtherValue adds a value based on a key to the Other setting.
|
// WithOtherValue adds a value based on a key to the Other setting.
|
||||||
//
|
//
|
||||||
// See `Configuration.Other`.
|
// See `Configuration.Other`.
|
||||||
|
@ -956,7 +973,6 @@ type Configuration struct {
|
||||||
//
|
//
|
||||||
// Look `context.RemoteAddr()` for more.
|
// Look `context.RemoteAddr()` for more.
|
||||||
RemoteAddrHeaders map[string]bool `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
|
RemoteAddrHeaders map[string]bool `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
|
||||||
|
|
||||||
// RemoteAddrPrivateSubnets defines the private sub-networks.
|
// RemoteAddrPrivateSubnets defines the private sub-networks.
|
||||||
// They are used to be compared against
|
// They are used to be compared against
|
||||||
// IP Addresses fetched through `RemoteAddrHeaders` or `Context.Request.RemoteAddr`.
|
// IP Addresses fetched through `RemoteAddrHeaders` or `Context.Request.RemoteAddr`.
|
||||||
|
@ -987,14 +1003,18 @@ type Configuration struct {
|
||||||
// End: net.ParseIP("198.19.255.255"),
|
// End: net.ParseIP("198.19.255.255"),
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Look `context.RemoteAddr()` for more.
|
// Look `Context.RemoteAddr()` for more.
|
||||||
RemoteAddrPrivateSubnets []netutil.IPRange `json:"remoteAddrPrivateSubnets" yaml:"RemoteAddrPrivateSubnets" toml:"RemoteAddrPrivateSubnets"`
|
RemoteAddrPrivateSubnets []netutil.IPRange `json:"remoteAddrPrivateSubnets" yaml:"RemoteAddrPrivateSubnets" toml:"RemoteAddrPrivateSubnets"`
|
||||||
// SSLProxyHeaders defines the set of header key values
|
// SSLProxyHeaders defines the set of header key values
|
||||||
// that would indicate a valid https Request (look `context.IsSSL()`).
|
// that would indicate a valid https Request (look `Context.IsSSL()`).
|
||||||
// Example: `map[string]string{"X-Forwarded-Proto": "https"}`.
|
// Example: `map[string]string{"X-Forwarded-Proto": "https"}`.
|
||||||
//
|
//
|
||||||
// Defaults to empty map.
|
// Defaults to empty map.
|
||||||
SSLProxyHeaders map[string]string `json:"sslProxyHeaders" yaml:"SSLProxyHeaders" toml:"SSLProxyHeaders"`
|
SSLProxyHeaders map[string]string `json:"sslProxyHeaders" yaml:"SSLProxyHeaders" toml:"SSLProxyHeaders"`
|
||||||
|
// HostProxyHeaders defines the set of headers that may hold a proxied hostname value for the clients.
|
||||||
|
// Look `Context.Host()` for more.
|
||||||
|
// Defaults to empty map.
|
||||||
|
HostProxyHeaders map[string]bool `json:"hostProxyHeaders" yaml:"HostProxyHeaders" toml:"HostProxyHeaders"`
|
||||||
// Other are the custom, dynamic options, can be empty.
|
// Other are the custom, dynamic options, can be empty.
|
||||||
// This field used only by you to set any app's options you want.
|
// This field used only by you to set any app's options you want.
|
||||||
//
|
//
|
||||||
|
@ -1124,6 +1144,11 @@ func (c Configuration) GetRemoteAddrPrivateSubnets() []netutil.IPRange {
|
||||||
return c.RemoteAddrPrivateSubnets
|
return c.RemoteAddrPrivateSubnets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHostProxyHeaders returns the HostProxyHeaders field.
|
||||||
|
func (c Configuration) GetHostProxyHeaders() map[string]bool {
|
||||||
|
return c.HostProxyHeaders
|
||||||
|
}
|
||||||
|
|
||||||
// GetOther returns the Other field.
|
// GetOther returns the Other field.
|
||||||
func (c Configuration) GetOther() map[string]interface{} {
|
func (c Configuration) GetOther() map[string]interface{} {
|
||||||
return c.Other
|
return c.Other
|
||||||
|
@ -1259,6 +1284,15 @@ func WithConfiguration(c Configuration) Configurator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v := c.HostProxyHeaders; len(v) > 0 {
|
||||||
|
if main.HostProxyHeaders == nil {
|
||||||
|
main.HostProxyHeaders = make(map[string]bool, len(v))
|
||||||
|
}
|
||||||
|
for key, value := range v {
|
||||||
|
main.HostProxyHeaders[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if v := c.Other; len(v) > 0 {
|
if v := c.Other; len(v) > 0 {
|
||||||
if main.Other == nil {
|
if main.Other == nil {
|
||||||
main.Other = make(map[string]interface{}, len(v))
|
main.Other = make(map[string]interface{}, len(v))
|
||||||
|
@ -1325,6 +1359,7 @@ func DefaultConfiguration() Configuration {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SSLProxyHeaders: make(map[string]string),
|
SSLProxyHeaders: make(map[string]string),
|
||||||
|
HostProxyHeaders: make(map[string]bool),
|
||||||
EnableOptimizations: false,
|
EnableOptimizations: false,
|
||||||
Other: make(map[string]interface{}),
|
Other: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,12 +153,14 @@ EnableOptimizations: true
|
||||||
DisableBodyConsumptionOnUnmarshal: true
|
DisableBodyConsumptionOnUnmarshal: true
|
||||||
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT"
|
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
Charset: "utf-8"
|
Charset: "utf-8"
|
||||||
|
|
||||||
RemoteAddrHeaders:
|
RemoteAddrHeaders:
|
||||||
X-Real-Ip: true
|
X-Real-Ip: true
|
||||||
X-Forwarded-For: true
|
X-Forwarded-For: true
|
||||||
CF-Connecting-IP: true
|
CF-Connecting-IP: true
|
||||||
|
HostProxyHeaders:
|
||||||
|
X-Host: true
|
||||||
|
SSLProxyHeaders:
|
||||||
|
X-Forwarded-Proto: https
|
||||||
Other:
|
Other:
|
||||||
MyServerName: "Iris: https://github.com/kataras/iris"
|
MyServerName: "Iris: https://github.com/kataras/iris"
|
||||||
`
|
`
|
||||||
|
@ -224,6 +226,34 @@ Other:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectedHostProxyHeaders := map[string]bool{
|
||||||
|
"X-Host": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, got := len(c.HostProxyHeaders), len(expectedHostProxyHeaders); expected != got {
|
||||||
|
t.Fatalf("error on TestConfigurationYAML: Expected HostProxyHeaders' len(%d) and got(%d), len is not the same", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range c.HostProxyHeaders {
|
||||||
|
if expected, got := expectedHostProxyHeaders[k], v; expected != got {
|
||||||
|
t.Fatalf("error on TestConfigurationYAML: Expected HostProxyHeaders[%s] = %t but got %t", k, expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedSSLProxyHeaders := map[string]string{
|
||||||
|
"X-Forwarded-Proto": "https",
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, got := len(c.SSLProxyHeaders), len(c.SSLProxyHeaders); expected != got {
|
||||||
|
t.Fatalf("error on TestConfigurationYAML: Expected SSLProxyHeaders' len(%d) and got(%d), len is not the same", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range c.SSLProxyHeaders {
|
||||||
|
if expected, got := expectedSSLProxyHeaders[k], v; expected != got {
|
||||||
|
t.Fatalf("error on TestConfigurationYAML: Expected SSLProxyHeaders[%s] = %s but got %s", k, expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(c.Other) == 0 {
|
if len(c.Other) == 0 {
|
||||||
t.Fatalf("error on TestConfigurationYAML: Expected Other to be filled")
|
t.Fatalf("error on TestConfigurationYAML: Expected Other to be filled")
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,8 @@ type ConfigurationReadOnly interface {
|
||||||
GetRemoteAddrPrivateSubnets() []netutil.IPRange
|
GetRemoteAddrPrivateSubnets() []netutil.IPRange
|
||||||
// GetSSLProxyHeaders returns the SSLProxyHeaders field.
|
// GetSSLProxyHeaders returns the SSLProxyHeaders field.
|
||||||
GetSSLProxyHeaders() map[string]string
|
GetSSLProxyHeaders() map[string]string
|
||||||
|
// GetHostProxyHeaders returns the HostProxyHeaders field.
|
||||||
|
GetHostProxyHeaders() map[string]bool
|
||||||
// GetOther returns the Other field.
|
// GetOther returns the Other field.
|
||||||
GetOther() map[string]interface{}
|
GetOther() map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,6 +346,7 @@ type Context interface {
|
||||||
// based on the 'escape'.
|
// based on the 'escape'.
|
||||||
RequestPath(escape bool) string
|
RequestPath(escape bool) string
|
||||||
// Host returns the host part of the current url.
|
// Host returns the host part of the current url.
|
||||||
|
// This method makes use of the `Configuration.HostProxyHeaders` field too.
|
||||||
Host() string
|
Host() string
|
||||||
// Subdomain returns the subdomain of this request, if any.
|
// Subdomain returns the subdomain of this request, if any.
|
||||||
// Note that this is a fast method which does not cover all cases.
|
// Note that this is a fast method which does not cover all cases.
|
||||||
|
@ -1813,7 +1814,18 @@ func (ctx *context) RequestPath(escape bool) string {
|
||||||
// } no, it will not work because map is a random peek data structure.
|
// } no, it will not work because map is a random peek data structure.
|
||||||
|
|
||||||
// Host returns the host part of the current URI.
|
// Host returns the host part of the current URI.
|
||||||
|
// This method makes use of the `Configuration.HostProxyHeaders` field too.
|
||||||
func (ctx *context) Host() string {
|
func (ctx *context) Host() string {
|
||||||
|
for header, ok := range ctx.app.ConfigurationReadOnly().GetHostProxyHeaders() {
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if host := ctx.GetHeader(header); host != "" {
|
||||||
|
return host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GetHost(ctx.request)
|
return GetHost(ctx.request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user