天天看點

【基礎進階】URL詳解與URL編碼

作為前端,每日與 URL 打交道是必不可少的。但是也許每天隻是單純的用,對其隻是一知半解,随着工作的展開,我發現在日常抓包調試,接口調用,浏覽器相容等許多方面,不深入去了解URL與URL編碼則會踩到很多坑。故寫下此篇文章,詳解一下 URL 。

很多人會混淆這兩個名詞。

URL:(Uniform/Universal Resource Locator 的縮寫,統一資源定位符)。

URI:(Uniform Resource Identifier 的縮寫,統一資源辨別符)。

關系:

URI 屬于 URL 更低層次的抽象,一種字元串文本标準。

就是說,URI 屬于父類,而 URL 屬于 URI 的子類。URL 是 URI 的一個子集。

二者的差別在于,URI 表示請求伺服器的路徑,定義這麼一個資源。而 URL 同時說明要如何通路這個資源(http://)。

何為端口?端口(Port),相當于一種資料的傳輸通道。用于接受某些資料,然後傳輸給相應的服務,而電腦将這些資料處理後,再将相應的回複通過開啟的端口傳給對方。

端口的作用:因為 IP 位址與網絡服務的關系是一對多的關系。是以實際上網際網路上是通過 IP 位址加上端口号來區分不同的服務的。

端口是通過端口号來标記的,端口号隻有整數,範圍是從0 到65535。

通常而言,我們所熟悉的 URL 的常見定義格式為:

scheme://host[:port#]/path/.../[;url-params][?query-string][#anchor]

 

開發當中一個很常見的場景是,需要從 URL 中提取一些需要的元素,譬如 host 、 請求參數等等。

通常的做法是寫正則去比對相應的字段,當然,這裡要安利下述這種方法,來自 James 的 blog,原理是動态建立一個 a 标簽,利用浏覽器的一些原生方法及一些正則(為了健壯性正則還是要的),完美解析 URL ,擷取我們想要的任意一個部分。

代碼如下:

Usage 使用方法:

利用上述方法,即可解析得到 URL 的任意部分。

為什麼要進行URL編碼?通常如果一樣東西需要編碼,說明這樣東西并不适合直接進行傳輸。

1、會引起歧義:例如 URL 參數字元串中使用 key=value 這樣的鍵值對形式來傳參,鍵值對之間以 & 符号分隔,如 ?postid=5038412&t=1450591802326,伺服器會根據參數串的 & 和 = 對參數進行解析,如果 value 字元串中包含了 = 或者 & ,如寶潔公司的簡稱為P&G,假設需要當做參數去傳遞,那麼可能URL所帶參數可能會是這樣 ?name=P&G&t=1450591802326,因為參數中多了一個&勢必會造成接收 URL 的伺服器解析錯誤,是以必須将引起歧義的 & 和 = 符号進行轉義, 也就是對其進行編碼。

2、非法字元:又如,URL 的編碼格式采用的是 ASCII 碼,而不是 Unicode,這也就是說你不能在 URL 中包含任何非 ASCII 字元,例如中文。否則如果用戶端浏覽器和服務端浏覽器支援的字元集不同的情況下,中文可能會造成問題。

那麼如何編碼?如下:

首先想聲明的是,W3C把這個函數廢棄了,身為一名前端如果還用這個函數是要打臉的。

escape隻是對字元串進行編碼(而其餘兩種是對URL進行編碼),與URL編碼無關。編碼之後的效果是以 %XX 或者 %uXXXX 這種形式呈現的。它不會對 ASCII字元、數字 以及 @ * / + 進行編碼。

根據 MDN 的說明,escape 應當換用為 encodeURI 或 encodeURIComponent;unescape 應當換用為 decodeURI 或 decodeURIComponent。escape 應該避免使用。舉例如下:

encodeURI() 是 Javascript 中真正用來對 URL 編碼的函數。它着眼于對整個URL進行編碼。

編碼後變為上述結果,可以看到空格被編碼成了%20,而斜杠 / ,冒号 : 并沒有被編碼。

是的,它用于對整個 URL 直接編碼,不會對 ASCII字母 、數字 、 ~ ! @ # $ & * ( ) = : / , ; ? + ' 進行編碼。

嘿,有的時候,我們的 URL 長這樣子,請求參數中帶了另一個 URL :

直接對它進行 encodeURI 顯然是不行的。因為 encodeURI 不會對冒号 : 及斜杠 / 進行轉義,那麼就會出現上述所說的伺服器接受到之後解析會有歧義。

這個時候,就該用到 encodeURIComponent() 。它的作用是對 URL 中的參數進行編碼,記住是對參數,而不是對整個 URL 進行編碼。

因為它僅僅不對 ASCII字母、數字 ~ ! * ( ) '  進行編碼。

錯誤的用法:

正确的用法:encodeURIComponent() 着眼于對單個的參數進行編碼:

利用上述的使用<a>标簽解析 URL 以及根據業務場景配合 encodeURI() 與 encodeURIComponent() 便能夠很好的處理 URL 的編碼問題。

應用場景最常見的一個是手工拼接 URL 的時候,對每對 key-value 用 encodeURIComponent 進行轉義,再進行傳輸。

原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。