Fix ipv6 handling in redirect middleware

This commit is contained in:
Romain 2020-06-17 01:10:04 +02:00 committed by GitHub
parent 9f32292473
commit e5e46bf4ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 49 additions and 11 deletions

View file

@ -86,7 +86,7 @@
}, },
"dashboard_redirect@internal": { "dashboard_redirect@internal": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
}, },

View file

@ -86,7 +86,7 @@
}, },
"dashboard_redirect@internal": { "dashboard_redirect@internal": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
}, },

View file

@ -54,7 +54,7 @@
"middlewares": { "middlewares": {
"dashboard_redirect@internal": { "dashboard_redirect@internal": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
}, },

View file

@ -86,7 +86,7 @@
}, },
"dashboard_redirect@internal": { "dashboard_redirect@internal": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
}, },

View file

@ -86,7 +86,7 @@
}, },
"dashboard_redirect@internal": { "dashboard_redirect@internal": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
}, },

View file

@ -115,7 +115,7 @@ func rawURL(req *http.Request) string {
port := "" port := ""
uri := req.RequestURI uri := req.RequestURI
schemeRegex := `^(https?):\/\/([\w\._-]+)(:\d+)?(.*)$` schemeRegex := `^(https?):\/\/(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
re, _ := regexp.Compile(schemeRegex) re, _ := regexp.Compile(schemeRegex)
if re.Match([]byte(req.RequestURI)) { if re.Match([]byte(req.RequestURI)) {
match := re.FindStringSubmatch(req.RequestURI) match := re.FindStringSubmatch(req.RequestURI)

View file

@ -12,7 +12,7 @@ import (
const ( const (
typeSchemeName = "RedirectScheme" typeSchemeName = "RedirectScheme"
schemeRedirectRegex = `^(https?:\/\/)?([\w\._-]+)(:\d+)?(.*)$` schemeRedirectRegex = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
) )
// NewRedirectScheme creates a new RedirectScheme middleware. // NewRedirectScheme creates a new RedirectScheme middleware.

View file

@ -186,6 +186,44 @@ func TestRedirectSchemeHandler(t *testing.T) {
expectedURL: "https://foo", expectedURL: "https://foo",
expectedStatus: http.StatusFound, expectedStatus: http.StatusFound,
}, },
{
desc: "IPV6 HTTP to HTTPS redirection without port",
config: dynamic.RedirectScheme{
Scheme: "https",
},
url: "http://[::1]",
expectedURL: "https://[::1]",
expectedStatus: http.StatusFound,
},
{
desc: "IPV6 HTTP to HTTPS redirection with port",
config: dynamic.RedirectScheme{
Scheme: "https",
Port: "8443",
},
url: "http://[::1]",
expectedURL: "https://[::1]:8443",
expectedStatus: http.StatusFound,
},
{
desc: "IPV6 HTTP with port 80 to HTTPS redirection without port",
config: dynamic.RedirectScheme{
Scheme: "https",
},
url: "http://[::1]:80",
expectedURL: "https://[::1]",
expectedStatus: http.StatusFound,
},
{
desc: "IPV6 HTTP with port 80 to HTTPS redirection with port",
config: dynamic.RedirectScheme{
Scheme: "https",
Port: "8443",
},
url: "http://[::1]:80",
expectedURL: "https://[::1]:8443",
expectedStatus: http.StatusFound,
},
} }
for _, test := range testCases { for _, test := range testCases {
@ -235,7 +273,7 @@ func TestRedirectSchemeHandler(t *testing.T) {
require.Errorf(t, err, "Location %v", location) require.Errorf(t, err, "Location %v", location)
} }
schemeRegex := `^(https?):\/\/([\w\._-]+)(:\d+)?(.*)$` schemeRegex := `^(https?):\/\/(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
re, _ := regexp.Compile(schemeRegex) re, _ := regexp.Compile(schemeRegex)
if re.Match([]byte(test.url)) { if re.Match([]byte(test.url)) {

View file

@ -25,7 +25,7 @@
"middlewares": { "middlewares": {
"dashboard_redirect": { "dashboard_redirect": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
} }

View file

@ -57,7 +57,7 @@
"middlewares": { "middlewares": {
"dashboard_redirect": { "dashboard_redirect": {
"redirectRegex": { "redirectRegex": {
"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$", "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
"replacement": "${1}/dashboard/", "replacement": "${1}/dashboard/",
"permanent": true "permanent": true
} }

View file

@ -197,7 +197,7 @@ func (i *Provider) apiConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Middlewares["dashboard_redirect"] = &dynamic.Middleware{ cfg.HTTP.Middlewares["dashboard_redirect"] = &dynamic.Middleware{
RedirectRegex: &dynamic.RedirectRegex{ RedirectRegex: &dynamic.RedirectRegex{
Regex: `^(http:\/\/[^:\/]+(:\d+)?)\/$`, Regex: `^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$`,
Replacement: "${1}/dashboard/", Replacement: "${1}/dashboard/",
Permanent: true, Permanent: true,
}, },