github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/rest/urlbuilder.go (about) 1 package rest 2 3 import ( 4 "fmt" 5 "log" 6 "net/url" 7 "path" 8 ) 9 10 type URL struct { 11 Base string 12 SubPaths []string 13 QueryValues url.Values 14 } 15 16 func NewURL(base string) URL { 17 return URL{Base: base, QueryValues: make(url.Values)} 18 } 19 20 func (u URL) QueryMap(m map[string]string) URL { 21 for k, v := range m { 22 u.QueryValues.Add(k, v) 23 } 24 25 return u 26 } 27 28 func (u URL) Query(k, v string, kvs ...string) URL { 29 u.QueryValues.Add(k, v) 30 31 for i := 0; i+1 < len(kvs); i += 2 { 32 u.QueryValues.Add(kvs[i], kvs[i+1]) 33 } 34 35 return u 36 } 37 38 func (u URL) Paths(paths ...string) URL { 39 u.SubPaths = append(u.SubPaths, paths...) 40 return u 41 } 42 43 func (u URL) String() string { 44 s, err := u.Build() 45 if err != nil { 46 log.Fatalf("build URL from base %s failed: %v", u.Base, err) 47 } 48 49 return s 50 } 51 52 func (u URL) Build() (string, error) { 53 base := FixURI(u.Base) 54 if !base.OK() { 55 return "", base.Err 56 } 57 58 b := base.Data 59 60 p2 := append([]string{b.Path}, u.SubPaths...) 61 b.Path = path.Join(p2...) 62 63 q := b.Query() 64 for k, v := range u.QueryValues { 65 for _, vi := range v { 66 q.Add(k, vi) 67 } 68 } 69 b.RawQuery = q.Encode() 70 return b.String(), nil 71 } 72 73 func JoinURL(base *url.URL, target string) (string, error) { 74 u, err := url.Parse(target) 75 if err != nil { 76 return "", fmt.Errorf("parse url %s: %w", target, err) 77 } 78 79 b := *base 80 b.Path = path.Join(b.Path, u.Path) 81 b.RawQuery = u.RawQuery 82 83 return b.String(), nil 84 }