What is URL Encoding
URL Encoding 也被成为 percent encoding,URL是由有限的字符(来自US-ASCII character set)组成的,这些字符包含数字(0-9)、字幕(a-z, A-Z)、特殊字符-
_
.
~
。
这也就意味着,URL中不能包含:
- ASCII控制字符(退格键,垂直制表符,水平制表符,换行符等)
- unsafe characters: space、\、<>、{、}
- 不在ASCII中的字符
还有一些绝对不能出现在query中的字符:
- 常见的一些对于URL有特殊意义的字符,被称作
保留字符
。比如: / # ? :
那么,当你的URI中必须要包含一些不被允许的字符该怎么办呢?
这时候就需要使用URL Encoding
将不被允许的字符转换成对应的十六进制三元字符组, 这个转换的过程被称为URI的encoding。
URI encode也被称作percent-encoding
, 原因是,所有不被允许的字符都需要转义成为使用%
开头的十六进制字符组,因此也被叫做perceng encoding
哪些字符可以包含在URI中?
根据RFC 3986所述,一个valid的URI中只能包含以下84种字符:
- 特殊字符
-._~:/?#[]@!$&'()*+,;=
-
字母
a-z / A-Z -
数字
0-9 -
以%开头的十六进制三元字符组
除此之外的任何一种字符都需要是使用字符三元组
替代。
如果URL中出现这种不被允许的字符会怎么样呢?
- 请求通过浏览器或者postman,做过转义之后发出
如果你通过浏览器发出请求中包含了一些不被允许的字符,浏览器会帮助我们做一些转义,别以为这是一件好事儿,因为不同的浏览器有不同的转义字符的方式。这时候你可能会惊喜的发现,同样一个URL,chrome上请求成功,IE11直接400
- 请求不做任何转义直接发送到server
这种方式我也不知道如何做到,我尝试使用curl/postman/
发现都会被转义,那么我们就大胆的猜测一下。
一个真的没有转义过包含非法字符的请求发送到server,会出现什么结果呢?
大胆猜测一下,server应该没有办法resolve这种请求,那么就有可能直接throw 400 error
简而言之, 如果直接发送包含不允许字符的URI给server,同样Server也不能够识别这些字符,就有可能导致这次请求失败
How can we achieve URL encoding in JS
JS提供了内置了两个API对URI进行encode:
- encodeURIComponent
- encodeURI
他们都可以将特殊字符进行encode,那么区别是什么呢?
- encodeURI() 不会encode:
~!@#$&*()=:/,;?+'
说明这个function可以作用于整个URI
encodeURI('https://stackoverflow.com/questions/?path={"a":"1"}')
// "https://stackoverflow.com/questions/?path=%7B%22a%22:%221%22%7D"
- encodeURIComponent() will not encode: ~!*()'
说明类似于?
这种分界query和path的符号也会被转义,因此无法作用于整个URI
encodeURIComponent是对URI的组成部分进行编码的方法,而不用对整个URL进行编码。
encodeURIComponent('https://stackoverflow.com/questions/?path={"a":"1"}')
// "https%3A%2F%2Fstackoverflow.com%2F%3Fpath%3D%7B%22a%22%3A%221%22%7D"
这样的URL根本无法被识别
Note
请不要使用escape,此方法已经被废弃
实例
- 在client端发一个请求获取所有的search result, 我在code中直接使用了fetch给下面的url发送了请求
https://xxxx/AAA/api/results?info={
"name":"yoyo"}&options={"page":1,"pageSize":30}
- 当我在chrome中打开页面的时候,server端接收到的请求是:
https://xxxx/AAA/api/results?info={%22name%22:%22yoyo%22}&options={%22page%22:1,%22pageSize%22:30}
- 当我在IE11中打开页面的时候,发现这个请求总是400,结果查看server端接收到的请求是:
https://xxxx/AAA/api/results?info={\x22name\x22:\x22yoyo\x22}&options={\x22page\x22:1,\x22pageSize\x22:30}
由于window的编码方式不同,导致server端无法识别\x22
,所以直接返回400
网友评论