URL與URL編碼詳解
作為前端,每日與URL打交道是必不可少的。但是也許每天只是單純的用,對其只是一知半解,隨著工作的展開,我發現在日常抓包除錯,介面呼叫,瀏覽器相容等許多方面,不深入去理解URL與URL編碼則會踩到很多坑。故寫下此篇文章,詳解一下URL 。
URL與URI:
URL:(Uniform/Universal Resource Locator 的縮寫,統一資源定位符)。
URI:(Uniform Resource Identifier 的縮寫,統一資源識別符號)。
URI屬於URL更低層次的抽象,一種字串文字標準。
就是說,URI屬於父類,而URL屬於URI的子類。URL是URI的一個子集。
二者的區別在於,URI 表示請求伺服器的路徑,定義這麼一個資源。而 URL 同時說明要如何訪問這個資源(http://)。
埠與URL標準格式:
埠(Port),相當於一種資料的傳輸通道。用於接受某些資料,然後傳輸給相應的服務,而電腦將這些資料處理後,再將相應的回覆通過開啟的埠傳給對方。
埠的作用:因為 IP 地址與網路服務的關係是一對多的關係。所以實際上因特網上是通過 IP 地址加上埠號來區分不同的服務的。
埠是通過埠號來標記的,埠號只有整數,範圍是從0 到65535。
URL標準格式:
通常而言,我們所熟悉的 URL 的常見定義格式為:
[JavaScript] 純文字檢視 複製程式碼scheme://host[:port#]/path/.../[;url-params][?query-string][#anchor] scheme //有我們很熟悉的http、https、ftp以及著名的ed2k,迅雷的thunder等。 host //HTTP伺服器的IP地址或者域名 port# //HTTP伺服器的預設埠是80,這種情況下埠號可以省略。 path //訪問資源的路徑 url-params //所帶引數 query-string //傳送給http伺服器的資料 anchor //錨點定位
利用a標籤自動解析url:
開發當中一個很常見的場景是,需要從 URL 中提取一些需要的元素,譬如 host 、 請求引數等等。
通常的做法是寫正則去匹配相應的欄位,原理是動態建立一個 a 標籤,利用瀏覽器的一些原生方法及一些正則(為了健壯性正則還是要的),完美解析 URL ,獲取我們想要的任意一個部分。
程式碼如下:
[JavaScript] 純文字檢視 複製程式碼// This function creates a new anchor element and uses location // properties (inherent) to get the desired URL data. Some String // operations are used (to normalize results across browsers). function parseURL(url) { var a = document.createElement('a'); a.href = url; return { source: url, protocol: a.protocol.replace(':',''), host: a.hostname, port: a.port, query: a.search, params: (function(){ var ret = {}, seg = a.search.replace(/^\?/,'').split('&'), len = seg.length, i = 0, s; for (;i<len;i++) { if (!seg[i]) { continue; } s = seg[i].split('='); ret[s[0]] = s[1]; } return ret; })(), file: (a.pathname.match(/([^/?#]+)$/i) || [,''])[1], hash: a.hash.replace('#',''), path: a.pathname.replace(/^([^/])/,'/$1'), relative: (a.href.match(/tps?:\/[^/]+(.+)/) || [,''])[1], segments: a.pathname.replace(/^\//,'').split('/') }; }
Usage 使用方法:
[JavaScript] 純文字檢視 複製程式碼var myURL = parseURL('http://abc.com:8080/dir/index.html?id=255&m=hello#top'); myURL.file; // = 'index.html' myURL.hash; // = 'top' myURL.host; // = 'abc.com' myURL.query; // = '?id=255&m=hello' myURL.params; // = Object = { id: 255, m: hello } myURL.path; // = '/dir/index.html' myURL.segments; // = Array = ['dir', 'index.html'] myURL.port; // = '8080' myURL.protocol; // = 'http' myURL.source; // = 'http://abc.com:8080/dir/index.html?id=255
利用上述方法,即可解析得到 URL 的任意部分。
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 字元,例如中文。否則如果客戶端瀏覽器和服務端瀏覽器支援的字符集不同的情況下,中文可能會造成問題。
escape 、encodeURI 、encodeURIComponent和escape():
(1).escape():
W3C把這個函式廢棄了。
escape只是對字串進行編碼(而其餘兩種是對URL進行編碼),與URL編碼無關。編碼之後的效果是以 %XX 或者 %uXXXX 這種形式呈現的。它不會對 ASCII字元、數字 以及 @ * / + 進行編碼。
根據 MDN 的說明,escape 應當換用為 encodeURI 或 encodeURIComponent;unescape 應當換用為 decodeURI 或 decodeURIComponent。escape 應該避免使用。舉例如下:
[JavaScript] 純文字檢視 複製程式碼encodeURI('https://www.baidu.com/ a b c') // "https://www.baidu.com/%20a%20b%20c" encodeURIComponent('https://www.baidu.com/ a b c') // "https%3A%2F%2Fwww.baidu.com%2F%20a%20b%20c" //而 escape 會編碼成下面這樣,eocode 了冒號卻沒 encode 斜槓,十分怪異,故廢棄之 escape('https://www.baidu.com/ a b c') // "https%3A//www.baidu.com/%20a%20b%20c"
(2).encodeURI():
encodeURI() 是 Javascript 中真正用來對 URL 編碼的函式。它著眼於對整個URL進行編碼。
[JavaScript] 純文字檢視 複製程式碼encodeURI("http://www.cnblogs.com/season-huang/some other thing"); //"http://www.cnblogs.com/season-huang/some%20other%20thing";
編碼後變為上述結果,可以看到空格被編碼成了%20,而斜槓 / ,冒號 : 並沒有被編碼。
是的,它用於對整個 URL 直接編碼,不會對 ASCII字母 、數字 、 ~ ! @ # $ & * ( ) = : / , ; ? + ‘ 進行編碼。
[JavaScript] 純文字檢視 複製程式碼encodeURI("~!@#$&*()=:/,;?+'") // ~!@#$&*()=:/,;?+'
(3).encodeURIComponent():
有的時候,我們的 URL 長這樣子,請求引數中帶了另一個 URL :
[JavaScript] 純文字檢視 複製程式碼var URL = "http://www.a.com?foo=http://www.b.com?t=123&s=456";
直接對它進行 encodeURI 顯然是不行的。
因為 encodeURI 不會對冒號 : 及斜槓 / 進行轉義,那麼就會出現上述所說的伺服器接受到之後解析會有歧義。
[JavaScript] 純文字檢視 複製程式碼encodeURI(URL) // "http://www.a.com?foo=http://www.b.com?t=123
這個時候,就該用到encodeURIComponent() 。它的作用是對 URL 中的引數進行編碼,記住是對引數,而不是對整個URL進行編碼。
因為它僅僅不對 ASCII字母、數字 ~ ! * ( ) ‘ 進行編碼。
錯誤的用法:
[JavaScript] 純文字檢視 複製程式碼var URL = "http://www.a.com?foo=http://www.b.com?t=123&s=456"; encodeURIComponent(URL); // "http%3A%2F%2Fwww.a.com%3Ffoo%3Dhttp%3A%2F%2Fwww.b.com%3Ft%3D123%26s%3D456" // 錯誤的用法,看到第一個 http 的冒號及斜槓也被 encode 了
正確的用法:
encodeURIComponent() 著眼於對單個的引數進行編碼:
[JavaScript] 純文字檢視 複製程式碼var param = "http://www.b.com?t=123&s=456"; // 要被編碼的引數 URL = "http://www.a.com?foo="+encodeURIComponent(param); //"http://www.a.com?foo=http%3A%2F%2Fwww.b.com%3Ft%3D123%26s%3D456"
利用上述的使用 a 標籤解析 URL 以及根據業務場景配合 encodeURI() 與 encodeURIComponent() 便能夠很好的處理 URL 的編碼問題。
應用場景最常見的一個是手工拼接 URL 的時候,對每對 key-value 用 encodeURIComponent 進行轉義,再進行傳輸。
相關文章
- 【基礎進階】URL詳解與URL編碼
- URL編碼與解碼原理
- Javascript編碼解碼URLJavaScript
- PHP中urlencode()函式進行URL編碼詳解PHP函式
- URL編碼轉換
- ptyon 特殊處理 url 編碼與解碼,字元編碼轉化 unicode字元Unicode
- js裡對URL進行編碼、解碼JS
- 解決 requests 庫 URL 編碼問題
- JavaScript對url地址編碼JavaScript
- 深入淺出URL編碼
- 前端補充:url編碼前端
- JS、C#中URL編碼解碼問題JSC#
- URL編碼:原理、應用與安全性
- 關於URL編碼/javascript/jsurl編碼JavaScriptJS
- js中對URL進行轉碼與解碼JS
- URL編碼(傳遞特殊符號)符號
- Python程式設計:URL網址連結中的中文編碼與解碼Python程式設計
- Django web框架-----url path name詳解DjangoWeb框架
- java實現url轉碼、解碼Java
- 使用javascript如何給url進行編碼JavaScript
- url傳遞的引數值編碼
- Python urlencode 編碼和url拼接Python
- iOS Url特殊符號編碼問題iOS符號
- Nginx URL重寫規則配置詳解Nginx
- python處理瀏覽器URL編碼Python瀏覽器
- Web開發者應知的URL編碼知識Web
- 網址URL中特殊字元轉義編碼字元
- CI框架中的site_url()與base_url()框架
- PHP安全的URL字串base64編碼和解碼PHP字串
- 網頁地址編碼解碼(網頁地址明文密文轉換)url編碼解碼 Python3網頁Python
- js解決url中文亂碼問題JS
- <url-pattern>/</url-pattern>和<url-pattern>/*</url-pattern>區別
- [URL轉碼]瀏覽器如何給URL進行轉碼的瀏覽器
- 網址(URL)的詳細解析
- Js 和Url預設位址列編碼等處理JS
- 包含中文字元的URL編碼問題(轉)字元
- url
- CI框架原始碼解讀--ROUTE和URL類框架原始碼