为什么要进行URL编码

13 min read

URI

URI是统一资源标识的意思,通常我们所说的URL只是URI的一种。典型URL的格式如下所示。下面提到的URL编码,实际上应该指的是URI编码。***

foo://example.com:8042/over/there?name=ferret#nose

scheme authority path query fragment

避免歧义

  • HTTP协议中参数组件的传输是“key=value”键值对的形式,如果要传输多个参数就需要用“&”符号对键值对进行分隔。例如?name1=value1&name2=$value2,这样在服务器收到这种字符串的时候,会用“&”分隔出每一个参数,然后再用“=”来分隔出参数值。

  • 如果我的参数值中就包含=或者&这样的特殊子字符的时候,该怎么办。比如说“name1=value1”,其中value1的值是“va&lu=e1”,那么在传输过程中就会变成“name1=va&lu=e1”。用户传输的本意是只有一个键值对,但是服务器端会解析成两个键值对,这样就自然的产生了歧义。

解决方法

JavaScript中提供了3对函数用来对Url编码以得到合法的Url,它们分别是

escape / unescape,

encodeURI / decodeURI

encodeURIComponent / decodeURIComponent

由于解码和编码的过程是可逆的,因此这里只解释编码的过程。

这三个编码的函数——escape,encodeURI,encodeURIComponent——都是用于将不安全不合法的Url字符转换为合法的Url字符表示,它们有以下几个不同点。

下面列出了这三个函数的安全字符(即函数不会对这些字符进行编码)

  • escape(69个):*/@±._0-9a-zA-Z

  • encodeURI(82个):!#$&’()*+,/:;=?@-._~0-9a-zA-Z

  • encodeURIComponent(71个):!’()*-._~0-9a-zA-Z

encodeURIComponent("http://baidu.com")
"http%3A%2F%2Fbaidu.com"
decodeURIComponent("http%3A%2F%2Fbaidu.com")
"http://baidu.com"
encodeURIComponent("我是中文")
"%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87"
decodeURIComponent("%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87")
"我是中文"
encodeURIComponent("@")
"%40"
encodeURI("@")
"@"