前端学HTTP之字符集
前面的話
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-6iso-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 $ 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:frContent-Language首部不僅限于文本文檔。音頻片段、電影以及應用程序都有可能是面向特定語言受眾的。任何面向特定語言受眾的媒體類型都可以有Content-Language首部。在下圖中,音頻文件標記為面向納瓦霍(Navajo)聽眾
如果內容是面向多種語言受眾的,可以列出多種語言。就像在HTTP規范中建議的,一份同時用英語和毛利語寫的“Treaty of Waitangi”(懷唐伊條約)譯稿,可以這樣描述:
Content-Language:mi, en不過,不能僅根據有多種語言在實體中出現就認為它是面向多種語言受眾的。為初學者編寫的語言入門教材,比如“A First Lesson in Latin”(拉丁語第一課),顯然是為英語受眾準備的,應當只用en來描述
我們絕大多數人至少懂一種語言。HTTP允許我們把語言方面的限制和優先選擇都發送給網站服務器。如果網站服務器有以多種語言表示的資源版本,它就能把內容用我們最優選的語言表示出來
客戶端請求西班牙語內容:
Accept-Language:es可以在Accept-Language首部中放入多個語言標記以枚舉所支持的全部語言及其優先順序(從左到右)??蛻舳耸走x英語,但也接受瑞士德語(標準語言標記是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目前還不支持在域名中使用國際化的字符。現在正在進行支持多語言的域名的相關標準化工作,但還沒有被廣泛部署
?
轉載于:https://www.cnblogs.com/xiaohuochai/p/6195941.html
總結
以上是生活随笔為你收集整理的前端学HTTP之字符集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL Server-表表达式基础回顾(
- 下一篇: 前端小技巧-定位的活学活用之仿淘宝列表