轉(zhuǎn)義原因:避免引起歧義
現(xiàn)在URL會(huì)使用key=value的形式傳參笛谦,鍵值對(duì)間使用&
分隔详炬,如/s?username=abc& password=123&fff
裙品。正常來(lái)說(shuō)忍宋,第一對(duì)鍵值是username=abc
帝火,第二對(duì)鍵值是password=123&fff
溜徙。然而第二隊(duì)鍵值對(duì)中的value的值包含了特殊字符&
,URL會(huì)根據(jù)這個(gè)字符分隔字符串湃缎,這就導(dǎo)致接收URL的服務(wù)器解析錯(cuò)誤了。所以我們需要對(duì)會(huì)引起歧義的URL字符進(jìn)行轉(zhuǎn)義蠢壹。
URL編碼原則:
使用安全的字符(沒(méi)有特殊用途或特殊意義的可打印字符)去表示那些不安全的字符嗓违。
那么那些是安全的字符,那些不是呢图贸?
文檔規(guī)定URL中只允許包含英文字符(a-zA-Z)蹂季、數(shù)字(0-9)、-_.~4個(gè)特殊字符以及所有保留字符疏日。
保留字符:
用作分隔不同組件的乏盐。我們知道URL可以劃分為不同的部分,如·協(xié)議制恍、主機(jī)、路徑等神凑。因此計(jì)算機(jī)保留了一些字符用作分隔的標(biāo)記净神,如冒號(hào)用于分隔協(xié)議和主機(jī),/用于分隔 主機(jī)和路徑溉委,?用于分隔路徑和查詢參數(shù)等鹃唯。還有一些字符(!$&'()*+,;=)用于在每個(gè)組件中起到分隔作用的,如=用于表示查詢參數(shù)中 的鍵值對(duì)瓣喊,&符號(hào)用于分隔查詢多個(gè)鍵值對(duì)坡慌。當(dāng)組件中的普通數(shù)據(jù)包含這些特殊字符時(shí),需要對(duì)其進(jìn)行編碼藻三。
指定的保留字符:
不安全字符:
有些字符在URL中會(huì)引起解析程序的歧義洪橘。具體原因有很多:
注意:對(duì)于合法字符來(lái)說(shuō),編碼和不編碼是等價(jià)的棵帽。但是對(duì)于上面提到的熄求,如果不經(jīng)過(guò)編碼,那么可能造成URL語(yǔ)義不同逗概。因此對(duì)于URL弟晚,至于普通英文和數(shù)字、特殊字符$-_.+!*'()還有保留 字符逾苫,才能出現(xiàn)在未經(jīng)編碼的URL中卿城。其他字符則都需要經(jīng)過(guò)編碼才能出現(xiàn)在URL中。
Url編碼(也叫百分比編碼:url encoding, or percent-encoding)
對(duì)于Url的非法字符铅搓,必須進(jìn)過(guò)編碼才能出現(xiàn)在url中瑟押,而目前采用的百分比編碼,就是將字符轉(zhuǎn)為對(duì)應(yīng)的16進(jìn)制標(biāo)量狸吞,然后每2位16進(jìn)制標(biāo)量前添加一個(gè)『%』勉耀。如a的16進(jìn)制ascii是61指煎,那么百分比編碼后值是%61。而非ascii字符便斥,如中文至壤,則先使用utf8編碼后,在進(jìn)行百分號(hào)編碼枢纠。如『樂(lè)』的utf8編碼是E4B990像街,所以它的百分比編碼結(jié)果是%E4%B9%90。
Swift中的編碼過(guò)程
Alamofire.request("http://hanxiao.52kjg.cn/Api/index.php", method: .post, parameters: params, encoding: URLEncoding.default).responseJSON
我們常用的Alamofire晋渺,上面代碼中的encoding就是URL編碼過(guò)程镰绎。(所以我們使用Alamofire時(shí), url或者參數(shù)中有特殊字符時(shí)木西,不用特殊處理畴栖,因?yàn)锳lamofire已經(jīng)為你處理好了)
主動(dòng)處理方式:
let myString = "樂(lè)"
//百分比編碼,參數(shù)表示特殊字符的種類
let percentEncode = myString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
print(percentEncode)
//解碼百分比的編碼
let decoding = percentEncode?.removingPercentEncoding
print(decoding)
上面方法不能對(duì)一些保留字符處理,如『=』八千。真TM坑吗讶。另外一種方法:地址:https://stackoverflow.com/questions/24551816/swift-encode-url/24552028#
let myString = "=123/"
let allowedCharacterSet = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)
if let escapedString = myString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) {
print(escapedString)
}
結(jié)果:
%3D123%2F