From cf06b1f1db9bf84301aa7e760267fdab46373116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Mata?= Date: Tue, 19 Mar 2024 22:58:26 +0000 Subject: [PATCH] net/url: fix missing handling for opaque value in ResolveReference method The current implementation doesn't resolve as per spec RFC 3986 the case where the base URL has an opaque value, and the reference doesn't have either a scheme, authority or path. Currently, this specific case falls back to the "abs_path" or "rel_path" cases, where the final path results of the base_path being resolved relatively to the reference's, but since the opaque value is stored independently, it needs a case of its own. The algorith for resolving references is defined in RFC 3986 section 5.2.2: https://www.rfc-editor.org/rfc/rfc3986.html#section-5.2.2 Fixes #66084 Change-Id: I82813e2333d8f2c4433c742f10e8c941888b55ac GitHub-Last-Rev: cb96626988f4bd4546ee840ba50e2b4efa1e23f1 GitHub-Pull-Request: golang/go#66415 Reviewed-on: https://go-review.googlesource.com/c/go/+/572915 LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil Reviewed-by: Carlos Amedee --- src/net/url/url.go | 7 +++++++ src/net/url/url_test.go | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/src/net/url/url.go b/src/net/url/url.go index 7cd6913ad7..6c74f3fbf9 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -1124,6 +1124,13 @@ func (u *URL) ResolveReference(ref *URL) *URL { url.RawFragment = u.RawFragment } } + if ref.Path == "" && u.Opaque != "" { + url.Opaque = u.Opaque + url.User = nil + url.Host = "" + url.Path = "" + return &url + } // The "abs_path" or "rel_path" cases. url.Host = u.Host url.User = u.User diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 4aa20bb95f..68219c3df1 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1248,6 +1248,14 @@ var resolveReferenceTests = []struct { // Empty path and query but with ForceQuery (issue 46033). {"https://a/b/c/d;p?q#s", "?", "https://a/b/c/d;p?"}, + + // Opaque URLs (issue 66084). + {"https://foo.com/bar?a=b", "http:opaque", "http:opaque"}, + {"http:opaque?x=y#zzz", "https:/foo?a=b#frag", "https:/foo?a=b#frag"}, + {"http:opaque?x=y#zzz", "https:foo:bar", "https:foo:bar"}, + {"http:opaque?x=y#zzz", "https:bar/baz?a=b#frag", "https:bar/baz?a=b#frag"}, + {"http:opaque?x=y#zzz", "https://user@host:1234?a=b#frag", "https://user@host:1234?a=b#frag"}, + {"http:opaque?x=y#zzz", "?a=b#frag", "http:opaque?a=b#frag"}, } func TestResolveReference(t *testing.T) {