From f36ec16c30f89587e05259db7fcc99c21dbb5b63 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Fri, 27 Feb 2026 15:43:05 -0400 Subject: [PATCH] Fix a URI resolution port bug Signed-off-by: Juan Cruz Viotti --- src/core/uri/resolution.cc | 10 +++++++++- test/uri/uri_relative_to_test.cc | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/core/uri/resolution.cc b/src/core/uri/resolution.cc index cd5b9261a..919023111 100644 --- a/src/core/uri/resolution.cc +++ b/src/core/uri/resolution.cc @@ -202,11 +202,19 @@ auto URI::relative_to(const URI &base) -> URI & { return *this; } - // Hosts must match (but both can be null for URNs) + // The full authority must match (but components can be null for URNs) + if (this->userinfo_ != base.userinfo_) { + return *this; + } + if (this->host_ != base.host_) { return *this; } + if (this->port_ != base.port_) { + return *this; + } + // Special case: both URIs are exactly the same if (this->path_ == base.path_ && this->query_ == base.query_ && this->fragment_ == base.fragment_) { diff --git a/test/uri/uri_relative_to_test.cc b/test/uri/uri_relative_to_test.cc index cd27a3cb4..ee370136a 100644 --- a/test/uri/uri_relative_to_test.cc +++ b/test/uri/uri_relative_to_test.cc @@ -58,6 +58,27 @@ TEST(URI_relative_to, absolute_absolute_base_false_4) { EXPECT_EQ(uri.recompose(), "https://bar.com"); } +TEST(URI_relative_to, absolute_absolute_base_false_different_ports) { + const sourcemeta::core::URI base{"http://localhost:8000"}; + sourcemeta::core::URI uri{"http://localhost:9000/schemas/test.json"}; + uri.relative_to(base); + EXPECT_EQ(uri.recompose(), "http://localhost:9000/schemas/test.json"); +} + +TEST(URI_relative_to, absolute_absolute_base_false_different_userinfo) { + const sourcemeta::core::URI base{"https://alice@example.com/foo"}; + sourcemeta::core::URI uri{"https://bob@example.com/foo/bar"}; + uri.relative_to(base); + EXPECT_EQ(uri.recompose(), "https://bob@example.com/foo/bar"); +} + +TEST(URI_relative_to, absolute_absolute_base_false_userinfo_vs_none) { + const sourcemeta::core::URI base{"https://example.com/foo"}; + sourcemeta::core::URI uri{"https://alice@example.com/foo/bar"}; + uri.relative_to(base); + EXPECT_EQ(uri.recompose(), "https://alice@example.com/foo/bar"); +} + TEST(URI_relative_to, absolute_relative_1) { const sourcemeta::core::URI base{"https://www.example.com"}; sourcemeta::core::URI uri{"foo"};