]> Cypherpunks repositories - gostls13.git/commitdiff
net/url: add JoinPath, URL.JoinPath
authorCarl Johnson <me@carlmjohnson.net>
Fri, 4 Mar 2022 14:49:52 +0000 (14:49 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 10 Mar 2022 01:34:17 +0000 (01:34 +0000)
Builds on CL 332209.

Fixes #47005

Change-Id: I82708dede05d79a196ca63f5a4e7cb5ac9a041ea
GitHub-Last-Rev: 51b735066eef74f5e67c3e8899c58f44c0383c61
GitHub-Pull-Request: golang/go#50383
Reviewed-on: https://go-review.googlesource.com/c/go/+/374654
Reviewed-by: Russ Cox <rsc@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

api/next.txt
src/net/url/url.go
src/net/url/url_test.go

index 23fd98a9bac0c715f27392d2b4535dbe3db3da68..148cbffbfeb6feb3b74198f769483bb5e01ba12f 100644 (file)
@@ -3,3 +3,5 @@ pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint1
 pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
 pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
 pkg encoding/binary, type AppendByteOrder interface, String() string
+pkg net/url, func JoinPath(string, ...string) (string, error)
+pkg net/url, method (*URL) JoinPath(...string) *URL
index f31aa08b5929db2880fd22ec735e2db3692cc222..1571bf728ba9145fc62a256fd812719799e49027 100644 (file)
@@ -13,6 +13,7 @@ package url
 import (
        "errors"
        "fmt"
+       "path"
        "sort"
        "strconv"
        "strings"
@@ -1176,6 +1177,17 @@ func (u *URL) UnmarshalBinary(text []byte) error {
        return nil
 }
 
+// JoinPath returns a new URL with the provided path elements joined to
+// any existing path and the resulting path cleaned of any ./ or ../ elements.
+func (u *URL) JoinPath(elem ...string) *URL {
+       url := *u
+       if len(elem) > 0 {
+               elem = append([]string{u.Path}, elem...)
+               url.setPath(path.Join(elem...))
+       }
+       return &url
+}
+
 // validUserinfo reports whether s is a valid userinfo string per RFC 3986
 // Section 3.2.1:
 //     userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
@@ -1216,3 +1228,14 @@ func stringContainsCTLByte(s string) bool {
        }
        return false
 }
+
+// JoinPath returns a URL string with the provided path elements joined to
+// the existing path of base and the resulting path cleaned of any ./ or ../ elements.
+func JoinPath(base string, elem ...string) (result string, err error) {
+       url, err := Parse(base)
+       if err != nil {
+               return
+       }
+       result = url.JoinPath(elem...).String()
+       return
+}
index 664757b832af04ff05b603691089df3d5def5c65..84dba45c3c1366872f2e2d152d84ce53ea169d73 100644 (file)
@@ -2062,3 +2062,59 @@ func BenchmarkPathUnescape(b *testing.B) {
                })
        }
 }
+
+func TestJoinPath(t *testing.T) {
+       tests := []struct {
+               base string
+               elem []string
+               out  string
+       }{
+               {
+                       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",
+               },
+               {
+                       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",
+               },
+               {
+                       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"},
+               },
+       }
+       for _, tt := range tests {
+               wantErr := "nil"
+               if tt.out == "" {
+                       wantErr = "non-nil error"
+               }
+               if out, err := JoinPath(tt.base, tt.elem...); out != tt.out || (err == nil) != (tt.out != "") {
+                       t.Errorf("JoinPath(%q, %q) = %q, %v, want %q, %v", tt.base, tt.elem, out, err, tt.out, wantErr)
+               }
+               var out string
+               u, err := Parse(tt.base)
+               if err == nil {
+                       u = u.JoinPath(tt.elem...)
+                       out = u.String()
+               }
+               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)
+               }
+       }
+}