github.com/webx-top/com@v1.2.12/url.go (about) 1 // Copyright 2013 com authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package com 16 17 import ( 18 "encoding/base64" 19 "math" 20 "net/url" 21 "path" 22 "regexp" 23 "strings" 24 ) 25 26 // URLEncode url encode string, is + not %20 27 func URLEncode(str string) string { 28 return url.QueryEscape(str) 29 } 30 31 // URLDecode url decode string 32 func URLDecode(str string) (string, error) { 33 return url.QueryUnescape(str) 34 } 35 36 // RawURLEncode rawurlencode() 37 func RawURLEncode(str string) string { 38 return strings.Replace(url.QueryEscape(str), "+", "%20", -1) 39 } 40 41 // RawURLDecode rawurldecode() 42 func RawURLDecode(str string) (string, error) { 43 return url.QueryUnescape(str) 44 } 45 46 // Base64Encode base64 encode 47 func Base64Encode(str string) string { 48 return base64.StdEncoding.EncodeToString([]byte(str)) 49 } 50 51 // Base64Decode base64 decode 52 func Base64Decode(str string) (string, error) { 53 s, e := base64.StdEncoding.DecodeString(str) 54 return string(s), e 55 } 56 57 var urlSafeBase64EncodeReplacer = strings.NewReplacer(`/`, `_`, `+`, `-`) 58 var urlSafeBase64DecodeReplacer = strings.NewReplacer(`_`, `/`, `-`, `+`) 59 60 // URLSafeBase64 base64字符串编码为URL友好的字符串 61 func URLSafeBase64(str string, encode bool) string { 62 if encode { // 编码后处理 63 str = strings.TrimRight(str, `=`) 64 str = urlSafeBase64EncodeReplacer.Replace(str) 65 return str 66 } 67 // 解码前处理 68 str = urlSafeBase64DecodeReplacer.Replace(str) 69 var missing = (4 - len(str)%4) % 4 70 if missing > 0 { 71 str += strings.Repeat(`=`, missing) 72 } 73 return str 74 } 75 76 // SafeBase64Encode base64 encode 77 func SafeBase64Encode(str string) string { 78 str = base64.URLEncoding.EncodeToString([]byte(str)) 79 str = strings.TrimRight(str, `=`) 80 return str 81 } 82 83 // SafeBase64Decode base64 decode 84 func SafeBase64Decode(str string) (string, error) { 85 var missing = (4 - len(str)%4) % 4 86 if missing > 0 { 87 str += strings.Repeat(`=`, missing) 88 } 89 b, err := base64.URLEncoding.DecodeString(str) 90 if err != nil { 91 return ``, err 92 } 93 return string(b), nil 94 } 95 96 // TotalPages 总页数 97 func TotalPages(totalRows uint, limit uint) uint { 98 return uint(math.Ceil(float64(totalRows) / float64(limit))) 99 } 100 101 // Offset 根据页码计算偏移值 102 func Offset(page uint, limit uint) uint { 103 if page == 0 { 104 page = 1 105 } 106 return (page - 1) * limit 107 } 108 109 // AbsURL 获取页面内相对网址的绝对路径 110 func AbsURL(pageURL string, relURL string) string { 111 if strings.Contains(relURL, `://`) { 112 return relURL 113 } 114 urlInfo, err := url.Parse(pageURL) 115 if err != nil { 116 return `` 117 } 118 return AbsURLx(urlInfo, relURL, true) 119 } 120 121 func AbsURLx(pageURLInfo *url.URL, relURL string, onlyRelative ...bool) string { 122 if (len(onlyRelative) == 0 || !onlyRelative[0]) && strings.Contains(relURL, `://`) { 123 return relURL 124 } 125 siteURL := pageURLInfo.Scheme + `://` + pageURLInfo.Host 126 if strings.HasPrefix(relURL, `/`) { 127 return siteURL + relURL 128 } 129 for strings.HasPrefix(relURL, `./`) { 130 relURL = strings.TrimPrefix(relURL, `./`) 131 } 132 urlPath := path.Dir(pageURLInfo.Path) 133 for strings.HasPrefix(relURL, `../`) { 134 urlPath = path.Dir(urlPath) 135 relURL = strings.TrimPrefix(relURL, `../`) 136 } 137 return siteURL + path.Join(urlPath, relURL) 138 } 139 140 func URLSeparator(pageURL string) string { 141 sep := `?` 142 if strings.Contains(pageURL, sep) { 143 sep = `&` 144 } 145 return sep 146 } 147 148 var localIPRegexp = regexp.MustCompile(`^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$`) 149 150 // IsLocalhost 是否是本地主机 151 func IsLocalhost(host string) bool { 152 switch host { 153 case `localhost`: 154 return true 155 case `[::1]`: 156 return true 157 default: 158 return localIPRegexp.MatchString(host) 159 } 160 } 161 162 // SplitHost localhost:8080 => localhost 163 func SplitHost(hostport string) string { 164 host, _ := SplitHostPort(hostport) 165 return host 166 } 167 168 func SplitHostPort(hostport string) (host string, port string) { 169 if strings.HasSuffix(hostport, `]`) { 170 host = hostport 171 return 172 } 173 sep := `]:` 174 pos := strings.LastIndex(hostport, sep) 175 if pos > -1 { 176 host = hostport[0 : pos+1] 177 if len(hostport) > pos+2 { 178 port = hostport[pos+2:] 179 } 180 return 181 } 182 sep = `:` 183 pos = strings.LastIndex(hostport, sep) 184 if pos > -1 { 185 host = hostport[0:pos] 186 if len(hostport) > pos+1 { 187 port = hostport[pos+1:] 188 } 189 return 190 } 191 host = hostport 192 return 193 } 194 195 func WithURLParams(urlStr string, key string, value string, args ...string) string { 196 if strings.Contains(urlStr, `?`) { 197 urlStr += `&` 198 } else { 199 urlStr += `?` 200 } 201 urlStr += key + `=` + url.QueryEscape(value) 202 var k string 203 for i, j := 0, len(args); i < j; i++ { 204 if i%2 == 0 { 205 k = args[i] 206 continue 207 } 208 urlStr += `&` + k + `=` + url.QueryEscape(args[i]) 209 k = `` 210 } 211 if len(k) > 0 { 212 urlStr += `&` + k + `=` 213 } 214 return urlStr 215 } 216 217 func FullURL(domianURL string, myURL string) string { 218 if IsFullURL(myURL) { 219 return myURL 220 } 221 if !strings.HasPrefix(myURL, `/`) && !strings.HasSuffix(domianURL, `/`) { 222 myURL = `/` + myURL 223 } 224 myURL = domianURL + myURL 225 return myURL 226 } 227 228 func IsFullURL(purl string) bool { 229 if len(purl) == 0 { 230 return false 231 } 232 if purl[0] == '/' { 233 return false 234 } 235 // find "://" 236 firstPos := strings.Index(purl, `/`) 237 if firstPos < 0 || firstPos == len(purl)-1 { 238 return false 239 } 240 if firstPos > 1 && purl[firstPos-1] == ':' && purl[firstPos+1] == '/' { 241 return true 242 } 243 return false 244 }