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
import (
"errors"
"fmt"
+ "path"
"sort"
"strconv"
"strings"
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 / ":" )
}
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
+}
})
}
}
+
+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)
+ }
+ }
+}