From 54ac3110510fa724d0c9ce59f84ddf5bc7f4b88f Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 11 Aug 2026 14:49:23 -0400 Subject: [PATCH] preserve ipv6 brackets and zone when stripping default ports --- transport/url.go | 5 ++--- transport/url_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/transport/url.go b/transport/url.go index 9deb080..16073de 100644 --- a/transport/url.go +++ b/transport/url.go @@ -30,13 +30,12 @@ func NormalizeURL(input string) (string, error) { // lowercase host parsed.Host = strings.ToLower(parsed.Host) - host := parsed.Hostname() port := parsed.Port() - // strip default ports + // strip default ports by suffix-trim so ipv6 brackets and zone survive if (parsed.Scheme == "wss" && port == "443") || (parsed.Scheme == "ws" && port == "80") { - parsed.Host = host + parsed.Host = strings.TrimSuffix(parsed.Host, ":"+port) } parsed.Path = strings.TrimRight(parsed.Path, "/") diff --git a/transport/url_test.go b/transport/url_test.go index 9fadc5d..b5dabc3 100644 --- a/transport/url_test.go +++ b/transport/url_test.go @@ -132,6 +132,21 @@ func TestNormalizeURL(t *testing.T) { input: "ws://relay.example.com:80", expected: "ws://relay.example.com", }, + { + name: "strip default wss port preserves ipv6 brackets", + input: "wss://[::1]:443", + expected: "wss://[::1]", + }, + { + name: "strip default ws port preserves ipv6 brackets", + input: "ws://[::1]:80", + expected: "ws://[::1]", + }, + { + name: "strip default port preserves ipv6 zone", + input: "wss://[fe80::1%25eth0]:443/", + expected: "wss://[fe80::1%25eth0]", + }, { name: "preserve non-default port", input: "wss://relay.example.com:8080", @@ -174,6 +189,24 @@ func TestNormalizeURL(t *testing.T) { } } +func TestNormalizeURLIdempotent(t *testing.T) { + inputs := []string{ + "wss://[::1]:443", + "ws://[::1]:80", + "wss://[fe80::1%25eth0]:443/", + "wss://relay.example.com:443/", + "wss://relay.example.com:8080/path", + } + + for _, input := range inputs { + once, err := NormalizeURL(input) + assert.NoError(t, err) + twice, err := NormalizeURL(once) + assert.NoError(t, err) + assert.Equal(t, once, twice, "normalizing %q twice must be stable", input) + } +} + func TestNormalizeURLError(t *testing.T) { _, err := NormalizeURL("http://relay.example.com") assert.ErrorIs(t, err, InvalidProtocol)