From 53cb949d2b0d59c99da5ad8c2f1ee95f87ee7318 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 11 Aug 2026 11:44:36 -0400 Subject: [PATCH] refine url normalization Before, the entire url was being lowercased, which mutilates various case-sensitive parts. Now, only the host gets lowercased, and the test verify that the userinfo, path, and query parts preserve their original case. --- transport/url.go | 7 ++++++- transport/url_test.go | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/transport/url.go b/transport/url.go index 3e367ec..9deb080 100644 --- a/transport/url.go +++ b/transport/url.go @@ -22,13 +22,18 @@ func ParseURL(urlStr string) (*url.URL, error) { } func NormalizeURL(input string) (string, error) { - parsed, err := ParseURL(strings.ToLower(input)) + parsed, err := ParseURL(input) if err != nil { return "", err } + // lowercase host + parsed.Host = strings.ToLower(parsed.Host) + host := parsed.Hostname() port := parsed.Port() + + // strip default ports if (parsed.Scheme == "wss" && port == "443") || (parsed.Scheme == "ws" && port == "80") { parsed.Host = host diff --git a/transport/url_test.go b/transport/url_test.go index 39364a4..9fadc5d 100644 --- a/transport/url_test.go +++ b/transport/url_test.go @@ -142,6 +142,22 @@ func TestNormalizeURL(t *testing.T) { input: "wss://relay.example.com/nostr", expected: "wss://relay.example.com/nostr", }, + { + name: "lowercase scheme+host, preserve path case", + input: "Wss://Relay.Example.Com/Nostr", + expected: "wss://relay.example.com/Nostr", + }, + { + name: "preserve user info", + input: "wss://user:P@ssWord@relay.example.com", + // String() cannot output a raw `@` so `%40` is expected + expected: "wss://user:P%40ssWord@relay.example.com", + }, + { + name: "preserve query", + input: "Wss://relay.example.com?field=Value", + expected: "wss://relay.example.com?field=Value", + }, { name: "no change needed", input: "wss://relay.example.com",