url.go raw

   1  package dara
   2  
   3  import (
   4  	"fmt"
   5  	"net/url"
   6  	"strings"
   7  )
   8  
   9  // PortMap maps protocols to their corresponding ports.
  10  var portMap = map[string]string{
  11  	"ftp":    "21",
  12  	"gopher": "70",
  13  	"http":   "80",
  14  	"https":  "443",
  15  	"ws":     "80",
  16  	"wss":    "443",
  17  }
  18  
  19  // URL is a wrapper around the URL type.
  20  type URL struct {
  21  	_url *url.URL
  22  }
  23  
  24  // NewURL constructs a new URL from a string.
  25  func NewURL(str string) (*URL, error) {
  26  	parsedURL, err := url.Parse(str)
  27  	if err != nil {
  28  		return nil, err
  29  	}
  30  	return &URL{_url: parsedURL}, nil
  31  }
  32  
  33  // Path returns the path and query of the URL.
  34  func (t *URL) Path() string {
  35  	if t._url.RawQuery == "" {
  36  		return t._url.Path
  37  	}
  38  	return t._url.Path + "?" + t._url.RawQuery
  39  }
  40  
  41  // Pathname returns the pathname of the URL.
  42  func (t *URL) Pathname() string {
  43  	return t._url.Path
  44  }
  45  
  46  // Protocol returns the protocol of the URL.
  47  func (t *URL) Protocol() string {
  48  	return strings.TrimSuffix(t._url.Scheme, ":")
  49  }
  50  
  51  // Hostname returns the hostname of the URL.
  52  func (t *URL) Hostname() string {
  53  	return t._url.Hostname()
  54  }
  55  
  56  // Host returns the host (host:port) of the URL.
  57  func (t *URL) Host() string {
  58  	return t._url.Host
  59  }
  60  
  61  // Port returns the port of the URL, or the default for the protocol if not specified.
  62  func (t *URL) Port() string {
  63  	if p := t._url.Port(); p != "" {
  64  		return p
  65  	}
  66  	return portMap[t.Protocol()]
  67  }
  68  
  69  // Hash returns the hash of the URL without the #.
  70  func (t *URL) Hash() string {
  71  	return strings.TrimPrefix(t._url.Fragment, "#")
  72  }
  73  
  74  // Search returns the search part of the URL without the ?.
  75  func (t *URL) Search() string {
  76  	return strings.TrimPrefix(t._url.RawQuery, "?")
  77  }
  78  
  79  // Href returns the full URL.
  80  func (t *URL) Href() string {
  81  	return t._url.String()
  82  }
  83  
  84  // Auth returns the username and password of the URL.
  85  func (t *URL) Auth() string {
  86  	password := getPassword(t._url.User)
  87  	username := t._url.User.Username()
  88  	if username == "" && password == "" {
  89  		return ""
  90  	}
  91  	return fmt.Sprintf("%s:%s", username, password)
  92  }
  93  
  94  // getPassword retrieves the password from a URL.User.
  95  func getPassword(user *url.Userinfo) string {
  96  	if password, ok := user.Password(); ok {
  97  		return password
  98  	}
  99  	return ""
 100  }
 101  
 102  // Parse constructs a new URL from a string.
 103  func ParseURL(urlStr string) (*URL, error) {
 104  	return NewURL(urlStr)
 105  }
 106  
 107  // EncodeURL encodes a URL string.
 108  func EncodeURL(urlStr string) string {
 109  	if urlStr == "" {
 110  		return ""
 111  	}
 112  	strs := strings.Split(urlStr, "/")
 113  	for i, v := range strs {
 114  		strs[i] = url.QueryEscape(v)
 115  	}
 116  	urlStr = strings.Join(strs, "/")
 117  	urlStr = strings.Replace(urlStr, "+", "%20", -1)
 118  	urlStr = strings.Replace(urlStr, "*", "%2A", -1)
 119  	urlStr = strings.Replace(urlStr, "%7E", "~", -1)
 120  	return urlStr
 121  }
 122  
 123  // PercentEncode encodes a string for use in URLs, replacing certain characters.
 124  func PercentEncode(uri string) string {
 125  	if uri == "" {
 126  		return ""
 127  	}
 128  	uri = url.QueryEscape(uri)
 129  	uri = strings.Replace(uri, "+", "%20", -1)
 130  	uri = strings.Replace(uri, "*", "%2A", -1)
 131  	uri = strings.Replace(uri, "%7E", "~", -1)
 132  	return uri
 133  }
 134  
 135  // PathEncode encodes each segment of a path.
 136  func PathEncode(path string) string {
 137  	if path == "" || path == "/" {
 138  		return path
 139  	}
 140  	strs := strings.Split(path, "/")
 141  	for i, v := range strs {
 142  		strs[i] = url.QueryEscape(v)
 143  	}
 144  	path = strings.Join(strs, "/")
 145  	path = strings.Replace(path, "+", "%20", -1)
 146  	path = strings.Replace(path, "*", "%2A", -1)
 147  	path = strings.Replace(path, "%7E", "~", -1)
 148  	return path
 149  }
 150