標籤:

percent-encode 百分號編碼

原文地址:http://www.imkevinyang.com/2009/08/詳解javascript中的url編解碼.html摘要URI(統一資源標識)編解碼為什麼需要編碼哪些需要編碼如何編碼預備知識foo://example.com:8042/over/there?name=ferret#nose\_/ \______________/ \________/\_________/ \__/| | | | |scheme authority path query fragment上面為典型的URL的格式。由於URL屬於URI的一種,所以下面提到的URL編碼,實際上應該指的是URI編碼。為什麼需要URL編碼?通常如果一樣東西需要編碼,說明這樣東西並不適合傳輸。原因多種多樣,如:內容Size過大、包含隱私數據等。URL的編碼原因是因為URL中有些字元會引起歧義。例如:URL參數字元串中使用鍵值對(key=value)的方式來傳參,鍵值對之間以&符號分隔,如"/s?q=abc& ie=utf-8"。如果value字元串中包含了"="或者"&",那麼勢必會造成接收URL的伺服器解析錯誤,因此必須將引起歧義的"="或者"&"符號進行轉義,也就是對其進行編碼。又如,URL的編碼格式採用的是ASCII碼,而不是Unicode,所以你不能在URL中包含任何非ASCII字元,例如中文。否則如果客戶端瀏覽器和服務端瀏覽器支持的字符集不同的情況下,可能會造成問題。URL編碼的原則就是使用安全的字元(沒有特殊用途或者特殊意義的可列印字元)去表示那些不安全的字元。哪些字元需要編碼?RFC3986文檔規定,URL中只允許包含英文字母(a-zA-Z)、數字(0-9)、4個特殊字元(- _ . ~)以及所有保留字元。RFC3986文檔對URL的編解碼問題做出了詳細的建議,指出了哪些字元需要被編碼才不會引起URL語義的轉變,以及對為什麼這些字元需要編碼做出了相應的解釋。URL中只允許使用可列印字元。US-ASCII碼中的10-7F位元組全都表示控制字元,這些字元都不能直接出現在URL中。同時,對於80-FF位元組(ISO-8859-1),由於已經超出了US-ACII定義的位元組範圍,因此也不可以放在URL中。保留字元。URL可以劃分成若干個組件:協議、主機、路徑等。有一些字元(:/?#[]@)是用作分隔不同組件的。例如:":"用於分隔協議和主機,"/"用於分隔主機和路徑,"?"用於分隔路徑和查詢參數,等等。還有一些字元(!$&"()*+,;=)用於在每個組件中起到分隔作用的,如"="用於表示查詢參數中 的鍵值對,"&"符號用於分隔查詢多個鍵值對。當組件中的普通數據包含這些特殊字元時,需要對其進行編碼。RFC3986中指定了以下字元為保留字元:!*"();:@&=+$,/?#[]不安全字元。還有一些字元,當他們直接放在URL中的時候,可能會引起解析程序的歧義。這些字元被視為不安全字元,原因有很多。空格在傳輸、用戶排版、文本處理程序處理URL的過程中都有可能引入無關緊要的空格或者去掉了有意義的空格引號以及<>引號和尖括弧通常用於在普通文本中起到分隔Url的作用#通常用於表示書籤或者錨點%百分號本身用作對不安全字元進行編碼時使用的特殊字元,因此本身需要編碼{}|^[]`~某一些網關或者傳輸代理會篡改這些字元注意:對於URL中的合法字元,編碼和不編碼是等價的,但對於上面提到的這些字元如果不經過編碼,那麼它們有可能會造成URL語義的不同。因此對於URL而言,只有普通英文字元和數字,特殊字元$-_.+!*"()還有保留字元,才能出現在未經編碼的URL之中。其他字元均需要經過編碼。但是由於歷史原因,目前尚存在一些不標準的編碼實現。例如對於"~"符號,雖然RFC3986文檔規定,對於波浪符號~,不需要進行URL編碼,但是還是有很多老的網關或者傳輸代理會。如何對Url中的非法字元進行編碼?URL編碼通常也被稱為百分號編碼(Url Encoding,also known as percent-encoding),是因為它的編碼方式非常簡單,使用%百分號加上兩位的字元(十六進位0~F)。URL編碼默認使用的字符集是US-ASCII。例如a在US-ASCII碼中對應的位元組是0x61,那麼URL編碼之後得到的就 是%61,我們在地址欄上輸入http://g.cn/search?q=%61%62%63,實際上就等同於在google上搜索abc了。又如@符號在ASCII字符集中對應的位元組為0x40,經過URL編碼之後得到的是%40。常見字元的URL編碼列表:保留字元的URL編碼!*""();:@&%21%2A%22%27%28%29%3B%3A%40%26=+$,/?%#[]%3D%2B%24%2C%2F%3F%25%23%5B%5D對於非ASCII字元,需要使用ASCII字符集的超集進行編碼得到相應的位元組,然後對每個位元組執行百分號編碼。 對於Unicode字元,RFC文檔建議使用utf-8對其進行編碼得到相應的位元組,然後對每個位元組執行百分號編碼。如:"中文"使用UTF-8字符集得到的位元組為0xE4 0xB8 0xAD 0xE6 0x96 0x87,經過URL編碼之後得到"%E4%B8%AD%E6%96%87"。如果某個位元組對應著ASCII字符集中的某個非保留字元,則此位元組無需使用百分號表示。 例如:"URL編碼",使用UTF-8編碼得到的位元組是0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由於前三個位元組對應著ASCII中的非保留字元"URL",因此這三個位元組可以用非保留字元"URL"表示。最終的URL編碼可以簡化成"URL%E7%BC%96%E7%A0%81",當然,如果你用"%55%72%6C%E7%BC%96%E7%A0%81"也是可以的。由於歷史的原因,有一些URL編碼實現並不完全遵循這樣的原則。其他和URL編碼相關的問題對包含中文的URL的處理問題,不同瀏覽器有不同的表現。例如:對於IE,如果你勾選了高級設置"總是以UTF-8發送URL",那麼URL路徑部分的中文會使用UTF-8進行URL編碼之後發送給服務端,而查詢參數中的中文部分使用系統默認字符集進行URL編碼。為了保證最大的互操作性,建議所有放到URL中的組件全部顯式指定某個字符集進行URL編碼,而不依賴於瀏覽器的默認實現。另外,很多HTTP監視工具或者瀏覽器地址欄等在顯示URL的時候會自動將URL進行一次解碼(使用UTF-8字符集),這就是為什麼當你在 Firefox中訪問Google搜索中文的時候,地址欄顯示的URL包含中文的緣故。但實際上發送給服務端的原始URL還是經過編碼的。你可以在地址欄上使用Javascript訪問location.href就可以看出來了。在研究URL編解碼的時候千萬別被這些假象給迷惑了。
推薦閱讀:

業力與大腦神經編碼記憶 腦可塑性-大腦皮層增大-記憶學習經歷固化 大腦重構 關鍵期MeCP2蛋白 中風大腦修復
JSP頁面編碼問題分析
字元,位元組和編碼
web請求編碼的有關問題
引得市缺字字體編碼方案說明

TAG:編碼 |