diff --git a/router/middleware/location/location.go b/router/middleware/location/location.go index 08dc91710..9e5290113 100644 --- a/router/middleware/location/location.go +++ b/router/middleware/location/location.go @@ -15,6 +15,27 @@ func Resolve(c *gin.Context) { c.Next() } +// parseHeader parses non unique headers value +// from a http.Request and return a slice of the values +// queried from the header +func parseHeader(r *http.Request, header string, token string) (val []string) { + for _, v := range r.Header[header] { + options := strings.Split(v, ";") + for _, o := range options { + keyvalue := strings.Split(o, "=") + var key, value string + if len(keyvalue) > 1 { + key, value = strings.TrimSpace(keyvalue[0]), strings.TrimSpace(keyvalue[1]) + } + key = strings.ToLower(key) + if key == token { + val = append(val, value) + } + } + } + return +} + // resolveScheme is a helper function that evaluates the http.Request // and returns the scheme, HTTP or HTTPS. It is able to detect, // using the X-Forwarded-Proto, if the original request was HTTPS @@ -29,6 +50,8 @@ func resolveScheme(r *http.Request) string { return "https" case r.Header.Get("X-Forwarded-Proto") == "https": return "https" + case len(r.Header.Get("Forwarded")) != 0 && len(parseHeader(r, "Forwarded", "proto")) != 0 && parseHeader(r, "Forwarded", "proto")[0] == "https": + return "https" default: return "http" } @@ -46,8 +69,12 @@ func resolveHost(r *http.Request) string { return r.URL.Host case len(r.Header.Get("X-Forwarded-For")) != 0: return r.Header.Get("X-Forwarded-For") + case len(r.Header.Get("Forwarded")) != 0 && len(parseHeader(r, "Forwarded", "for")) != 0: + return parseHeader(r, "Forwarded", "for")[0] case len(r.Header.Get("X-Host")) != 0: return r.Header.Get("X-Host") + case len(r.Header.Get("Forwarded")) != 0 && len(parseHeader(r, "Forwarded", "host")) != 0: + return parseHeader(r, "Forwarded", "host")[0] case len(r.Header.Get("XFF")) != 0: return r.Header.Get("XFF") case len(r.Header.Get("X-Real-IP")) != 0: