Skip to content

Commit 604140d

Browse files
earthboundkidgopherbot
authored andcommitted
net/url: add JoinPath, URL.JoinPath
Builds on CL 332209. Fixes #47005 Change-Id: I82708dede05d79a196ca63f5a4e7cb5ac9a041ea GitHub-Last-Rev: 51b7350 GitHub-Pull-Request: #50383 Reviewed-on: https://go-review.googlesource.com/c/go/+/374654 Reviewed-by: Russ Cox <[email protected]> Auto-Submit: Russ Cox <[email protected]> Trust: Ian Lance Taylor <[email protected]> Reviewed-by: Damien Neil <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 9faef5a commit 604140d

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

api/next.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint1
33
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
44
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
55
pkg encoding/binary, type AppendByteOrder interface, String() string
6+
pkg net/url, func JoinPath(string, ...string) (string, error)
7+
pkg net/url, method (*URL) JoinPath(...string) *URL

src/net/url/url.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ package url
1313
import (
1414
"errors"
1515
"fmt"
16+
"path"
1617
"sort"
1718
"strconv"
1819
"strings"
@@ -1176,6 +1177,17 @@ func (u *URL) UnmarshalBinary(text []byte) error {
11761177
return nil
11771178
}
11781179

1180+
// JoinPath returns a new URL with the provided path elements joined to
1181+
// any existing path and the resulting path cleaned of any ./ or ../ elements.
1182+
func (u *URL) JoinPath(elem ...string) *URL {
1183+
url := *u
1184+
if len(elem) > 0 {
1185+
elem = append([]string{u.Path}, elem...)
1186+
url.setPath(path.Join(elem...))
1187+
}
1188+
return &url
1189+
}
1190+
11791191
// validUserinfo reports whether s is a valid userinfo string per RFC 3986
11801192
// Section 3.2.1:
11811193
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
@@ -1216,3 +1228,14 @@ func stringContainsCTLByte(s string) bool {
12161228
}
12171229
return false
12181230
}
1231+
1232+
// JoinPath returns a URL string with the provided path elements joined to
1233+
// the existing path of base and the resulting path cleaned of any ./ or ../ elements.
1234+
func JoinPath(base string, elem ...string) (result string, err error) {
1235+
url, err := Parse(base)
1236+
if err != nil {
1237+
return
1238+
}
1239+
result = url.JoinPath(elem...).String()
1240+
return
1241+
}

src/net/url/url_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,3 +2062,59 @@ func BenchmarkPathUnescape(b *testing.B) {
20622062
})
20632063
}
20642064
}
2065+
2066+
func TestJoinPath(t *testing.T) {
2067+
tests := []struct {
2068+
base string
2069+
elem []string
2070+
out string
2071+
}{
2072+
{
2073+
base: "https://go.googlesource.com",
2074+
elem: []string{"go"},
2075+
out: "https://go.googlesource.com/go",
2076+
},
2077+
{
2078+
base: "https://go.googlesource.com/a/b/c",
2079+
elem: []string{"../../../go"},
2080+
out: "https://go.googlesource.com/go",
2081+
},
2082+
{
2083+
base: "https://go.googlesource.com/",
2084+
elem: []string{"./go"},
2085+
out: "https://go.googlesource.com/go",
2086+
},
2087+
{
2088+
base: "https://go.googlesource.com//",
2089+
elem: []string{"/go"},
2090+
out: "https://go.googlesource.com/go",
2091+
},
2092+
{
2093+
base: "https://go.googlesource.com//",
2094+
elem: []string{"/go", "a", "b", "c"},
2095+
out: "https://go.googlesource.com/go/a/b/c",
2096+
},
2097+
{
2098+
base: "http://[fe80::1%en0]:8080/",
2099+
elem: []string{"/go"},
2100+
},
2101+
}
2102+
for _, tt := range tests {
2103+
wantErr := "nil"
2104+
if tt.out == "" {
2105+
wantErr = "non-nil error"
2106+
}
2107+
if out, err := JoinPath(tt.base, tt.elem...); out != tt.out || (err == nil) != (tt.out != "") {
2108+
t.Errorf("JoinPath(%q, %q) = %q, %v, want %q, %v", tt.base, tt.elem, out, err, tt.out, wantErr)
2109+
}
2110+
var out string
2111+
u, err := Parse(tt.base)
2112+
if err == nil {
2113+
u = u.JoinPath(tt.elem...)
2114+
out = u.String()
2115+
}
2116+
if out != tt.out || (err == nil) != (tt.out != "") {
2117+
t.Errorf("Parse(%q).JoinPath(%q) = %q, %v, want %q, %v", tt.base, tt.elem, out, err, tt.out, wantErr)
2118+
}
2119+
}
2120+
}

0 commit comments

Comments
 (0)