close

 

因為噗浪朋友的一則訊息,讓我興起了想要整理一些關於 URLEncode 的問題,整理一下才發現每個語言都有不同的函式來處理關於 URLEncode 的問題。

先說為什麼需要作 URLEncode,RFC 3986規範了哪些字元是作為保留字(如:!@/?等),如果URL中使用到了這些保留字,就必須將它編碼為「%HEXHEX」的形式,舉例來說,「空白字元」的 ASCII code 是32,所以會被編碼為 %20,而其它 non-ASCII 字元(如:中文字)則以 UTF-8 字元編碼後的位元組來編碼成 %HEXHEX 的形式。

如果有一個字串是:「This is my **書本**」,根據 RFC 3986 的定義,作完 URL encode 之後應該會變成「This%20is%20my%20%2A%2A%E6%9B%B8%E6%9C%AC%2A%2A」。

那什麼時候會需要對文字作 URL encode 呢?比方說,Facebook 提供了一個分享網頁到個人塗鴨牆(Wall)的作法,那就是將欲分享的網頁URL,比方說是 http://www.example.com/,只要將它作為參數(u傳給http://www.facebook.com/share.php就可以了,但你千萬不能寫成:

http://www.facebook.com/share.php?u=http://www.example.com/

 

,而是必須將它作 URL encode 之後,組合成:

http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.example.com%2F

 

這樣才是正確的。

若是你在瀏覽器的網址列直接輸入前者也會正確,那是因為瀏覽器會幫你作了 url encode

不過,在 RFC 3986 之前,HTTP 也有為 GET/POST 在傳遞參數時的 url encode 方式作定義,基本上也是 encode 成 %HEXHEX 的形式,保留字跟 RFC 3986 的有部份出入,不過就沒有限定一定是 UTF-8 的文字編碼了,而且還有一個重點--「空白字元」會被編碼成 + 而不是 %20。所以「This is a book」就會被編碼成「This+is+a+book」。

常用語言的函式庫

因為有這樣的差異,所以開發人員在使用函式庫的時候常常會搞混什麼時候該用/不該用什麼函式,以 PHP 來說就分為兩組函式:

  • urlencode / urldecode

    簡單地說就是以 HTTP 所使用的 application/x-www-form-urlencoded 的編碼規則,也就是會將空白字元編碼成 + 而不是%20

  • rawurlencode / rawurldecode

    按照 RFC 3986 所定義的方式來作編碼。

Python 版本的話就是:

  • urllib.urlencode / urllib.urldecode

    會把空白字元編碼成 +

  • 目前要使用 Python 3 以後的 urllib.parse.urlencode 才會按照 RFC 3986 的方式來作編碼,若是 2.x 的版本就要另外處理或是找 3rd-party 資料庫來做。

JavaScript 的 encodeURI 或是 encodeURIComponent (兩者僅相差一些保留字是否要作編碼,如 #)目前則是都使用 RFC 3986 的方式來作編碼,所以要作 application/x-www-form-urlencoded 的編碼時(AJAX POST),就要自己把 %20 替換成 + (jQuery 目前的程式碼就是這樣做的)

Java 的 java.net.URLEncoder.encode 這個 method 也是編碼成 application/x-www-form-urlencoded 的方式,如果要遵照 RFC 3986 的定義,則可以自行再把 + 替換成 %20 即可。

--

轉自 http://blog.ericsk.org/archives/1423

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 dizzy03 的頭像
    dizzy03

    碎碎念

    dizzy03 發表在 痞客邦 留言(0) 人氣()