From 4a1038fa52db57cee23a76fd2ea86247eff42f29 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Mar 2024 13:50:37 +0000 Subject: [PATCH] Revert "net/url: consider an empty base Path as equivalent to / in JoinPath" This reverts commit a46285f8c2389b92952c1484daacfccf70a17047 (CL 469935). Reason for revert: This breaks a variety of code inside Google that seem representative of possible external real-world usage. If we roll this forward again we should include a GODEBUG like urljoinpathslash=0 to go back to the old behavior. Change-Id: I6cd8e9888a0c088669dc5634418372252289e074 Reviewed-on: https://go-review.googlesource.com/c/go/+/571655 LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh Auto-Submit: Russ Cox --- src/net/url/url.go | 7 +- src/net/url/url_test.go | 180 ++++++++++++++++------------------------ 2 files changed, 73 insertions(+), 114 deletions(-) diff --git a/src/net/url/url.go b/src/net/url/url.go index 1245c67aea..f362958edd 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -1200,12 +1200,7 @@ func (u *URL) UnmarshalBinary(text []byte) error { func (u *URL) JoinPath(elem ...string) *URL { elem = append([]string{u.EscapedPath()}, elem...) var p string - if elem[0] == "" { - // RequestURI converts an empty Path to /, so do the same - // here for consistency. See #58605. - elem[0] = "/" - p = path.Join(elem...) - } else if !strings.HasPrefix(elem[0], "/") { + if !strings.HasPrefix(elem[0], "/") { // Return a relative path if u is relative, // but ensure that it contains no ../ elements. elem[0] = "/" + elem[0] diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 6672363da6..4aa20bb95f 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -2066,155 +2066,128 @@ func BenchmarkPathUnescape(b *testing.B) { func TestJoinPath(t *testing.T) { tests := []struct { - base string - elem []string - out string - wantPath string - wantRawPath string + base string + elem []string + out string }{ { - base: "https://go.googlesource.com", - elem: []string{"go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com", + elem: []string{"go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com/a/b/c", - elem: []string{"../../../go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com/a/b/c", + elem: []string{"../../../go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com/", - elem: []string{"../go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com/", + elem: []string{"../go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com", - elem: []string{"../go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com", + elem: []string{"../go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com", - elem: []string{"../go", "../../go", "../../../go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com", + elem: []string{"../go", "../../go", "../../../go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com/../go", - elem: nil, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com/../go", + elem: nil, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com/", - elem: []string{"./go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com/", + elem: []string{"./go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com//", - elem: []string{"/go"}, - out: "https://go.googlesource.com/go", - wantPath: "/go", + base: "https://go.googlesource.com//", + elem: []string{"/go"}, + out: "https://go.googlesource.com/go", }, { - base: "https://go.googlesource.com//", - elem: []string{"/go", "a", "b", "c"}, - out: "https://go.googlesource.com/go/a/b/c", - wantPath: "/go/a/b/c", + base: "https://go.googlesource.com//", + elem: []string{"/go", "a", "b", "c"}, + out: "https://go.googlesource.com/go/a/b/c", }, { base: "http://[fe80::1%en0]:8080/", elem: []string{"/go"}, }, { - base: "https://go.googlesource.com", - elem: []string{"go/"}, - out: "https://go.googlesource.com/go/", - wantPath: "/go/", + base: "https://go.googlesource.com", + elem: []string{"go/"}, + out: "https://go.googlesource.com/go/", }, { - base: "https://go.googlesource.com", - elem: []string{"go//"}, - out: "https://go.googlesource.com/go/", - wantPath: "/go/", + base: "https://go.googlesource.com", + elem: []string{"go//"}, + out: "https://go.googlesource.com/go/", }, { - base: "https://go.googlesource.com", - elem: nil, - out: "https://go.googlesource.com/", - wantPath: "/", + base: "https://go.googlesource.com", + elem: nil, + out: "https://go.googlesource.com/", }, { - base: "https://go.googlesource.com/", - elem: nil, - out: "https://go.googlesource.com/", - wantPath: "/", + base: "https://go.googlesource.com/", + elem: nil, + out: "https://go.googlesource.com/", }, { - base: "https://go.googlesource.com/a%2fb", - elem: []string{"c"}, - out: "https://go.googlesource.com/a%2fb/c", - wantPath: "/a/b/c", - wantRawPath: "/a%2fb/c", + base: "https://go.googlesource.com/a%2fb", + elem: []string{"c"}, + out: "https://go.googlesource.com/a%2fb/c", }, { - base: "https://go.googlesource.com/a%2fb", - elem: []string{"c%2fd"}, - out: "https://go.googlesource.com/a%2fb/c%2fd", - wantPath: "/a/b/c/d", - wantRawPath: "/a%2fb/c%2fd", + base: "https://go.googlesource.com/a%2fb", + elem: []string{"c%2fd"}, + out: "https://go.googlesource.com/a%2fb/c%2fd", }, { - base: "https://go.googlesource.com/a/b", - elem: []string{"/go"}, - out: "https://go.googlesource.com/a/b/go", - wantPath: "/a/b/go", + base: "https://go.googlesource.com/a/b", + elem: []string{"/go"}, + out: "https://go.googlesource.com/a/b/go", }, { - base: "/", - elem: nil, - out: "/", - wantPath: "/", + base: "/", + elem: nil, + out: "/", }, { - base: "a", - elem: nil, - out: "a", - wantPath: "a", + base: "a", + elem: nil, + out: "a", }, { - base: "a", - elem: []string{"b"}, - out: "a/b", - wantPath: "a/b", + base: "a", + elem: []string{"b"}, + out: "a/b", }, { - base: "a", - elem: []string{"../b"}, - out: "b", - wantPath: "b", + base: "a", + elem: []string{"../b"}, + out: "b", }, { - base: "a", - elem: []string{"../../b"}, - out: "b", - wantPath: "b", + base: "a", + elem: []string{"../../b"}, + out: "b", }, { - base: "", - elem: []string{"a"}, - out: "/a", - wantPath: "/a", + base: "", + elem: []string{"a"}, + out: "a", }, { - base: "", - elem: []string{"../a"}, - out: "/a", - wantPath: "/a", + base: "", + elem: []string{"../a"}, + out: "a", }, } for _, tt := range tests { @@ -2234,14 +2207,5 @@ func TestJoinPath(t *testing.T) { if out != tt.out || (err == nil) != (tt.out != "") { t.Errorf("Parse(%q).JoinPath(%q) = %q, %v, want %q, %v", tt.base, tt.elem, out, err, tt.out, wantErr) } - if u == nil { - continue - } - if got, want := u.Path, tt.wantPath; got != want { - t.Errorf("Parse(%q).JoinPath(%q).Path = %q, want %q", tt.base, tt.elem, got, want) - } - if got, want := u.RawPath, tt.wantRawPath; got != want { - t.Errorf("Parse(%q).JoinPath(%q).RawPath = %q, want %q", tt.base, tt.elem, got, want) - } } } -- 2.48.1