X-Forwarded-Proto must not skip the redirection.

This commit is contained in:
Ludovic Fernandez 2019-11-15 12:36:04 +01:00 committed by Traefiker Bot
parent 3fd330c2fb
commit 42a8d84a1f
3 changed files with 48 additions and 17 deletions

View file

@ -132,19 +132,13 @@ func rawURL(req *http.Request) string {
uri = match[4] uri = match[4]
} }
if req.TLS != nil || isXForwardedHTTPS(req) { if req.TLS != nil {
scheme = "https" scheme = "https"
} }
return strings.Join([]string{scheme, "://", host, port, uri}, "") return strings.Join([]string{scheme, "://", host, port, uri}, "")
} }
func isXForwardedHTTPS(request *http.Request) bool {
xForwardedProto := request.Header.Get("X-Forwarded-Proto")
return len(xForwardedProto) > 0 && xForwardedProto == "https"
}
func applyString(in string, out io.Writer, req *http.Request) error { func applyString(in string, out io.Writer, req *http.Request) error {
t, err := template.New("t").Parse(in) t, err := template.New("t").Parse(in)
if err != nil { if err != nil {

View file

@ -19,6 +19,7 @@ func TestRedirectRegexHandler(t *testing.T) {
config dynamic.RedirectRegex config dynamic.RedirectRegex
method string method string
url string url string
headers map[string]string
secured bool secured bool
expectedURL string expectedURL string
expectedStatus int expectedStatus int
@ -104,6 +105,19 @@ func TestRedirectRegexHandler(t *testing.T) {
expectedURL: "https://foo:443", expectedURL: "https://foo:443",
expectedStatus: http.StatusFound, expectedStatus: http.StatusFound,
}, },
{
desc: "HTTP to HTTPS, with X-Forwarded-Proto",
config: dynamic.RedirectRegex{
Regex: `http://foo:80`,
Replacement: "https://foo:443",
},
url: "http://foo:80",
headers: map[string]string{
"X-Forwarded-Proto": "https",
},
expectedURL: "https://foo:443",
expectedStatus: http.StatusFound,
},
{ {
desc: "HTTPS to HTTP", desc: "HTTPS to HTTP",
config: dynamic.RedirectRegex{ config: dynamic.RedirectRegex{
@ -171,12 +185,18 @@ func TestRedirectRegexHandler(t *testing.T) {
if test.method != "" { if test.method != "" {
method = test.method method = test.method
} }
r := testhelpers.MustNewRequest(method, test.url, nil)
req := testhelpers.MustNewRequest(method, test.url, nil)
if test.secured { if test.secured {
r.TLS = &tls.ConnectionState{} req.TLS = &tls.ConnectionState{}
} }
r.Header.Set("X-Foo", "bar")
handler.ServeHTTP(recorder, r) for k, v := range test.headers {
req.Header.Set(k, v)
}
req.Header.Set("X-Foo", "bar")
handler.ServeHTTP(recorder, req)
assert.Equal(t, test.expectedStatus, recorder.Code) assert.Equal(t, test.expectedStatus, recorder.Code)
switch test.expectedStatus { switch test.expectedStatus {

View file

@ -19,6 +19,7 @@ func TestRedirectSchemeHandler(t *testing.T) {
config dynamic.RedirectScheme config dynamic.RedirectScheme
method string method string
url string url string
headers map[string]string
secured bool secured bool
expectedURL string expectedURL string
expectedStatus int expectedStatus int
@ -39,6 +40,18 @@ func TestRedirectSchemeHandler(t *testing.T) {
expectedURL: "https://foo", expectedURL: "https://foo",
expectedStatus: http.StatusFound, expectedStatus: http.StatusFound,
}, },
{
desc: "HTTP to HTTPS, with X-Forwarded-Proto",
config: dynamic.RedirectScheme{
Scheme: "https",
},
url: "http://foo",
headers: map[string]string{
"X-Forwarded-Proto": "https",
},
expectedURL: "https://foo",
expectedStatus: http.StatusFound,
},
{ {
desc: "HTTP with port to HTTPS without port", desc: "HTTP with port to HTTPS without port",
config: dynamic.RedirectScheme{ config: dynamic.RedirectScheme{
@ -197,13 +210,17 @@ func TestRedirectSchemeHandler(t *testing.T) {
if test.method != "" { if test.method != "" {
method = test.method method = test.method
} }
r := httptest.NewRequest(method, test.url, nil) req := httptest.NewRequest(method, test.url, nil)
for k, v := range test.headers {
req.Header.Set(k, v)
}
if test.secured { if test.secured {
r.TLS = &tls.ConnectionState{} req.TLS = &tls.ConnectionState{}
} }
r.Header.Set("X-Foo", "bar") req.Header.Set("X-Foo", "bar")
handler.ServeHTTP(recorder, r) handler.ServeHTTP(recorder, req)
assert.Equal(t, test.expectedStatus, recorder.Code) assert.Equal(t, test.expectedStatus, recorder.Code)
@ -223,9 +240,9 @@ func TestRedirectSchemeHandler(t *testing.T) {
if re.Match([]byte(test.url)) { if re.Match([]byte(test.url)) {
match := re.FindStringSubmatch(test.url) match := re.FindStringSubmatch(test.url)
r.RequestURI = match[4] req.RequestURI = match[4]
handler.ServeHTTP(recorder, r) handler.ServeHTTP(recorder, req)
assert.Equal(t, test.expectedStatus, recorder.Code) assert.Equal(t, test.expectedStatus, recorder.Code)
if test.expectedStatus == http.StatusMovedPermanently || if test.expectedStatus == http.StatusMovedPermanently ||