漫谈Url Encode
什么是Url Encode以及Why
我们日常都要接触各种各样的url,比如我们在京东搜索 氢氟酸,浏览器会生成如下url,请求给京东web服务器:
1 | https://search.jd.com/Search?keyword=氢氟酸&enc=utf-8 |
此url由如下部分组成:
- search.jd.com是HTTP请求的地址,会被DNS服务器解析成为ip地址
- /Search是请求的path,不同的请求path对应不同的web后端处理逻辑,这里我们调用的/Search表明我们请求的是搜索服务
- ?keyword=氢氟酸&enc=utf-8 ? 后面是query parameter,**&** 是多个parameter的分隔符,指明搜索关键字和编码方式
目前为止,url很直观,但当我们搜索 氢氟 酸(多一个空格)和C&K时,url变成如下的样子:
1 | https://search.jd.com/Search?keyword=氢氟%20酸&enc=utf-8 |
看起来是空格和 & 被转为 %xx 发送出去了,为什么需要这种转换?
因为url存在特殊字符,比如&,它起到分割不同param的作用,但是我们想搜索的keyword带有&的话,比如这样:keyword=C&K,url在解析的时候就会错误的认为keyword=C,因此需要有种方法把对于url有特殊含义的字符(如&)转换,这就是Url Encode的作用
如何Url Encode
那么url中到底哪些字符需要被转义(URL Encode)呢?如何进行?
URLs can only be sent over the Internet using the ASCII character-set.
也就是说最终传输的url仅仅会包含ASCII码指定的字符
url中包含的字符分为:
- reserved character:
1
! * ' ( ) ; : @ & = + $ , / ? # [ ]
- unreserved character
1
0-9a-zA-A-_.~
- Other characters
如空格 “ 等
RFC 1738 做了规定
“…Only alphanumerics [0-9a-zA-Z], the special characters “$-.+!*’(),” [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL.”
“只有字母和数字[0-9a-zA-Z]、一些特殊符号”$-.+!*’(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”
当我们需要在url中传送url保留字符时,就需要进行url encode了:
Reserved characters after url encoding
! | # | $ | & | ‘ | ( | ) | * | + | , | / | : | ; | = | ? | @ | [ | ] |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
%21 | %23 | %24 | %26 | %27 | %28 | %29 | %2A | %2B | %2C | %2F | %3A | %3B | %3D | %3F | %40 | %5B | %5D |
可见,编码的方式是用 % 加ASCII hex码完成的,因此url encode又成为percent-encoding,
url-encoding也能对unreserved字符进行编码,如a被编码为%61但是不建议这样做,没必要而且可能会有潜在的兼容性问题。除了reserverd字符和unreserved字符,其他字符必须进行url编码:
newline | space | “ | % | < | > | \ | ^ | ` | { | } | | |
---|---|---|---|---|---|---|---|---|---|---|---|
%0A | %20 | %22 | %25 | %3C | %3E | %5C | %5E | %60 | %7B | %7D | %7C |
url装载非Ascii码信息
比如在京东搜索台灯,url如何装载汉字信息呢?答案仍是url encoding,汉字被编码为一系列的含 % 的ASCII串
有些url为什么会包含汉字呢?
其实这只是浏览器显示效果,打开chrome控制台,可以看到汉字是被url encode过的
golang中实现Url Encode
利用net/url包可以很方便的进行url编码操作
把string进行url encode,这样就能将其安全的作为url使用
1 | import "http/url" |
如果想生成带parameter的url呢? stackoverflow上一个回答提供的代码很方便:
1 | var Url *url.URL |
输出如下
1 | http://www.example.com/some/path/or/other_with_funny_characters%3F_or_not/?hello=42&hello=54&vegetable=potato%23fresh |
参考文献
关于URL编码
Percent-encoding
HTML URL Encoding Reference
Encode / decode URLs