Golang urlencode与urldecode编码解码
时间:2021-11-8 作者:smarteng 分类: Go语言
为什么需要编码和解码
1.是因为当字符串数据以url的形式传递给web服务器时,字符串中是不允许出现空格和特殊字符的;
2.因为 url 对字符有限制,比如把一个邮箱放入 url,就需要使用 urlencode 函数,因为 url 中不能包含 @ 字符;
3.url转义其实也只是为了符合url的规范而已。因为在标准的url规范中中文和很多的字符是不允许出现在url中的。
4.一般的开发平台都是想要加密的,加密算法的时候,一般需要把参数拼接,之后进行 URL的encode,之后加密
哪些字符是需要转化的呢?
1. ASCII 的控制字符
这些字符都是不可打印的,自然需要进行转化。
2. 一些非ASCII字符
这些字符自然是非法的字符范围。转化也是理所当然的了。
3. 一些保留字符
很明显最常见的就是“&”了,这个如果出现在url中了,那你认为是url中的一个字符呢,还是特殊的参数分割用的呢?
4. 就是一些不安全的字符了。
例如:空格。为了防止引起歧义,需要被转化为“+”。
明白了这些,也就知道了为什么需要转化了,而转化的规则也是很简单的。
按照每个字符对应的字符编码,不是符合我们范围的,统统的转化为%的形式也就是了。自然也是16进制的形式。
5.和字符编码无关
通过urlencode的转化规则和目的,我们也很容易的看出,urleocode是基于字符编码的。同样的一个汉字,不同的编码类型,肯定对应不同的urleocode的串。gbk编码的有gbk的encode结果。
apache等服务器,接受到字符串后,可以进行decode,但是还是无法解决编码的问题。编码问题,还是需要靠约定或者字符编码的判断解决。
因此,urleocode只是为了url中一些非ascii字符,可以正确无误的被传输,至于使用哪种编码,就不是encode所关心和解决的问题了。
编码问题,不是urlencode所要解决的。
golang之UrlEncode编码/UrlDecode解码
package main
import(
"fmt"
"net/url"
)
func main() {
var urlStr string = "傻了吧:%:%@163& .html.html"
escapeUrl := url.QueryEscape(urlStr)
fmt.Println("编码:",escapeUrl)
enEscapeUrl, _ := url.QueryUnescape(escapeUrl)
fmt.Println("解码:",enEscapeUrl)
}
输出
编码: %E5%82%BB%E4%BA%86%E5%90%A7%3A%25%3A%25%40163%26+.html.html
解码: 傻了吧:%:%@163& .html.html
详细实例
一、urlencode
golang下可以使用net/url模块实现urlencode和urldecode操作。具体实现的函数为url.QueryEscape和url.QueryUnescape,代码如下:
package main
import(
"fmt"
"net/url"
)
func main() {
var urlStr string = "运维之路"
escapeUrl := url.QueryEscape(urlStr)
fmt.Println("编码:",escapeUrl)
enEscapeUrl, _ := url.QueryUnescape(escapeUrl)
fmt.Println("解码:",enEscapeUrl)
}
如果涉及到多个参数转码的,这在get和post请求中都有,比如id=100&site=361way.com这样的。可以在通过url.Values进行增加后转码,发下:
package main
import (
"fmt"
"net/url"
)
func main() {
params := url.Values{}
params.Add("name", "@Rajeev")
params.Add("phone", "+919999999999")
fmt.Println(params.Encode())
}
#输出:
name=%40Rajeev&phone=%2B919999999999
同样的,我们通过url的其他函数处理操作过后,一个典型的get请求的URL如下:
package main
import (
"fmt"
"net/url"
)
func main() {
// Let's start with a base url
baseUrl, err := url.Parse("http://www.mywebsite.com")
if err != nil {
fmt.Println("Malformed URL: ", err.Error())
return
}
// Add a Path Segment (Path segment is automatically escaped)
baseUrl.Path += "path with?reserved characters"
// Prepare Query Parameters
params := url.Values{}
params.Add("q", "Hello World")
params.Add("u", "@rajeev")
// Add Query Parameters to the URL
baseUrl.RawQuery = params.Encode() // Escape Query Parameters
fmt.Printf("Encoded URL is %q\n", baseUrl.String())
}
#输出结果
Encoded URL is "http://www.mywebsite.com/path%20with%3Freserved%20characters?q=Hello+World&u=%40rajeev"
二、urldecode
简单的url解码,直接使用Unescape就可以了,如下:
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
encodedValue := "Hell%C3%B6+W%C3%B6rld%40Golang"
decodedValue, err := url.QueryUnescape(encodedValue)
if err != nil {
log.Fatal(err)
return
}
fmt.Println(decodedValue)
}
带form 参数,就像上面提到的"param1=value1¶m2=value2"这种格式的可以使用url.ParseQuery()参数解析成map[string][]string格式,如下:
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
queryStr := "name=Rajeev%20Singh&phone=%2B9199999999&phone=%2B628888888888"
params, err := url.ParseQuery(queryStr)
if err != nil {
log.Fatal(err)
return
}
fmt.Println("Query Params: ")
for key, value := range params {
fmt.Printf(" %v = %v\n", key, value)
}
}
#其输出为:
Query Params:
name = [Rajeev Singh]
phone = [+9199999999 +628888888888]
一个get请求类,后面带参数的URL,可以通过如下方式解析并解码
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
u, err := url.Parse("https://www.website.com/person?name=Rajeev%20Singh&phone=%2B919999999999&phone=%2B628888888888")
if err != nil {
log.Fatal(err)
return
}
fmt.Println("Scheme: ", u.Scheme)
fmt.Println("Host: ", u.Host)
queries := u.Query()
fmt.Println("Query Strings: ")
for key, value := range queries {
fmt.Printf(" %v = %v\n", key, value)
}
fmt.Println("Path: ", u.Path)
}
# 输出如下:
Scheme: https
Host: www.website.com
Query Strings:
phone = [+919999999999 +628888888888]
name = [Rajeev Singh]
Path: /person