百分號編碼
百分號編碼(英語:Percent-encoding),又稱URL編碼(URL encoding)是特定上下文的統一資源定位符(URL)的編碼機制,實際上也適用於統一資源標誌符(URI)的編碼。也用於為application/x-www-form-urlencoded MIME準備資料,因為它用於通過HTTP的請求操作(request)提交HTML表單資料。
URI的百分號編碼
URI的字元類型
URI所允許的字元分作保留與未保留。保留字元是那些具有特殊含義的字元,例如:斜線字元用於URL(或URI)不同部分的分界符;未保留字元沒有這些特殊含義。百分號編碼把保留字元表示為特殊字元序列。上述情形隨URI與URI的不同版本規格會有輕微的變化。
! |
* |
' |
( |
) |
; |
: |
@ |
& |
= |
+ |
$ |
, |
/ |
? |
# |
[ |
]
|
A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
M |
N |
O |
P |
Q |
R |
S |
T |
U |
V |
W |
X |
Y |
Z
| |
a |
b |
c |
d |
e |
f |
g |
h |
i |
j |
k |
l |
m |
n |
o |
p |
q |
r |
s |
t |
u |
v |
w |
x |
y |
z
| |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9
|
- |
_ |
. |
~ |
URI中的其它字元必須用百分號編碼。
對保留字元的百分號編碼
如果一個保留字元在特定上下文中具有特殊含義(稱作「reserved purpose」) , 且URI中必須使用該字元用於其它目的,那麼該字元必須百分號編碼。百分號編碼一個保留字元,首先需要把該字元的ASCII的值表示為兩個16進制的數字,然後在其前面放置跳脫字元(「%
」),置入URI中的相應位置。(對於非ASCII字元,需要轉換為UTF-8位元組序,然後每個位元組按照上述方式表示。)
例如,"/
",如果用作URI的路徑成份的分界符,則是具有特殊含義的保留字元。如果該字元需要出現在URI一個路徑成分的內部,則三字元序列"%2F
"或"%2f
"就用於代替原本的"/
"出現在該URI路徑成分的內部.
! |
# |
$ |
& |
' |
( |
) |
* |
+ |
, |
/ |
: |
; |
= |
? |
@ |
[ |
]
|
%21 |
%23 |
%24 |
%26 |
%27 |
%28 |
%29 |
%2A |
%2B |
%2C |
%2F |
%3A |
%3B |
%3D |
%3F |
%40 |
%5B |
%5D
|
在特定上下文中沒有特殊含義的保留字元也可以被百分號編碼,在語意上與不百分號編碼的該字元沒有差別。
在URI的"查詢"成分(?字元後的部分)中, 例如"/
"仍然是保留字元但是沒有特殊含義,除非一個特定的URI有其它規定。該/
字元在沒有特殊含義時不需要百分號編碼。
如果保留字元具有特殊含義,那麼該保留字元用百分號編碼的URI與該保留字元僅用其自身表示的URI具有不同的語意。
對未保留字元的百分號編碼
未保留字元不需要百分號編碼。
兩個URI的差別如果僅在於未保留字元是用百分號編碼還是用字元自身表示,那麼這兩個URI具有等價的語意。但URI處理器實際上並不總是把二者視作等價[來源請求]。例如,URI的消費者不應該把"%41
"與"A
","%7E
"與"~
"視作不同,但是某些URI的消費者就是這麼做了。為了最大的互操作性,URI的製造者不應該對未保留字元進行百分號編碼。
對百分號字元的百分號編碼
由於百分號字元("%")表示百分號編碼位元組流的存在,因此百分號字元應該被編碼為3個位元組的序列:"%25",用於URI內部。
對任意資料的百分號編碼
大多數URI涉及表示任意資料,例如IP位址或檔案系統路徑作為URI的成分。
二進資料
1994年發布的RFC 1738規定[1], URI中的二進制資料應該表示為8位元組的序列,然後對每個8位元組按照上述方式百分號編碼. 例如,位元組值0F(十六進制)應表示為"%0F
",位元組值41(十六進制)應表示為"A
"或"%41
". 優先使用未保留字元來表示這些位元組值,因為這使得URL更短。
字元資料
二進資料的百分號編碼過程已經被外推到字元資料,甚至到不適合或未被完全規範的地步。在WWW初創階段,僅僅處理ASCII字元是否編碼問題,還沒有什麼問題。但隨後發展到對非ASCII字元如何在URI中編碼,缺少標準規範的情況下導致了歧義性的解釋URI的錯誤。
例如, 基於RFC 1738與RFC 2396的協定規定,字元資料先要根據某種字元編碼轉換為位元組流,然後再表示為URI。如果URI不提供是何種字元編碼的提示資訊,那麼這個URI難以可靠的解析。
當前標準
2005年1月發布的RFC 3986,建議所有新的URI必須對未保留字元不加以百分號編碼;其它字元建議先轉換為UTF-8位元組序列, 然後對其位元組值使用百分號編碼。此前的URI不受此標準的影響。
非標準的實現
有一些不符合標準的把Unicode字元在URI中表示為:%uxxxx
, 其中xxxx是用4個十六進制數字表示的Unicode的碼位值。任何RFC都沒有這樣的字元表示方法,並且已經被W3C拒絕 (頁面存檔備份,存於網際網路檔案館)。第三版的ECMA-262仍然包含函式escape(string)
使用這種語法,但也有函式encodeURI(uri)
轉換字元到UTF-8位元組序列並用百分號編碼每個位元組。
application/x-www-form-urlencoded類型
當HTML表單中的資料被提交時,表單的域名與值被編碼並通過HTTP的GET或者POST方法甚至更古遠的email[2]把請求傳送給伺服器。這裡的編碼方法採用了一個非常早期的通用的URI百分號編碼方法,並且有很多小的修改如換行規格化以及把空格符的編碼"%20
"替換為"+
" 。按這套方法編碼的資料的MIME類型是application/x-www-form-urlencoded
,當前仍用於(雖然非常過時了)HTML與XForms規範中。此外,CGI規範包括了web伺服器如何解碼這類資料、利用這類資料的內容。
如果傳送的是HTTP GET請求,application/x-www-form-urlencoded
資料包含在所請求URI的查詢成分中。如果傳送的是HTTP POST請求或通過email,資料被放置在訊息體中,媒體類型的名字被包含在訊息的Content-Type頭內部。
參見
參考文獻
- ^ RFC 1738 §2.2; RFC 2396 §2.4; RFC 3986 §1.2.1, 2.1, 2.5
- ^ User-agent support for email based HTML form submission, using a 'mailto' URL as the form action, was proposed in RFC 1867 section 5.6, during the HTML 3.2 era. Various web browsers implemented it by invoking a separate email program or using their own rudimentary SMTP capabilities. Although sometimes unreliable, it was briefly popular as a simple way to transmit form data without involving a web server or CGI scripts.
外部連結
- RFC 3986 / STD 66 (plus errata (頁面存檔備份,存於網際網路檔案館)), the current generic URI syntax specification.
- RFC 2396 (obsolete, plus errata (頁面存檔備份,存於網際網路檔案館)) and RFC 2732 (plus errata (頁面存檔備份,存於網際網路檔案館)) together comprised the previous version of the generic URI syntax specification.
- RFC 1738 (mostly obsolete) and RFC 1808 (obsolete), which define URLs.
- RFC 1630 (obsolete), the first generic URI syntax specification.
- W3C Guidelines on Naming and Addressing: URIs, URLs, ... (頁面存檔備份,存於網際網路檔案館)
- W3C explanation of UTF-8 in URIs (頁面存檔備份,存於網際網路檔案館)
- W3C HTML form content types (頁面存檔備份,存於網際網路檔案館)
- 線上URL編解碼工具 (頁面存檔備份,存於網際網路檔案館)