关于URL编码
2017年02月10日 Theory

在写上一篇博客之前,我一直对URL编码没什么概念,看到网页链接上一串百分号加数字的字符串时会短暂的想想,因为工作中也不涉及到具体的URL编码的部分,一直也没深入过,而促使我写下来记录就是上一篇博客中markdown解析的时候出了一点小问题(markdown链接是放在小括号里面的,然后放在小括号的链接本身也包含小括号,这时markdown解析出了问题),然后查问题的时候就查到了URL编码的相关知识,这几天又查阅了资料,简要写在这里,深化一下记忆。

什么是URL编码

什么是URL?URL是Uniform Resource Locator(统一资源定位符)的缩写,就是平常说的网页地址,像www.google.com就是个URL。而URL编码就是把URL里面的字符按照一定的规则标准进行编码,产生一个国际范围内通用的字符串(ASCII码串),这里是Wiki上URL编码的解释,可以看到Wiki上的关键词是percent-encoding,因为URL编码针对每个字符的编码都使用%做前缀转义字符。

为什么需要URL编码

URL就是统一为网络上资源命名,万维网遍及世界,所以URL需要具有通用性(世界范围内通用,跨语言,跨地区时区),具有通用性的同时还要有完整性,不能因为URL中带了一些特殊字符就导致URL在传输过程中丢失了信息(比如URL中带有某个特定国家的文字),否则就失去了URL的意义,定位不到资源,因此RFC1738网络标准对URL做了硬性的规定(可以在上面的链接里看到具体RFC1738对URL的规定),除了一些ascii字符和特殊的保留字符可以直接用于URL,其他的字符都需要经过编码才可以用于表示URL,这样经过标准规则对URL进行编码,所有的特殊字符都可以用标准中规则的字符进行编码,世界范围内使用相同的规则,编码解码达成一致,通用性和完整性都得到了保证。

URL编码的规则标准

当前的URL编码标准是对所有URL标准内的保留字符不进行百分号的编码,其他的一律先转换成UTF-8的字节(每个单独的字节转换为十六进制位再在前面都加百分号)表示,再在其前面加上百分号(%)。下面用简单的例子来演示一下URL编码标准的过程。

简单例子

因何而起,便以何结束,既然是上次写的博客,就以上次博客地址为例(只取一个汉字做为例子,不按个分析演示了),地址是https://bugcode.net/2017/02/05/闭包等于匿名函数吗,这里只取这个字,来演示URL编码的过程:

  1. 汉字不是RFC1738标准中规则的保留字,所以要取字的UTF-8编码,其对应的十六进制Unicode码是95ED

  2. 再将对应的Unicode码转换为对应的UTF-8字节,转换需要UTF-8转换表,通过转换表,获取当前95ED对应的UTF-8字节序列,下面是一张UTF-8转换表:

unicode UTF-8
0000 - 007F 0#######
0080 - 07FF 11##### 10######
0800 - FFFF 1110#### 10###### 10######
10000 - 1FFFFF 11110#### 10###### 10###### 10######
  1. 上面表格中左侧是Unicode码对应范围,右侧是UTF-8对应字节序列表示,#代表对应Unicode码对应的二进制位,依次填入,后面不够的补0,具体可以查阅UTF-8编码规则相关资料,95ED对应范围在0800 - FFFF范围内,即字需要三个字节表示。HEX(95ED) = BIN(10010101 11101101),对应转换表,可得到对应的UTF-8字节序列分别是(把95ED二进制位分别按位填入1110#### 10###### 10######的#位置中)

    第一个字节需要填入4位,即: 1110 1001

    第二个字节填入6位,即: 10 010111

    第三个字节填入6位,即: 10 101101

    三个字节对应的二进制位,再转换为十六进制分别是:

    BIN(1110 1001) = HEX(E9)

    BIN(10 010111) = HEX(97)

    BIN(10101101) = HEX(AD)

    根据规则,标准之内的保留字不需要填加%前缀转义进行编码,最后上面的链接https://bugcode.net/2017/02/05/闭(只取一个汉字做例子演示,其余同理)经过URL编码之后就是https://bugcode.net/2017/02/05/%E9%97%AD

  2. 最后用JS的encodeURI函数来验证一下结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <html>
    <body>

    <script type="text/javascript">
    document.write(encodeURI("https://bugcode.net/2017/02/05/闭")+ "<br />")

    </script>
    </body>
    </html>

    代码输出: https://bugcode.net/2017/02/05/%E9%97%AD