diff --git a/app/proxy/ssl.go b/app/proxy/ssl.go index 671725e4..f3be1962 100644 --- a/app/proxy/ssl.go +++ b/app/proxy/ssl.go @@ -15,6 +15,8 @@ import ( R "github.com/go-pkgz/rest" "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "github.com/umputun/reproxy/app/discovery" ) // sslMode defines ssl mode for rest server @@ -76,7 +78,10 @@ func (h *Http) httpChallengeOnlyRouter(m AutocertManager) http.Handler { func (h *Http) redirectHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - server, _, _ := strings.Cut(r.Host, ":") + server := discovery.HostName(r.Host) + if strings.Contains(server, ":") { + server = "[" + server + "]" // an ipv6 literal needs its brackets back in a url + } // use standard HTTPS port by default httpsPort := 443 // no need to specify the port if it's the standard HTTPS port diff --git a/app/proxy/ssl_test.go b/app/proxy/ssl_test.go index 114d9c92..461c931e 100644 --- a/app/proxy/ssl_test.go +++ b/app/proxy/ssl_test.go @@ -48,6 +48,28 @@ func TestSSL_Redirect(t *testing.T) { assert.Equal(t, "https://localhost/blah?param=1", resp.Header.Get("Location")) } +func TestSSL_RedirectHost(t *testing.T) { + tbl := []struct{ host, location string }{ + {host: "example.com", location: "https://example.com/blah?param=1"}, + {host: "example.com:80", location: "https://example.com/blah?param=1"}, + {host: "127.0.0.1:80", location: "https://127.0.0.1/blah?param=1"}, + {host: "[::1]:80", location: "https://[::1]/blah?param=1"}, + {host: "[::1]", location: "https://[::1]/blah?param=1"}, + } + + p := Http{} + for _, tt := range tbl { + t.Run(tt.host, func(t *testing.T) { + req := httptest.NewRequest("GET", "/blah?param=1", http.NoBody) + req.Host = tt.host + wr := httptest.NewRecorder() + p.redirectHandler().ServeHTTP(wr, req) + assert.Equal(t, http.StatusTemporaryRedirect, wr.Code) + assert.Equal(t, tt.location, wr.Header().Get("Location")) + }) + } +} + func TestSSL_httpChallengeOnlyRouter(t *testing.T) { log.Setup(log.Debug, log.LevelBraces)