中文URL編碼

URL編碼是一個比較麻煩的事情,RFC 3986是關於URI的一個標準,在它的第2節定義了字符如何在URI中進行表示,而第3節把一個URI區分爲scheme, hier-part, query, fragment幾個component。根據這個RFC,A URI is composed from a limited set of characters consisting of digits, letters, and a few graphic symbols. 附錄A中給出了ABNF定義。

比如URL,http://www.forss.cn/?p=230#comments,就包含了上述的全部四個components。這個URL不需要進行百分號編碼,因爲每個component中都沒有保留字,全部爲字母、數字或者非保留的ASCII可見字符(見RFC 3986第2.3節)。

假設我們在Firefox中打開了這個URL,並且想通過del.icio.us的插件按鈕把它收藏起來。del.icio.us插件打開一個新窗口,並通過GET方法向服務器發出請求,將這個URL和它對應的title作爲query的參數傳遞給服務器,服務器就把這兩個值填充到對應的input value屬性中。

假如不經過編碼,這個GET請求中的URL就是”http://del.icio.us/flimsy?url=http://www.forss.cn/?p=230#comments&title=*** » ***» Blog換了個樣子&noui&jump=close&v=4″。問題就出來了,#號後面的是什麼呢?按理說應該解釋爲頁面中的一個anchor,然而#comments只是url這個參數的一部分。另外,URL中含有漢字,也不符合標準。所以編碼是必須的,要針對各個component,以及query中的每個參數值做percent encoding. 注意不是對整個URL(指del.icio.us的GET請求中的長URL)做,如果flimsy後面的問號被編碼,服務器便不知道它後面是query部分了。正確編碼後的鏈接應該是這樣,很長,就不顯示了,你可以複製鏈接地址來看看(似乎顯示的時候瀏覽器又自動decode了,點擊即可在地址欄看到編碼後結果)

URL編碼要求先將URL轉換爲一個UTF-8的字節序列,然後再做percent encoding, 這在RFC 3986和W3C的網站上都有介紹。在爲Firefox做插件時,主要用Javascript實現程序邏輯,而Javascript中的字符串是UTF-8編碼,且有一個方便的encodeURIComponent函數可以做URL編碼。除此之外,還有escape/encodeURI兩個函數。關於它們三個的比較,可參考這篇文章

如果沒有現成的函數,對UTF-8字節序列進行percent encoding也是比較方便的。對於unreserved character值,不需要做轉換,其它的字節全部用% HEXDIG HEXDIG來表示。另外空格除”%20″外,也可以轉爲”+”,節省空間。

一個非常重要的問題就是如何把字符(ASCII字符除外,主要是中文等)轉換爲UTF-8的字節序列。並不是每種語言都像Javascript那樣方便,比如在C++中,你得到了一個含有中文的寬字符串,怎麼處理呢?Win32 API中是有一個InternetCanonicalizeUrl函數,但它只針對一個字節序列,不會考慮中文的編碼轉換。在MSDN“規範的URL”定義中,”Characters that must be encoded”並沒有提到寬字符的處理,甚至沒有提到UTF-8. 它還要求字符串中必須包含一個scheme.

有時間的時候我會再寫一篇關於怎麼在Windows中把中文轉換爲UTF-8字節序列的文章,對進行中文URL編碼的朋友也許會有幫助。見“GBK(GB2312)向UTF-8的編碼轉換”一文。

PS. 網上文章一大抄,這幾天體會深刻,中文文章尤甚。許多誤導的文章被當作經典轉來轉去,充斥着搜索引擎。網上信息越來越多,有用的信息有時候卻越來越難找。本文參考網上一些較爲權威的資料,但仍有可能理解不對,歡迎指正。

 
發佈了3 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章