转义原因:避免引起歧义

现在URL会使用key=value的形式传参,键值对间使用&分隔,如/s?username=abc& password=123&fff。正常来说,第一对键值是username=abc,第二对键值是password=123&fff。然而第二队键值对中的value的值包含了特殊字符&,URL会根据这个字符分隔字符串,这就导致接收URL的服务器解析错误了。所以我们需要对会引起歧义的URL字符进行转义。

URL编码原则:

使用安全的字符(没有特殊用途或特殊意义的可打印字符)去表示那些不安全的字符。

那么那些是安全的字符,那些不是呢?

文档规定URL中只允许包含英文字符(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。

保留字符:

用作分隔不同组件的。我们知道URL可以划分为不同的部分,如·协议、主机、路径等。因此计算机保留了一些字符用作分隔的标记,如冒号用于分隔协议和主机,/用于分隔 主机和路径,?用于分隔路径和查询参数等。还有一些字符(!$&'()*+,;=)用于在每个组件中起到分隔作用的,如=用于表示查询参数中 的键值对,&符号用于分隔查询多个键值对。当组件中的普通数据包含这些特殊字符时,需要对其进行编码。

指定的保留字符:


不安全字符:

有些字符在URL中会引起解析程序的歧义。具体原因有很多:


注意:对于合法字符来说,编码和不编码是等价的。但是对于上面提到的,如果不经过编码,那么可能造成URL语义不同。因此对于URL,至于普通英文和数字、特殊字符$-_.+!*'()还有保留 字符,才能出现在未经编码的URL中。其他字符则都需要经过编码才能出现在URL中。

Url编码(也叫百分比编码:url encoding, or percent-encoding)

对于Url的非法字符,必须进过编码才能出现在url中,而目前采用的百分比编码,就是将字符转为对应的16进制标量,然后每2位16进制标量前添加一个『%』。如a的16进制ascii是61,那么百分比编码后值是%61。而非ascii字符,如中文,则先使用utf8编码后,在进行百分号编码。如『乐』的utf8编码是E4B990,所以它的百分比编码结果是%E4%B9%90。

Swift中的编码过程

Alamofire.request("http://hanxiao.52kjg.cn/Api/index.php", method: .post, parameters: params, encoding: URLEncoding.default).responseJSON

我们常用的Alamofire,上面代码中的encoding就是URL编码过程。(所以我们使用Alamofire时, url或者参数中有特殊字符时,不用特殊处理,因为Alamofire已经为你处理好了)

主动处理方式:

let myString = "乐"
//百分比编码,参数表示特殊字符的种类
let percentEncode = myString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
print(percentEncode)
//解码百分比的编码
let decoding = percentEncode?.removingPercentEncoding
print(decoding)
let myString = "=123/"
let allowedCharacterSet = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)
if let escapedString = myString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) {
print(escapedString)
}

结果:

%3D123%2F