RedirectScheme redirects based on X-Forwarded-Proto header
This commit is contained in:
parent
55ba4356f2
commit
ff17ac53df
3 changed files with 31 additions and 5 deletions
|
@ -12,7 +12,17 @@ Redirecting the Client to a Different Scheme/Port
|
||||||
TODO: add schema
|
TODO: add schema
|
||||||
-->
|
-->
|
||||||
|
|
||||||
RedirectScheme redirects requests from a scheme/port to another.
|
The RedirectScheme middleware redirects the request if the request scheme is different from the configured scheme.
|
||||||
|
The middleware does not work for websocket requests.
|
||||||
|
|
||||||
|
!!! warning "When behind another reverse-proxy"
|
||||||
|
|
||||||
|
When there is at least one other reverse-proxy between the client and Traefik,
|
||||||
|
the other reverse-proxy (i.e. the last hop) needs to be a [trusted](../../routing/entrypoints.md#forwarded-headers) one.
|
||||||
|
|
||||||
|
Otherwise, Traefik would clean up the X-Forwarded headers coming from this last hop,
|
||||||
|
and as the RedirectScheme middleware relies on them to determine the scheme used,
|
||||||
|
it would not function as intended.
|
||||||
|
|
||||||
## Configuration Examples
|
## Configuration Examples
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
const (
|
const (
|
||||||
typeSchemeName = "RedirectScheme"
|
typeSchemeName = "RedirectScheme"
|
||||||
uriPattern = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
|
uriPattern = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
|
||||||
|
xForwardedProto = "X-Forwarded-Proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewRedirectScheme creates a new RedirectScheme middleware.
|
// NewRedirectScheme creates a new RedirectScheme middleware.
|
||||||
|
@ -63,7 +64,11 @@ func rawURLScheme(req *http.Request) string {
|
||||||
scheme = schemeHTTPS
|
scheme = schemeHTTPS
|
||||||
}
|
}
|
||||||
|
|
||||||
if scheme == schemeHTTP && port == ":80" || scheme == schemeHTTPS && port == ":443" || port == "" {
|
if value := req.Header.Get(xForwardedProto); value != "" {
|
||||||
|
scheme = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if scheme == schemeHTTP && port == ":80" || scheme == schemeHTTPS && port == ":443" {
|
||||||
port = ""
|
port = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,22 @@ func TestRedirectSchemeHandler(t *testing.T) {
|
||||||
},
|
},
|
||||||
url: "http://foo",
|
url: "http://foo",
|
||||||
headers: map[string]string{
|
headers: map[string]string{
|
||||||
"X-Forwarded-Proto": "https",
|
"X-Forwarded-Proto": "http",
|
||||||
},
|
},
|
||||||
expectedURL: "https://foo",
|
expectedURL: "https://foo",
|
||||||
expectedStatus: http.StatusFound,
|
expectedStatus: http.StatusFound,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "HTTP to HTTPS, with X-Forwarded-Proto to HTTPS",
|
||||||
|
config: dynamic.RedirectScheme{
|
||||||
|
Scheme: "https",
|
||||||
|
},
|
||||||
|
url: "http://foo",
|
||||||
|
headers: map[string]string{
|
||||||
|
"X-Forwarded-Proto": "https",
|
||||||
|
},
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "HTTP with port to HTTPS without port",
|
desc: "HTTP with port to HTTPS without port",
|
||||||
config: dynamic.RedirectScheme{
|
config: dynamic.RedirectScheme{
|
||||||
|
|
Loading…
Reference in a new issue