diff --git a/docs/content/middlewares/http/redirectscheme.md b/docs/content/middlewares/http/redirectscheme.md index 2d4520867..3e37e89fc 100644 --- a/docs/content/middlewares/http/redirectscheme.md +++ b/docs/content/middlewares/http/redirectscheme.md @@ -12,7 +12,17 @@ Redirecting the Client to a Different Scheme/Port 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 diff --git a/pkg/middlewares/redirect/redirect_scheme.go b/pkg/middlewares/redirect/redirect_scheme.go index 00e30b8b4..204e1a16c 100644 --- a/pkg/middlewares/redirect/redirect_scheme.go +++ b/pkg/middlewares/redirect/redirect_scheme.go @@ -13,8 +13,9 @@ import ( ) const ( - typeSchemeName = "RedirectScheme" - uriPattern = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$` + typeSchemeName = "RedirectScheme" + uriPattern = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$` + xForwardedProto = "X-Forwarded-Proto" ) // NewRedirectScheme creates a new RedirectScheme middleware. @@ -63,7 +64,11 @@ func rawURLScheme(req *http.Request) string { 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 = "" } diff --git a/pkg/middlewares/redirect/redirect_scheme_test.go b/pkg/middlewares/redirect/redirect_scheme_test.go index 710a681ee..3d94bfcda 100644 --- a/pkg/middlewares/redirect/redirect_scheme_test.go +++ b/pkg/middlewares/redirect/redirect_scheme_test.go @@ -47,11 +47,22 @@ func TestRedirectSchemeHandler(t *testing.T) { }, url: "http://foo", headers: map[string]string{ - "X-Forwarded-Proto": "https", + "X-Forwarded-Proto": "http", }, expectedURL: "https://foo", 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", config: dynamic.RedirectScheme{