From f9f5db739e69cad3f1d19351f5c91e7a8831d069 Mon Sep 17 00:00:00 2001 From: ZachDreamZ Date: Sat, 4 Jul 2026 00:30:03 +0800 Subject: [PATCH] fix: parse relative URLs with multiple leading slashes for special schemes When a relative URL starts with more than two slashes (e.g. ///test) and the base has a special scheme (http, https, ws, wss, ftp), the parser should consume all leading slashes before parsing the authority, matching the URL spec's special authority slashes state. Previously, split_prefix("//") only consumed exactly two slashes, leaving the remaining slash to be parsed as part of the authority, which caused an empty host error for inputs like ///test with base http://example.org/. This fix adds a check for special schemes before the split_prefix call, routing directly to after_double_slash which handles the remaining input correctly. Fixes URL parsing for: new URL('///test', 'http://example.org/') -> http://test/ new URL('///example.org/path', 'http://example.org/') -> http://example.org/path Removed 7 entries from expected_failures.txt that now pass correctly. --- url/src/parser.rs | 3 +++ url/tests/expected_failures.txt | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/url/src/parser.rs b/url/src/parser.rs index dbdf9b906..8f2499a23 100644 --- a/url/src/parser.rs +++ b/url/src/parser.rs @@ -774,6 +774,9 @@ impl Parser<'_> { debug_assert!(base_url.byte_at(scheme_end) == b':'); self.serialization .push_str(base_url.slice(..scheme_end + 1)); + if scheme_type.is_special() { + return self.after_double_slash(remaining, scheme_type, scheme_end); + } if let Some(after_prefix) = input.split_prefix("//") { return self.after_double_slash(after_prefix, scheme_type, scheme_end); } diff --git a/url/tests/expected_failures.txt b/url/tests/expected_failures.txt index 8d4407c45..860fcd516 100644 --- a/url/tests/expected_failures.txt +++ b/url/tests/expected_failures.txt @@ -53,13 +53,6 @@ @[\\]^_`{|}~> @[\\]^_`{|}~> - against - against - against - against - against - against - against against set pathname to <\u{0}\u{1}\t\n\r\u{1f} !\"#$%&\'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u{7f}\u{80}\u{81}\u{c9}\u{e9}> set hash to <>