標籤:can 伺服器 關心 程式崩潰 容器 擴充 actor web伺服器 手寫
前面的話
HTTP報文中可以承載以任何語言表示的內容,就像它能承載映像、影片或任何類型的媒體那樣。對HTTP來說,實體主體只是二進位資訊的容器而已。為了支援國際性內容,伺服器需要告知用戶端每個文檔的字母表和語言,這樣用戶端才能正確地把文檔中的資訊解包為字元並把內容呈現給使用者,而要實現這個功能,需要用到接下來要詳細介紹的字元集
首部概述
伺服器通過HTTP協議的Content-Type首部中的charset參數和Content-Language首部告知用戶端文檔的字母表和語言。這些首部描述了實體主體的“資訊盒子”裡面裝的是什麼,如何把內容轉換成合適的字元以便顯示在螢幕上以及裡面的詞語表示的是哪種語言
同時,用戶端需要告知伺服器使用者理解何種語言,瀏覽器上安裝了何種字母表編碼演算法。用戶端發送Accept-Charset首部和Accept-Language首部,告知伺服器它理解哪些字元集編碼演算法和語言以及其中的優先順序
下面的HTTP報文中的這些Accept首部可能是母語為法語的人發出的。他喜歡使用母語,但也會說一點兒英語,他的瀏覽器支援iso-8859-1 西歐字元集編碼和UTF-8 Unicode字元集編碼
Accept-Language: fr, en;q=0.8 Accept-Charset: iso-8859-l, utf-8
參數“q=0.8”是品質因子(quality factor),說明英語的優先順序(0.8)比法語低(預設值是1.0)
編碼過程
HTTP字元集的值說明如何把實體內容的二進位碼轉換為特定字母表中的字元。每個字元集標記都命名了一種把二進位碼轉換為字元的演算法(反之亦然)。字元集標記在由IANA維護的MIME字元集登錄授權單位進行了標準化。附錄H中概述了其中的很多字元集
下面的Content-Type首部告知接收者,傳輸的內容是一份HTML檔案,用charset參數告知接收者使用iso-8859-6阿拉伯字元集的解碼演算法把內容中的二進位碼轉換為字元:
Content-Type: text/html; charset=iso-8859-6
iso-8859-6的編碼演算法把8位範圍映射為拉丁字母和阿拉伯字母,以及數字,標點和其他符號。例如,在中,反白的二進位碼的值是225,它在iso-8859-6中被映射到阿拉伯字母“FEH”(讀音類似英語字母F)
[注意]與漢語、日語不同的是,阿拉伯語中只有28個字元,8位空間有256個不同的值,足以容納拉丁字元、 阿拉伯字元以及其他符號
有些字元編碼(比如UTF-8和iso-2022-jp)更加複雜,它們是可變長(variable-length)編碼,也就是說每個字元的位元都是可變的。這種類型的編碼允許使用額外的二進位位表示擁有大量字元的字母表(比如漢語和日語),僅用較少的二進位位來表示標準的拉丁字元
我們想把文檔中的二進位碼轉換為字元以便顯示在螢幕上。但由於有很多不同的字母表,也有很多不同的方法把字元編碼成二進位碼(這些方法各有優缺點),我們需要一種標準方法來描述並應用把二進位碼轉換為字元的解碼演算法
把二進位碼轉換為字元要經過兩個步驟,如所示
在圖a中,文檔中的二進位碼被轉換成字元代碼,它表示了特定編碼字元集 中某個特定編號的字元。在這個例子裡,解碼後的字元代碼是數字編號225
在圖b中,字元代碼用於從編碼的字元集中選擇特定的元素。在iso-8859-6中,值225對應阿拉伯字母“FEH”。在步驟a和b中使用的演算法取決於MIME的charset標記
國際化字元系統的關鍵目標是把語義(字母)和表示(圖形化的顯示形式)隔離開來。HTTP只關心字元資料和相關語言及字元集標籤的傳輸。字元形狀的顯示是由使用者的圖形顯示軟體(包括瀏覽器、作業系統、字型等)完成的,c所示
如果用戶端使用了錯誤的字元集參數,用戶端就會顯示一些奇怪的錯亂字元。假設瀏覽器從主體中獲得值225(二進位為11100001)
如果瀏覽器認為主體是用iso-8859-1西歐字元編碼的,它將會顯示帶有重音符號的小寫拉丁字母“a”
如果瀏覽器使用iso-8859-6阿拉伯編碼,它將會顯示阿拉伯字母“FEH”
如果瀏覽器使用iso-8859-7希臘編碼,它將會顯示小寫希臘字母“Alpha”
如果瀏覽器使用iso-8859-8希伯來編碼,它將會顯示希伯來字母“BET”
【標準化的MIME charset值】
特定的字元編碼方案和特定的已編碼字元集組合成一個MIME字元集(MIME charset)。HTTP在Content-Type和Accept-Charset首部中使用標準化的MIME charset標記。MIME charset的值都會在IANA註冊
下表列出了文檔和瀏覽器所使用的一些MIME charset編碼方案
[注意]關於完整的登入字元集內容請移步至此
Web伺服器通過在Content-Type首部中使用charset參數把MIME字元集標記發送給用戶端
Content-Type:text/html; charset=iso-2022-jp
如果沒有顯式地列出字元集,接收方可能就要設法從文檔內容中推斷出字元集。對於HTML內容來說,可以在描述charset的<meta HTTP-EQUIT="Content-Type">標記中找到字元集
下例中展示了HTML META標記如何把字元集設定為日語編碼iso-2022-jp。如果文檔不是HTML類型,或其中沒有META Content-Type標記,軟體可以設法掃描實際的文本,看看能否找出語言和編碼的常見模式,以此推斷字元編碼
<head><meta HTTP-EQUIT="Content-Type" content="text/html;charset=iso-2202-jp"><meta lang="jp"><title>Japanese</title></head>
在過去的幾十年間,人們開發了成千上萬種字元編解碼方法。大多數用戶端不可能支援所有這些不同的字元編碼和映射系統
HTTP用戶端可以使用Accept-Charset請求首部來明確告知伺服器它支援哪些字元系統。Accept-Charset首部的值列出了用戶端支援的字元編碼方案。例如,下面的HTTP請求首部表明,用戶端接受西歐字元系統iso-8859-1和UTF-8變長的Unicode相容系統。伺服器可以隨便選擇這兩種字元編碼方案之一來返回內容
Accept-Charset: iso-8859-1, utf-8
[注意]沒有Content-Charset這樣的響應首部和Accept-Charset請求首部匹配。為了和MIME標準相容,響應的字元集是由伺服器通過Content-Type響應首部的charset參數帶回來的。不對稱真是太糟了,不過需要的資訊倒是都有了
編碼文法
【術語】
以下是應當瞭解的電子化字元系統的8個術語
1、字元
字元是指字母、數字、標點、表意文字(比如漢語)、符號,或其他文本形式的書寫“原子”。由統一字元集(Universal Character Set, UCS,它的非正式的名字是Unicode3)首創,為多種語言中的很多字元開發了一系列標準化的文本名稱,它們常用來便捷地命名字元,而且不會與其他字元衝突
2、字形
描述字元的筆畫圖案或唯一的圖形化形狀。如果一個字元有多種不同的寫法,就有多個字形
3、編碼後的字元
分配給字元的唯一數字編號,這樣我們就可以操作它了
4、代碼空間
計劃用於字元代碼值的整數範圍
5、代碼寬度
每個固定大小的字元代碼所用的位元
6、字元庫
特定的工作字元集,相當於全體字元的一個子集
7、編碼後的字元集
組成字元庫(從全球的字元中選出若干字元)的已編碼字元集,並為每個字元分配代碼空間中的一個代碼。換句話說,它把數字化的字元代碼映射為實際的字元
8、字元編碼方案
把數字化的字元代碼編碼成一系列二進位碼(並能相應地反向解碼)的演算法。字元編碼方案可用來減少識別字元所需要的資料總量(壓縮)、解決傳輸限制、統一重疊編碼字元集
【糟糕的命名】
從技術上說,MIME中的charset標記(用在Content-Type首部的charset參數中和Accept-Charset首部中)描述的壓根就不是字元集。MIME中的charset值所命名的是把資料位元映射為唯一的字元的一整套演算法。它是字元編碼方案(character encoding scheme)和編碼後的字元集(coded character set)這兩種概念的組合
因為關於字元編碼方案和編碼後的字元集方面的標準都已經發布過了,所以,這個術語的使用是很草率的,很容易引起混淆。下面是HTTP/1.1的作者們對於他們如何使用這些術語的介紹
術語“字元集”在本文檔中是指一種方法,它可以把一系列8位位元組轉換為一系列字元。注意:術語“字元集”經常被稱為“字元編碼”。但由於HTTP和MIME共用同樣的註冊資訊,術語也能共用是很重要的
IETF在RFC 2277中也採用了非標準的術語:
本文檔中使用術語“字元集”來表示一組把一系列8位位元組轉換為一系列字元的規則的集合,比如編碼後的字元集與字元編碼方案的組合。這與MIME的“charset=”參數中標識符的用法相同,並且已在IANA的字元集註冊表中註冊。(注意這不是在其他標準主體,比如在國際標準組織ISO中使用的術語)
[注意]更糟糕的是,MIME中的charset標記經常會從特定的編碼後字元集的名稱或編碼方案的名稱裡面選取。例如,iso-8859-1是一個編碼後字元集(它為一個包含256個歐洲字元的集合分配了數字化的代碼),但MIME用charset值iso-8859-1來表示一種8位的、對編碼後的字元集恒等的編碼。這種不精確的術語並不是致命的問題,但在閱讀標準文檔的時候,需要對其假設用法保持清醒的頭腦
因此,在閱讀標準文檔的時候,要保持清醒,這樣才能確切地知道它所定義的到底是什麼
【字元】
字元是書寫的最基本的構建單元。字元可以表示字母、數字、標點、表意符號(比如在漢語中)、數學符號,或其他書寫的基本單元
字元和字型以及風格無關。顯示了同一個字元(UCS中的命名是LATIN SMALL LETTER A)的若干變體。儘管它們的筆畫圖案和風格有很大的不同,但母語是西歐語言的讀者都能立刻辨認出這5個形狀是同一個字元
在很多書面語體系中,根據一個字元在單詞中位置的不同,同一個字元也會有不同的筆畫形狀。例如,中的4種筆畫都表示字元ARABIC LETTER AIN
圖a顯示了AIN作為一個單獨的字元時是如何書寫的。圖d顯示的是AIN在單詞開頭時的情形。圖c顯示了AIN在單詞中間的情形,而圖b顯示的是AIN在單詞結尾處的情形
【字形】
不要把字元和字形混淆。字元是唯一的、抽象的語言“原子”。字形是畫出每個字元時使用的特定方式。根據藝術形式和手法的不同,每個字元可以有很多不同的字形
同樣,也不要把字元與表示形式混淆起來。為了讓書法作品更好看,很多手寫體和字型允許人們把相鄰的字元漂亮地連寫起來,稱為連筆(ligatures),這樣兩個字元就平滑地串連在一起了。母語為英語的作者常把F和I結合為FI連筆,而阿拉伯語的作者常把字元“LAM”和“ALIF”結合為一種很優雅的連筆
這裡給出一般的規則:如果用一種字形替代另一種的時候,文本的意思變了,那這些字形就是不同的字元。否則,它們就是同一個字元的不同風格的表示形式
【編碼後的字元集】
根據RFC 2277和2130的定義,編碼後的字元集把整數映射到字元。編碼後的字元集經常用數組來實現,通過代碼數值來索引。數組的元素就是字元
下面我們來看一些重要的編碼後的字元集標準,包括具有曆史意義的US-ASCII字元集、ASCII的iso-8859擴充、日文的JIS X 0201字元集以及統一字元集(Universal Character Set, Unicode)
1、US-ASCII:所有字元集的始祖
ASCII是最著名的編碼後字元集,早在1968年就由ANSI在標準X3.4,“美國標準資訊交換代碼”(American Standard Code for Information Interchange)中進行了標準化。ASCII的代碼值只是從0到127,因此只需要7個二進位碼就可以覆蓋代碼空間。ASCII的推薦名稱是US-ASCU,這樣可以和那些7位字元集的一些國際化變體區分開來。HTTP報文(首部,URI等)使用的字元集是US-ASCII
2、iso-8859
iso-8859字元集標準是US-ASCII的8位超集,使用二進位碼的高位增加了一些國際化書面字元。由額外的二進位碼提供的附加空間(多了128個代碼)還不夠大,甚至都不夠所有的歐洲字元使用,更不用說亞洲字元了。因此iso-8859為不同地區定製了不同的字元集,如下所示
iso-8859-1 西歐語言(例如,英語、法語)iso-8859-2 中歐和東歐語言(例如,捷克、波蘭)iso-8859-3 南歐語言iso-8859-4 北歐語言(例如,拉托維亞,立陶宛,格陵蘭}iso-8859-5 斯拉夫語(例如,保加利亞、俄羅斯、塞爾維亞)iso-8859-6 阿拉伯語iso-8859-7 希臘語iso-8859-8 希伯來語iso-8859-9 土耳其語iso-8859-10 日耳曼和斯堪的納維亞語言(例如,冰島、因紐特)iso-8859-15 對iso-8859-1的修改,包括了新的歐元字元
iso-8859-1也稱為Latin1,是HTML的預設字元集。可以用它來表示大多數西歐語言的文本。因為iso-8859-15中包含了新的歐元符號,有過一些用它來代替iso-8859-1並作為HTTP預設編碼後字元集的討論。然而,由於iso-8859-1已經被廣泛採用,要大範圍地變更到iso-8859-15恐怕不是短時間內可以完成的
3、JIS X 0201
JIS X 0201是把ASCII擴充到日文半寬片假名字元的一個極小化的字元集。半寬片假名字元最早用在日文電報系統中。JISX 0201常常被稱作JIS Roman,JIS是 “Japanese Industrial Standard”(日文工業化標準)的縮寫
4、JIS X 0208與JIS X 0212
日文中包括數千個來自幾個書面語系統中的字元。儘管可以勉強只使用JIS X 0201中的那63個基本的片假名字元,但實際使用中需要遠比這個更完整的字元集
JIS X 0208字元集是首個多位元組日文字元集,它定義了6879個編碼的字元,其中大多數是來源於中文的日本漢字。JIS X 0212字元集又擴充了6067個字元
5、UCS
UCS(Universal Character Set,統一字元集)是把全世界的所有字元整合到單一的編碼後字元集的環球標準化成果。UCS由ISO 10646定義。Unicode是遵循UCS標準的商業化聯合組織。UCS具有能容納百萬以上字元的代碼空間,不過基本集合只有大約5萬個字元
【字元編碼方案】
字元編碼方案規定如何把字元的代碼數字打封裝入內容位元,以及在另一端如何將其解包回字元代碼
字元編碼方案有以下3種主要類型
1、固定寬度
固定寬度方式的編碼用固定數量的位元表示每個編碼後的字元。它們能被快速處理,但可能會浪費空間
2、可變寬度(無模態)
可變寬度方式的編碼對不同的字元代碼數字採用不同數量的位元。對於常用字元,這樣可以減少需要的位元,而且還能在允許使用多位元組來表示國際性字元的同時,保持對傳統8位字元集的相容性
3、可變寬度(有模態)
有模態的編碼使用特殊的“轉義”模式在不同的模態之間切換。例如,可以用有模態的編碼在文本中使用多個互相有重疊的字元集。有模態的編碼處理起來比較複雜,但它們可以有效地支援複雜的書寫系統
下面我們來看一些常見的編碼方案
1、8位
8位固定寬度恒等編碼把每個字元代碼編碼為相應的8位二進位值。它只能支援有256個字元代碼範圍的字元集。iso-8859字元集家族系列使用的就是8位恒等編碼
2、UTF-8
UTF-8是一種流行的為UCS設計的字元編碼方案,UTF表示UCS變換格式(UCS Transformation Format)。UTF-8為字元代碼值使用的是無模態的變寬編碼,第一位元組的高位表示編碼後的字元所用的位元組數,所需的每個後續位元組都含有6位的代碼值
如果編碼後的第1位元組的最高位是0,長度就是1位元組,剩餘的7位就包含字元的代碼。這樣帶來的美妙結果就是和ASCII相容(但和iso-8859系列不相容,因為iso-8859系列使用了最高位)
例如,字元代碼90(ASCII的“Z”)會被編碼為1個位元組(01011010),而代碼5073(13位二進位值為1001111010001)會被編碼為3個位元組:11100001 10001111 10010001
3、iso-2022-jp
iso-2022-jp是互連網上的日文文檔中廣泛使用的編碼。它是變寬、有模態的,所有值都不超過128,以避免和不支援8位字元的軟體出現相容性問題
編碼上下文始終被設定為4種預設的字元集之一,使用特殊的“逸出序列” (escape sequence)在字元集之間切換。iso-2022-jp的初始狀態使用US-ASCII字元集,使用3個位元組的逸出序列可以切換到JIS X 0201(JIS-Roman)字元集或大得多的JIS X 0208-1978和JIS X 0208-1983字元集
下表中列出了這些逸出序列。實際上,日文文本以ESC @或ESC@或ESC B 開始,以ESC(B或ESC(J結束
在US-ASCII或JIS-Roman模態下,每個字元使用單個位元組。當使用更大的JISX 0208系列的字元集時,每個字元代碼使用2個位元組。該編碼把發送的位元組的範圍範圍限制在33~126之間
4、euc-jp
euc-jp是另一種流行的日文編碼。EUC代表“Extended Unix Code”(擴充Unix代碼),最早是為了在Unix作業系統上支援亞洲字元而開發的
和iso-2022-jp類似,euc-jp編碼也是變長的,允許使用幾種標準的日文字元集。但和iso-2022-jp不同的是,euc-jp編碼不是模態的。沒有逸出序列可以在不同模態之間切換
euc-jp支援4種編碼後的字元集:JIS X 0201(JIS-Roman,對ASCII進行一些日文替換)、JIS X 0208、半寬片假名(最早在日文電報系統中使用的63個字元)以及JIS X 0212
編碼JIS Roman(它和ASCII相容)的時候使用1個位元組,對JIS X 0208和半寬片假名則使用2個位元組,而對JIS X 0212使用3個位元組。這種編碼有點浪費空間但處理起來很簡單
下表概括了此編碼的格局
語言標記
語言標記是命名口語的標準化字串短語
名字需要標準化,不然的話,有些人會把法語文檔打上French標記,而有些其他人會用Francis,還有些人可能會用France,更有些懶人可能會用Fra甚至是F。標準化語言標記就可以避免這些混亂
英語的標記是en,德語的標記是de,韓語的標記是ko,等等。語言標記能夠描述語言的地區變種和方言,比如巴西葡萄牙語的標記是pt-BR、美式英語的標記是en-US,漢語中的湖南話的標記是zh-xiang。甚至還有個標準語言標記i-klingon是描述克林根語的
實體的Content-Language首部欄位描述實體的目標受眾語言。如果內容主要是給法語受眾的,其Content-Language首部欄位就將包含:
Content-Language:fr
Content-Language首部不僅限於文字文件。音頻片段、電影以及應用程式都有可能是面向特定語言受眾的。任何面向特定語言受眾的媒體類型都可以有Content-Language首部。在中,音頻檔案標記為面向納瓦霍(Navajo)聽眾
如果內容是面向多種語言受眾的,可以列出多種語言。就像在HTTP規範中建議的,一份同時用英語和毛利語寫的“Treaty of Waitangi”(懷唐伊條約)譯稿,可以這樣描述:
Content-Language:mi, en
不過,不能僅根據有多種語言在實體中出現就認為它是面向多種語言受眾的。為初學者編寫的語言入門教材,比如“A First Lesson in Latin”(拉丁語第一課),顯然是為英語受眾準備的,應當只用en來描述
我們絕大多數人至少懂一種語言。HTTP允許我們把語言方面的限制和優先選擇都發送給網站伺服器。如果網站伺服器有以多種語言表示的資源版本,它就能把內容用我們最優選的語言表示出來
用戶端請求西班牙語內容:
Accept-Language:es
可以在Accept-Language首部中放入多個語言標記以枚舉所支援的全部語言及其優先順序(從左至右)。用戶端首選英語,但也接受瑞士德語(標準語言標記是de-CH)或其他德語變種(標記是de):
Accept-Language:en, de-CH, de
用戶端使用Accept-Language首部和Accept-Charset首部請求可以理解的內 容
在RFC 3066,“Tags for the Identification of Languages”(標識語言的標記)中記錄了語言標記的標準化文法。可以用語言標記來表示:一般的語言分類(比如es代表西班牙語);特定國家的語言(比如en-GB代表英國英語);語言的方言(比如no-bok指挪威的書面語);地區性的語言(比如sgn-US-MA代表美國馬撒葡萄園島上的手語);標準化的非變種語言(比如i-navajo);非標準的語言(比如 x-snowboarder-slang)
語言標記有一個或多個部分,用連字號分隔,稱為子標記:
第一個子標記稱為主子標記,其值是標準化的;第二個子標記是可選的,遵循它自己的命名標準;其他尾隨的子標記都是未註冊的
主子標記中只能含有字母(A-Z)。其後的子標記可以含有字母和數字,長度最多8個字元
中給出了一個樣本
所有的標記都是不區分大小寫,也就是說,標記en和eN是等價的。但是,習慣上用全小寫來表示一般的語言,而用全大寫來表示特定的國家。例如,fr表示所有分類為法語的語言,而FR表示國家法國
第一個和第二個語言子標記的值由各種標準文檔以及相關的維護組織定義。IANA依據RFC 3066中概括的規則來管理標準的語言標記列表
如果語言標記由標準的國家和語言值組成,標記就不需要專門註冊。只有那些無法用標準的國家和語言值構成的語言標記才需要專門向IANA註冊
第一個子標記通常是標準化的語言記號,選自ISO 639中的語言標準集合。不過也可以用字母i來標識在IANA中註冊的名字,或用x表示私人的或者擴充的名字,下面是各種規則
如果第一個子標記含有2個字元,那就是來自ISO 639和639-1標準的語言代碼;如果含有3個字元,那就是來自ISO 639-223標準及其擴充的語言代碼;如果是字母i,則表示該語言標記是在IANA顯式註冊的;如果是字母x,則表示該語言標記是私人的、非標準的,或擴充的子標記
下表中給出了一些樣本
第二個子標記通常是標準化的國家記號,選自ISO 3166中的國家代碼和地區標準集合。不過也可以是在IANA註冊過的其他字串,下面是各種規則。
如果第二個子標記含有2個字元,那就是ISO 3166中定義的省/地區;如果含有3-8個字元,可能是在IANA中註冊的值;如果是單個字元,這是非法的情況
下表中列出了ISO 3166中的部分國家代碼
除了最長可以到8個字元(字母和數字)之外,第三個和其後的子標記沒有特殊規則
國際化URI
直到今天,URI還沒有為國際化提供足夠的支援。除了少數(定義得很糟的)例外,URI如今還是由US-ASCII字元的一個子集組成的。人們正在努力使主機名稱和URL的路徑中能包含更豐富的集合中的字元,但直到現在,這些標準還沒有被廣泛接受和部署
URI的設計者們希望世界上每個人都能通過電子郵件、電話、公告板,甚至無線電來共用URI。他們還希望URI容易使用和記憶,但這兩個目標是相互衝突的
為了讓世界各地的人們都能夠便捷地輸入、操控,以及共用URI,設計者們為URI選擇了常用字元的一個很有限的子集(基本的拉丁字母表中的字母、數字以及少數特殊符號)。世界上絕大多數軟體和鍵盤都支援這個小的字元集合
但不幸的是,限制了字元集的話,URI就無法被全球的人們方便地使用和記憶。世界上有很大一部分人甚至都不認識拉丁字母,他們幾乎無法把URI當作抽象模式來記憶
URI的設計者們覺得確保資源標識符的可轉抄能力(transcribability)和共用能力比讓它們由最有意義的字元組成更加重要。因此,如今的URI基本上是由ASCII字元的受限子集構成的
URI中允許出現的US-ASCII字元的子集,可以被分成保留、未保留以及逸出字元這幾類。未保留的字元可用於URI允許其出現的任何部分。保留的字元在很多URI中都有特殊的含義,因此一般來說不能使用它們
下表中列出了全部未保留、保留,以及逸出字元
【轉義】
URI轉義提供了一種安全的方式,可以在URI內部插入保留字元以及原本不支援的字元(比如各種空白)。每個轉義是一組3字元序列,由百分比符號(%)後面跟上兩個十六進位數位字元。這兩個十六進位數字就表示一個US-ASCII字元的代碼
例如,要在URL中插入一個空白(ASCII 32),可以用轉義%20,因為20是32的十六進位表示。類似地,如果想插入一個百分比符號並且不想讓它被當作轉義,就可以輸入%25,25是百分比符號的ASCII代碼的十六進位值
展示了URI中的概念性字元是如何轉換為當前字元集中字元的代碼位元組的。需要處理URI時,轉義會被反轉義回來,產生它們代表的ASCII代碼的位元組
在內部處理時,HTTP應用程式應當在傳輸和轉寄URI的時候保持轉義不變。HTTP應用程式應該僅在需要資料的時候才對URI進行轉義。更重要的是,應用程式應該確保任何URI都不會被反轉義2次,因為在轉義的時候可能會把百分比符號編碼進去,反轉義出來之後,再轉一次就會導致資料丟失
需要注意的是,要轉義的值本身應該在US-ASCII代碼值的範圍內(0~127)。某些應用程式試圖用轉義值來表示iso-8859-l中擴充的字元(代碼範圍在128-
255)。例如,網站伺服器可能會錯誤地用轉義來對包含了國際字元的檔案名稱進行編碼。這樣做是不對的,可能會使別的應用出問題
例如,檔案名稱Sven Olssen.html(包含了一個母音變音)可能被網站伺服器編碼為 Sven%20%D6lssen.html。把空格編碼為%20是對的,但從技術上說,把O編碼為%D6是非法的,因為代碼D6(十進位值214)落在了ASCII代碼範圍之外。ASCII只定義了最大值為0X7F(十進位值127)的代碼
【模態切換】
有些URI也用ASCII字元的序列來表示其他字元集中的字元。例如,可能使用iso-2022-jp編碼插入“ESC(J”,切換到JIS-Roman字元集,用“ESC(B”切換回ASCII字元集。這在一些本地化的環境中可以工作,但這種方式沒有進行良好的定義,而且沒有標準化的方案來識別URL所使用的特定編碼。正如RFC 2396的作者所說的那樣:
對於含有非ASCII字元的原始字元序列來說,境況複雜。如果可能用到多個字元集的活,傳輸表示字元序列的8位位元組序列的網際網路協議期待能有辦法來識別所用的字元集[RFC 2277]
然而,在通用的URI文法中沒有提供進行這種識別的手段。個別的URI方案可以請求單一的字元集,定義預設的字元集,或提供指示所用字元集的方法。期待將來對這個規範的修改能為URI中的字元編碼提供一種系統化的處理方案
目前,URI對國際化應用還不是非常友好。URI的可移植性目標比語言靈活性方面的目標更重要。人們正在盡最大努力使URI更加國際化,但在短期內,HTTP應用程式還是應當堅持使用ASCII。它從1968年就出現了,所以只用它的話,一切還不至於太糟
注意事項
HTTP首部必須由US-ASCII字元集中的字元構成。不過,並不是所有的用戶端和伺服器都正確地實現了這一點,可能會時不時收到一些代碼值大於127的非法字元
很多HTTP應用程式使用作業系統和庫常式來處理字元(比如Unix中的字元分類庫ctype),但不是所有這些庫都支援ASCII範圍(0-127)之外的字元代碼
在某些情況下(一般來說,是較老的實現),當輸入非ASCII字元時,這些庫可能會返回不正確的結果,或者使應用程式崩潰。假設報文中含有非法資料,在使用這些字元分類庫來處理HTTP報文之前,要仔細閱讀它們的文檔
HTTP的規範中明確定義了合法的GMT日期格式,但要知道並非所有Web伺服器和用戶端都遵守這些規則。例如,我們曾見過Web伺服器發送的無效HTTP Date(日期)首部中的月份是用本地語言表示的
HTTP應用程式應當嘗試容忍一些不合規矩的日期,不能在接收的時候崩潰。不過也不是所有發送出來的日期都能被正確解釋,如果日期無法解析,伺服器應當謹慎處理
DNS目前還不支援在網域名稱中使用國際化的字元。現在進行中支援多語言的網域名稱的相關標準化工作,但還沒有被廣泛部署
前端學HTTP之字元集