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  }