From 121679b44e160aab44e9fa8a98d99002a26c8010 Mon Sep 17 00:00:00 2001 From: wjqserver <114663932+WJQSERVER@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:31:10 +0800 Subject: [PATCH] fix: preserve IPv6 brackets in redirects Re-wrap bare IPv6 hosts after stripping ports so HTTPS redirect URLs stay valid. Add a regression test covering bracketed IPv6 hosts in redirect responses. --- serve.go | 3 +++ serve_test.go | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/serve.go b/serve.go index 386eaf5..0fc83f9 100644 --- a/serve.go +++ b/serve.go @@ -332,6 +332,9 @@ func buildRedirectServer(engine *Engine, cfg runConfig) (*http.Server, error) { if parsedHost, _, err := net.SplitHostPort(host); err == nil { host = parsedHost + if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { + host = "[" + host + "]" + } } targetURL := "https://" + host diff --git a/serve_test.go b/serve_test.go index 8de14c3..c717653 100644 --- a/serve_test.go +++ b/serve_test.go @@ -399,6 +399,26 @@ func TestBuildRedirectServerUsesConfiguredRedirectHostWhenHeaderModeDisabled(t * } } +func TestBuildRedirectServerPreservesIPv6BracketsInRedirectURL(t *testing.T) { + engine := New() + server, err := buildRedirectServer(engine, runConfig{addr: ":443", httpRedirectAddr: ":80"}) + if err != nil { + t.Fatalf("build redirect server: %v", err) + } + + req := httptest.NewRequest(http.MethodGet, "http://[::1]/plain/path?q=1", nil) + req.Host = "[::1]:80" + rr := httptest.NewRecorder() + server.Handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusMovedPermanently { + t.Fatalf("expected redirect status %d, got %d", http.StatusMovedPermanently, rr.Code) + } + if location := rr.Header().Get("Location"); location != "https://[::1]/plain/path?q=1" { + t.Fatalf("unexpected IPv6 redirect location: %q", location) + } +} + func TestGracefulServeShutsDownSiblingServersOnStartupFailure(t *testing.T) { occupied, err := net.Listen("tcp", "127.0.0.1:0") if err != nil {