你真的瞭解URLEncode嗎?

xiaxveliang 發表於 2021-02-23

使用瀏覽器進行Http網路請求時,若請求query中包含中文,中文會被編碼為 %+16進位制+16進位制形式,但你真的深入瞭解過,為什麼要進行這種轉義編碼嗎?編碼的原理又是什麼?

例如,瀏覽器中進行百度搜尋“你好”時,連結地址會被自動編碼:
(編碼前)https://www.baidu.com/s?wd=你好
(編碼後)https://www.baidu.com/s?wd=%E4%BD%A0%E5%A5%BD
出現以上情況是網路請求前,瀏覽器對請求URL進行了URL編碼(URL Encoding)

URL編碼(URL Encoding):也稱作百分號編碼(Percent Encoding), 是特定上下文的統一資源定位符 URL的編碼機制。URL編碼(URL Encoding)也適用於統一資源標誌符(URI)的編碼,同樣用於 application/x-www-form-urlencoded MIME準備資料。

一、為什麼需要URL Encoding

在URL的最初設計時,希望可以通過書面轉錄,比如寫在餐巾紙上告訴另外一人,因此URI的構成字元必須是可寫的ASCII字元。
中文不在ASCII字元中,因此中文出現在URL地址中時,需要進行編碼;同時可書寫的ASCII字元中,存在一些不安全字元也需要轉碼,如空格(空格容易被忽略,也容易意想不到的原因引入)。

不安全字元

不安全字元

二、編碼原理

編碼的原理可以表述為:
將需要轉碼的字元,按指定編碼方式(預設使用UTF-8編碼)轉化為位元組流,每個位元組按16進製表示,並新增%組成一個percent編碼。

例如:漢字 “你好”

  • UTF-8位元組流列印為:-28 -67 -96 -27 -91 -67
  • 對應的16進製表示為:E4 BD A0 E5 A5 BD
  • URLEncode編譯後為:%E4%BD%A0%E5%A5%BD

2.1、哪些字元需要轉碼

上文中提到需要轉碼的字元,那麼哪些字元是需要轉碼的字元?
這裡涉及到兩個概念:Reserved(保留字元)Unreserved(非保留字元)

  • Reserved(保留字元)是那些具有特殊含義的字元,例如:"/"字元用於URL不同部分的分界符;
  • Unreserved(非保留字元)沒有特殊含義,包含希臘字母 / 數字 / "-" / "." / "_" / "~"

保留字元&非保留字元

回到剛才的問題,哪些字元是需要轉碼的字元?

  • 1、除了Reserved(保留字元)Unreserved(非保留字元)之外的所有字元,均需要percent編碼;
  • 2、某些情況下Reserved(保留字元)也需要進行percent編碼:
    Reserved(保留字元)不用於URL分隔符,而是用於其他的位置,不代表某種特性的含義時,需要進行percent編碼。例如:保留字元用於URL請求query後面的value中時,要對此時用到的Reserved(保留字元)做percent編碼;

2.2、注意:空格的編碼有 “+”和“%20”兩種

結論:

  • 1、空格編碼為+的情況:
    提交表單時請求時Content-Type:application/x-www-form-urlencoded的情況下,URL請求查詢字串中出現空格時,需替換為+
  • 2、其他情況空格編碼為%20

依據:

按照 rfc3986 標準,空格在進行編碼時,編碼後對應為%20

空格ASCII表16進製表示對應為20

但根據W3C標準:,提交表單時請求時Content-Type:application/x-www-form-urlencoded情況下,URL請求查詢字串中出現空格時,需替換為+

W3C中空格替換為+號依據

三、參考

rfc3986:
https://tools.ietf.org/html/rfc3986

rfc1738:
https://www.ietf.org/rfc/rfc1738.txt

W3C標準:
https://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1

維基百科:百分號編碼:
https://zh.wikipedia.org/wiki/%E7%99%BE%E5%88%86%E5%8F%B7%E7%BC%96%E7%A0%81

========== THE END ==========

歡迎關注我的公眾號