3協議參數
3.1HTTP版本
HTTP使用一個“<major>.<minor>”模式來標志協議版本。協議版本就是要允許發送者表達message格式的信息以及它理解更多HTTP協議的能力(不只是說通訊的功能)。加了不影響通訊行為的MESSAGE組件或加了擴展的域值都不必改變版本號。<minor>增大表示協議被改變,一般的MESSAGE解析算法沒有變,但是增加了MESSAGE語義也就增加了發送者額外的功能。<major>增大如果MESSAGE的格式改變了。
HTTPmessage的HTTP版本在MESSAGE的頭一行的版本域中被表示。
HTTP-Version =”HTTP””/”1*digit”.”1*DIGIT
注意major和minor數每一個都可以獨立對待。因此HTTP/2。4比HTTP/2。13低,而HTTP/2。4又比HTTP/12。3低。前面的0必須被接收者忽略而發送者千萬不要發。
一個發送包含“HTTP/1。1”版本的request或response信息必須最少與這個規范條件兼容。而一個和這個規范最少條件兼容的應用應該在他們的MESSAGE中標明HTTP/1。1版本,并且對于于HTTP/1。0不兼容的MESSAGE必須標明HTTP/1。1版本。關于什么時候送規范的HTTPV值更多細節看RFC2145[36]。
應用的HTTP版本是應用最少條件兼容的最高HTTP版本。
Proxy和gateway應用需要仔細對待轉發不同于自身應用版本的message。因為過來的MESSAGE中的HTTP版本代表了發送者的協議能力,一個PROXY/GATEWAY千萬不要發送一個高于該版本的MESSAGE。相反,如果接受了一個更高版本也不要減低或報錯或轉向TUNNEL行為。
RFC2068[33]發布時發現了與HTTP/1。0proxy交互時出現的問題,緩存proxy必須,gateway可以,tunnel千萬不要升級request到他們支持的最高版本。Proxy和gateway的Response必須和那個request保持同一個版本。
注意:在HTTP版本間的轉換可能包含頭區某域的改變,而這些改變可能被要求或被拒絕。
3.2統一資源定位符
關于URI以前出現的名稱有:WWW地址,通用文檔標志,通用資源標志,最后,代表URL和URN的組合。只要和HTTP相關,URI就是一個簡單的格式化字符串,通過名稱,地址或其他特征來標志一個資源。
3.2.1普通語法
在HTTP中URI可以以一個絕對的形式表現或相對于一些知道的基本的URI,這取決于使用的上下文。這兩種形式被區分于:絕對的URI總是以一個模式名稱跟一個冒號開始。關于URL的詞法和語法的絕對定義信息,需要看“Uniform Resource Identifiers (URI): Generic Syntax and Semantics,” RFC 2396 [42](取代了RFCs1738[4]和RFC1808[11]);而其中的部分定義“URI-reference”, “absoluteURI”, “relativeURI”,“port”, “host”,“abs_path”, “rel_path”, 和 “authority”在本規范中也被使用。
HTTP協議并沒有對URI的長度有一個預先的限制。服務器必須能夠處理任何他們提供資源的響應URI,而且應該能夠處理無限長度的URI,如果他們提供基于GET的表達形式。一個服務器應該返回414如果一個URI比服務器能處理的URI還長的話。
注意:服務器應該小心對待長度超過255個字節的URI,因為一些老client和proxy實現可能不支持這些長度。
3.2.2http URL
“http”模式被用來通過HTTP協議定位網絡資源。下面為httpURL定義了模式化的詞法和語法.
http_URL = "http:" "http://" host [ ":" port ] [ abs_path [ "?" query ]]
如果端口空或為給出,使用80。語法就是,資源所在的server在host的port端口監聽tcp連接,而abs_path指定了請求資源的Request-URI。IP地址的使用只要有可能就應該被避免(RFC1900[24])。如果abs_path沒有出現在URL中,它必須作為“/”作為Request-URI(SEC5。1。2)。如果一個代理接受到不完全domain名稱的主機名稱,它可以用它自己的domain名稱加進去;如果接受到完整的,則不能改變主機名稱。
3.2.3URI比較
當把兩個URI比較以決定他們是否匹配,一個client應該采用大小寫敏感地字節對應字節地方式比較整個URI,下面除外:
端口默認為80,有沒有相同
host名稱必須大小寫不敏感
模式名稱必須大小寫不敏感
一個空的abs_path等同于一個“/”的abs_path
不在“reserved” and “unsafe”字符集里的字符等價與“% HEX HEX”編碼。例如
http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html
等價的。
3.3Data/Time 格式
3.3.1完整日期
HTTP應用歷史上允許3中不同的DATE/TIME表示:
Sun,
Sunday, 06-Nov-94
Sun Nov 6
第一種多用于INTERNET標準并且代表了RFC1123[8](RFC822[9]的更新)的固定長度子集。
第二種被普遍使用,但是基于被廢棄的RFC850[12]日期格式并且缺少年度的4位表示。HTTP/1.1clients 和server解析date值就必須接受所有3種格式,雖然必須的是在HTTP頭區按RFC1123產生日期值。SEC19.3。
注意:date值的接收程序被鼓勵可以接受非HTTP應用發的DATE值,這種情況經常出現在通過SMTP/NNTP的代理或網關接收或發送信息。
3.2.2 delta秒
一些HTTP頭區允許一個時間值被一個秒的整數值來表示,十進制,在message被接收到之后。
3.4 字符集
HTTP使用MIME描述的相同定義來定義字符集。
在這篇文檔中,術語字符集指使用一個或多個表把一組字節碼轉換成一組字符的方法。注意相反方向的無限制的轉化不是必需的,并不是所有的字符都在一個給定字符集中,并且一個字符集可以提供多個字節碼組合來代表一個指定字符。這個定義用來允許多種字符編碼,從簡單的單表映射如US-ASCII到復雜表的轉化如ISO-2022技術。但是,和MIME字符集名稱定義相關的定義必須完整地明確從字節碼到字符的映射。具體地說,使用外面的相關信息來確定精確映射是不允許的。
注意:更常使用字符編碼來指字符集。但是因為HTTP和MIME使用相同的登記,所以術語最好統一起來。
HTTP字符集用大小寫不敏感的標記來標志。完整的標記組合由IANACharacter Set registry [19]來定義。
Charset=token
雖然HTTP允許任意的TOKEN,凡是IANA Character Set registry [19]中定義的組合值必須代表其中注冊的字符集。應用應該僅使用那些在IANA登記中的字符集。
實現者要意識到IETF[38][41]。
3.4.1沒有CHARSET
一些HTTP/1。0軟件認為沒有CHARSET參數的CONTENT-TYPE頭應該“由接收者來猜”。這并不正確。發送者如果要阻止這種行為應該包含一個參數即使字符集是ISO-8859-1而且如果不會迷惑接收者也應該這樣做。
不幸的是一些更老的HTTP/1。0CLIENT不能合適地處理CHARSET參數。HTTP/1。1接收者必須采用發送者提供的該參數;而且那些可以猜的用戶端初始展示一個文檔時也必須使CONTENT-TYPE區里的字符集,而不是自己愛咋咋地。
3.5內容編碼
內容編碼值來指示一個可以被用到一個ENTITY上的編碼轉換。內容編碼主要被使用來允許一個文檔被壓縮或不丟失媒體類別信息和其他信息的轉化。ENTITY被編碼地存儲,直接發送,然后只被接收者解碼。
content-coding = token
token是大小寫不敏感的。HTTP/1。1在Accept-Encoding(section 14.3)和Content-Encoding (section 14.11)使用該值。盡管該值描述了內容編碼,更重要的是它指定了什么樣的解碼是合適的。
IANA登記了內容編碼值。起初,登記包含了下面這些標記:
Gzip 一個編碼樣式,由文件壓縮程序GZIP(GNU ZIP)提供,RFC1952[25]描述。這個格式是LZ77和32CRC編碼。
Compress
有UNIX文件壓縮程序“compress”來提供。格式是LZW編碼。
使用程序名字來標志編碼格式并不理想,也將在未來的編碼中被取代。在這里使用是歷史的原因,并不是個好設計。為了向前兼容,一個應用應該把“x-zip”和“x-compress“認為和”gzip“”compress”認為是各自相同的。
Deflate
“zlib“(RFC1950[3]定義)和”deflate“壓縮機制(RFC1951[29]定義)的組合。
Identity
默認的編碼;沒有轉化的轉化。只在Accept-Encoding頭中使用,不應在Content-Encoding中使用。
新的內容編碼值應該被登記;為了允許交互性,對新值的內容編碼算法應該是可公共使用并足夠用來獨立實現,并且要滿足內容編碼存在的初衷。
3.6傳輸編碼
傳輸編碼被用來指示一個用來保證ENTITY穿越網絡安全傳輸的編碼。它是MESSAGE的一個屬性并不是原始的ENETITY的。
transfer-coding = "chunked" | transfer-extension
transfer-extension = token *( ";" parameter )
parameter以屬性值對的形式存在。
parameter = attribute "=" value
attribute = token
value = token | quoted-string
所有的傳輸編碼值是大小寫不敏感的。HTTP/1。1在TE(sec14.39)和Transfer-Encoding(SEC14。41)中使用。
只要一個傳輸編碼被應用在一個MESSAGE-BODY中,該編碼集合必須包含“CHUNKED“,除非message因關閉連接而結束。當”chunked“被使用,他必須是對MESSAGE-BODY的最后的編碼。絕對不能用兩次。靠這個接受者可以決定MESSAGE的傳輸長度(SEC4。4)。
MEME[7]的Content-Transfer-Encoding值,用來通過7位傳輸服務來實現2進制數據安全傳輸。雖然傳輸編碼類似于這種安全傳輸,但是,安全傳輸在8位傳輸協議有一個不同的焦點。在HTTP傳輸中不安全的問題主要在決定BODY的長度和加密數據。
IANA登記了傳輸編碼值。最初,包含“chunked” (section 3.6.1), “identity” (section 3.6.2), “gzip” (section3.5), “compress” (section 3.5), and “deflate” (section 3.5)。新登記也應該和內容編碼一樣登記。
一個server,如果接收了無法處理的傳輸編碼,應該返回501,并且關閉連接。一個server絕對不能發給HTTP1。0客戶端傳輸編碼。
3.6.1大塊的傳輸編碼
修改BODY改成一塊一塊的序列,每一個帶大小指示,帶一個可選的尾部,里面有ENTITY-HEADER區。這允許動態地產生的內容也被接收者識別組裝好。
Chunked-Body = *chunk
last-chunk
trailer
CRLF
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
chunk-size區是十六進制數字用來表示塊的大小。編碼以一個大小為0,跟著一個空行結束的尾部的塊來作為結束。
尾部允許發送者來在MESSAGE結束出包括額外的HTTP頭區。而TRAILER頭區可以用來知識哪個頭區被包含在了一個尾部(SEC14。40)
一個server如果使用塊傳輸編碼,決不能為頭區使用尾部,除非下面至少一個是真的。
a)request包含一個TE頭區,指示在response的傳輸編碼中尾部是可以接受的。
b)server是response的origin server,尾部整個由可選元數據,而接收者可以不接收這些元數據也能使用MESSAGE。換句話說,ORIGIN SERVER愿意接收在client傳遞過程中尾部被割掉的信息。
這個要求阻止了一些通過了HTTP/1。1(或更高版本)而被HTTP/1。0接收時出現的交互錯誤。這樣就不會強于要求代理實現一個無限大小的緩存。
App19.4.6展示了一個解碼Chunked-Body的例程。
所有的HTTP/1。1應用必須能夠接收并解碼CHUNKED傳輸編碼,并且必須忽略他們不理解的chunk-extension擴展。
3.7媒體類型
HTTP使用IMT[17]在Content-Type (section 14.17) and Accept (section 14.1) 頭區中提供開放和靈活擴展的數據類型和類型交互。
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token
參數可以以attribute/value的形式來跟隨type/subtype
ype, subtype, 和 parameter屬性名稱都是大小寫不敏感的。參數值可以是或不是到小寫敏感,這取決于參數名稱對應的語法。LWS決不能在type和subtype之間被使用,也不能在attribute和它的value之間使用。參數的存在與否可能會對media-type的處理有很重要的意義,這取決于其在登記中的定義。
注意一些老的HTTP應用不會認出該媒體類型參數。當發送數據給這些應用時,實現應該只使用那些被定義要求使用的TYPE/SUBTYPE。
MEDIA-TYPE在(IANA [19])中定義。登記過程在RFC1590[17]中被概括。使用非登記的media tyoe是不提倡的。
3.7.1標準化和默認文本
國際媒體類型用一個標準形式登記。一個entity-body在通過HTTPmessage傳遞前必須作為相應的標準形式存在。 “text”類型例外,我們將在下一段說明。
在標準形式下,“text”的子類使用CRLF作為文本行的連接。HTTP放松了這個要求,允許在一個完整的entity-body中始終用“CR”或“LF”單獨代表行連接。HTTP應用對于通過HTTP接收到的文本必須能夠使用CRLF,CR,LF作為行連接的代表。另外,如果文本使用的字符集并不使用13,10代表CR,LF,就象在一些多字節字符集那樣,那么,HTTP允許使用其對應的字節碼代表該字符。這種靈活性
3.7.2多部分類型
MIME提供了許多“multipart”類型—用一個message封裝一個或多個entity。所有的multipart共享一個公共的語法(sec5.1.1-RFC2046[40]),并且必須包含一個分界參數作為media類型值的一部分。Message本身是一個協議元素因此必須進使用CRLF去作為跨BODY-PART的行繼續標志。不同于在RFC2046,任何多部分類型的MESSAGE的尾部必須是空的;HTTP應用絕對不能傳遞尾部。(即使原先的多部分包含一個尾部)。這個限制的存在是為了保持多部分消息體的自分界性質,就是信息體的結束使用多部分的結束作為結束。
一般情況下,HTTP對于一個多部分消息體是和其他的一樣嚴格作為有效負荷處理的。有個例外是“multipart/byteranges”(appendix19.2)當它出現在206response中時,會被一些HTTP緩存機制象在sec13.5.4和14.16中描述地那樣處理。在其他情況下,一個HTTPuser agent 應該類似于一個MIME用戶接收一個多類型那樣處理。除了那些在MIME語義中定義的那些,在每個多部分消息體中的MIME頭區對于HTTP沒有任何意義。
一般情況下,一個HTTPuser agent應該象MIME一樣處理多部分類型。如果一個應用接受到一個不認識的multipart subtype,它必須把它等同與“multipart/mixed”處理。
注意:“multipart/form-data”已經被明確定義用來通過POST方法傳遞表單數據,RFC1867[15]。
3.8產品標記
產品標記被用來允許通訊應用來通過軟件名稱和版本來標志他們自己。大多數使用產品標記的區也使用子產品來形成被列出的應用的重要組成部分,它們以空格分開。按照其重要程度來有序列出。
product = token ["/" product-version]
product-version = token
例如:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4
產品標記應該言短意賅。它們絕對不能被用來做廣告或其他不重要的信息。雖然任何的標記字符可以出現在一個product-version里,這些個字符應該只用來標記版本。(例如,接續的版本好應該只在產品版本部分不同)。
3.9屬性值
HTTP content negotiation(SEC12)使用短浮點數來標記各種negotiable參數的重要性(權重)。一個權重回被標準化成一個>0并且<1的數。如果一個參數是0的質量值,那這個參數的內容是不被客戶端所接受的。HTTP/1。1應用絕對不能產生多于小數點后3位的數。用戶對他們的值的配置也應該限于此
qvalue = ( "0" [ "." 0*3DIGIT ] )
| ( "1" [ "." 0*3("0") ] )
其實這個名字本身容易引起誤解,因為其值僅僅代表要求質量的相對級別。
3.10語言標記
一個語言標記被用來標志人們說的語言。當然計算機語言肯定不被包含在內。HTTP在Accept-Language 和 Content-Language區使用語言標記。
HTTP語言標記的語法和登記和RFC1766[1]定義的類似。總之,一個語言標記是由1或多個部分組成:一個主語言標記和一個可能的空子標記序列:
language-tag = primary-tag *( "-" subtag )
primary-tag = 1*8ALPHA
subtag = 1*8ALPHA
空格在標記中不被允許并且所有的標記都是大小寫不敏感的。語言標記命名空間在IANA中管理。例如:
en, en-US, en-cockney, i-cherokee, x-pig-latin
任何2字母的主標記是一個ISO-639語言縮寫,而任何2字母的初始子標記是一個ISO-3166國家碼。(后3個沒有登記,最后一個不會被允許)。
3.11實體標記
實體標記用來比較來自相同的去請求資源的兩個或多個實體。HTTP/1。1在ETag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), 和If-Range
使用實體標記。
如何定義以及怎么作為緩存校驗來比較在sec13.3.3中描述。
entity-tag = [ weak ] opaque-tag
weak = "W/"
opaque-tag = quoted-string
如果同一資源的兩個ENTITY具有相同的位集可以共享“strong entity tag”。
而由一個"W/" 前綴表示的“weak entity tag”標記的tag,如果是相等的并可以在語義上無修改地互相取代,那么可以共享一個標記。只能用來弱比較。
在一個給定resource中的對應實體必須保持實體標記具有唯一性。但是如果是不同URI得到的實體可以有相同標記值,但不表示這些實體是等價的。
3.12范圍單位
HTTP/1。1允許一個client只是response實體的部分被包含在response中。HTTP/1。1在Range (section 14.35) 和Content-Range (section 14.16)中使用范圍單位。一個實體能夠根據各種結構單位分成多個范圍
range-unit = bytes-unit | other-range-unit
bytes-unit = "bytes"
other-range-unit = token
在HTTP/1。1定義的唯一的范圍單位是”byte”。HTTP/1。1的實現可以忽略其他范圍定義。HTTP/1。1被設計成允許那些不必知道范圍單位的應用的存在。