轉自:http://www.cnblogs.com/k1988/archive/2010/01/12/2165683.htmlhtml
說明前端
本文檔規定了互聯網社區的標準組協議,並須要討論和建議以便更加完善。請參考web
「互聯網官方協議標準」(STD 1)來了解本協議的標準化狀態。本協議不限流傳發布。算法
版權聲明數據庫
Copyright (C) The Internet Society (1999). All Rights Reserved.瀏覽器
摘要緩存
超文本傳輸協議(HTTP)是一種爲分佈式,合做式,超媒體信息系統。它是一種通用的,無狀態(stateless)的協議,除了應用於超文本傳輸外,它也能夠應用於諸如名稱服務器和分佈對象管理系統之類的系統,這能夠經過擴展它的請求方法,錯誤代碼和報頭[47]來實現。HTTP的一個特色是數據表現形式是可輸入的和可協商性的,這就容許系統能被創建而獨立於數據傳輸。 安全
HTTP在1990年WWW全球信息剛剛起步的時候就獲得了應用。本說明書詳細闡述了HTTP/1.1 協議,是RFC 2068的修訂版[33]。服務器
目錄(略)網絡
1 引論
1.1 目的
超文本傳輸協議(HTTP)是一種爲分佈式,合做式,多媒體信息系統服務,面向應用層的 協議。在1990年WWW全球信息剛剛起步的時候HTTP就獲得了應用。HTTP的第一個版本叫作HTTP/0.9,是一種爲互聯網原始數據傳輸服務的簡單協議。由RFC 1945[6]定義的HTTP/1.0進一步完善了這個協議。它容許消息以相似MIME的格式傳送,包括有關數據傳輸的維護信息和關於請求/響應的句法修正。可是,HTTP/1.0沒有充分考慮到分層代理,緩存的做用以及對穩定鏈接和虛擬主機的需求。而且隨着不完善的應用程序的激增,HTTP/1.0迫切須要一個新的版本,以便使兩個通訊應用程序可以肯定彼此的真實性能。
這裏規定的協議叫作擧TTP/1.1".這個協議與HTTP/1.0相比,要求更爲嚴格,以確保各項功能獲得可靠實現。
實際的信息系統除了簡單的檢索外,要求更多的功能性(functionality),包括查找(search),前端更新(front-end update)和註解(annotation)。HTTP容許可擴充的方法集和報頭集以指示請求的目的[47]。它是創建在統一資源標識符(URI)[3]提供的地址(URL)[4]和名字(URN)上[20],以指出方法應用於哪一個資源的。消息以相似於一種叫作多用途網絡郵件擴展(MIME)[7] 的互聯網郵件的格式傳送。
HTTP也是用於用戶代理之間及代理/網關到其餘網絡系統的通用通訊協議,這樣的網絡系統可能由SMTP[16],NNTP[13],FTP[18],Gopher[2]和WAIS[10]協議支持。這樣,HTTP容許不一樣的應用程序對資源進行基本的超媒體訪問。
1.2 要求
本文的關鍵詞"MUST", "MUST NOT", "REQUIRED", "SHALL","SHALL NOT","SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 和 "OPTIONAL"將由RFC 2119[34]解釋。
一個應用程序若是不能知足協議提供的一個或多個MUST或REQUIRED等級的要求,是不符合要求的。一個應用程序若是知足全部MUST或REQUIRED等級以及全部SHOULD等級的要求,則被稱爲非條件遵循(unconditionally compliant)的;若知足全部MUST等級的要求但不能知足全部SHOULD等級的要求則被稱爲條件遵循的(conditionally compliant)。
1.3 術語
本說明用到了若干術語,以表示HTTP通訊中各參與者和對象扮演的不一樣角色。
鏈接(connection)
爲通訊而在兩個程序間創建的傳輸層虛擬電路。
消息(message)
HTTP通訊中的基本單元。它由一個結構化的八比特字節序列組成,與第4章定義的句法相匹配,並經過鏈接獲得傳送。
請求(request)
一種HTTP請求消息,參看第5章的定義。
響應(response)
一種HTTP響應消息,參看第6章的定義。
資源(resource)
一種網絡數據對象或服務,能夠用第3.2節定義的URI指定。資源能夠以多種表現方式(例如多種語言,數據格式,大小和分辨率)或者根據其它方面而而不一樣的表現形式。
實體(entity)
實體是請求或響應的有效承載信息。一個實體包含元信息和內容,元信息以實體頭域(entity-header field)形式表示,內容以消息主體(entity-body)形式表示。在第7節詳述。
表現形式 (representation)
一個響應包含的實體是由內容協商(content negotiation)決定的。如第12章所述。有可能存在一個特定的響應狀態碼對應多個表現形式。
內容協商(content negotiation)
當服務一個請求時選擇資源的一種適當的表示形式的機制(mechanism),如第12節所述。任何響應裏實體的表現形式都是可協商的(包括出錯響應).
變量(variant)
在任何給定時刻,一個資源對應的表現形式(representation)能夠有一個或多個(譯註:一個URI請一個資源,但返回的是此資源對應的表現形式,這根據內容協商決定)。每一個表現形式(representation)被稱做一個變量。使用變量這個術語並非意味着資源(resource)是必須由內容協商決定的.
客戶端(client)
爲發送請求創建鏈接的程序.
用戶代理(user agent)
初始化請求的客戶端程序。常見的如瀏覽器,編輯器,蜘蛛(網絡穿越機器人),或其餘的終端用戶工具.
服務器(Server)
服務器是這樣一個應用程序,它贊成請求端的鏈接,併發送響應(response)。任何給定的程序都有可能既作客戶端又作服務器;咱們使用這些術語是爲了說明特定鏈接中應用程序所擔當的角色,而不是指一般意義上應用程序的能力。一樣,任何服務器均可以基於每一個請求的性質扮演源服務器,代理,網關,或者隧道等角色之一。
源服務器(Origin server)
存在資源或者資源在其上被建立的服務器(server)被成爲源服務器(origin server)。
代理( Proxy)
代理是一箇中間程序,它既擔當客戶端的角色也擔當服務器的角色。代理表明客戶端向服務器發送請求。客戶端的請求通過代理,會在代理內部獲得服務或者通過必定的轉換轉至其餘服務器。一個代理必須能同時實現本規範中對客戶端和服務器所做的要求。透明代理(transparent proxy)須要代理受權和代理識別,但不修改請求或響應。非透明代理(non-transparent proxy)需修改請求或響應,以便爲用戶代理(user agent)提供附加服務,附加服務包括組註釋服務,媒體類型轉換,協議簡化,或者匿名過濾等。除非透明行爲或非透明行爲經明確指出,不然,HTTP代理既是透明代理也是非透明代理。
網關(gateway)
網關實際上是一個服務器,扮演着表明其它服務器爲客戶端提供服務的中間者。與代理(proxy)不一樣,網關接收請求,彷彿它就是請求資源的源服務器。請求的客戶端可能覺察不到它正在同網關通訊。
隧道(tunnel)
隧道也是一箇中間程序,它一個在兩個鏈接之間充當盲目中繼(blind relay)的中間程序。一旦隧道處於活動狀態,它不能被認爲是此次HTTP通訊的參與者,雖然HTTP請求可能已經把它初始化了。當兩端的中繼鏈接都關閉的時候,隧道再也不存在。
緩存(cache)
緩存是程序響應消息的本地存儲。緩存是一個子系統,控制消息的存儲、取回和刪除。緩存裏存放可緩存響應(cacheable response)爲的是減小對未來一樣請求的響應時間和網絡帶寬消耗。任一客戶端或服務器均可能含有緩存,但高速緩存不能被一個充當隧道(tunnel)的服務器使用。
可緩存(cacheable)
咱們能夠說響應(response)是可緩存的,若是一個緩存(cache)爲了響應後繼請求而被容許存儲響應消息(response message)的副本。肯定HTTP響應的緩存能力(cacheability)在13節中有介紹。即便一個資源(resourse)是可緩存的,也可能存在緩存是否能利用緩存副本的約束。
第一手的(first-hand)
若是一個響應直接從源服務器或通過若干代理(proxy),而且沒有沒必要要的延時,最後到達客戶端,那麼這個響應就是第一手的(first-hand)。
若是響應被源服務器(origin server)驗證是有效性(validity)的,那麼這個響應也一樣是第一手的。
明確過時時間(explicit expiration time)
是源服務器但願實體(entity)若是沒有被進一步驗證(validation)就不要再被緩存(cache)返回的時間。
啓發式過時時間(heuristic expiration time)
當沒有明確終止時間(explicit expiration time)可利用時,由緩存所指定的終止時間.
年齡(age)
一個響應的年齡是從被源服務器發送或被源服務器成功確認的時間點到如今的時間。
保鮮壽命(freshness lifetime)
一個響應產生的時間點到過時時間點之間的長度。
保鮮(Fresh)
若是一個響應的年齡尚未超過保鮮壽命(freshness lifetime),它就是保鮮的.
陳舊(Stale)
一個響應的年齡已經超過了它的保鮮壽命(freshness lifetime),就是陳舊的.
語義透明(semantically transparent)
緩存(cache)可能會以一種語意透明(semantically transparent)的方式工做。這時,對於一個特定的響應,使用緩存既不會對請求客戶端產生影響也不會對源服務器產生影響,緩存的使用只是爲了提升性能。當緩存(cache)具備語意透明性時,客戶端從緩存接收的響應跟直接從源服務器接收的響應徹底一致(除了使用hop-by-hop頭域)。
驗證器(Validator)
驗證器實際上是協議元素(例如:實體頭(entity tag)或最後更改時間(last-modified time)等),這些協議元素被用於識別緩存裏保存的數據(即緩存項)是不是源服務器的實體的副本。
上游/下游(upstream/downstream)
上游和下游描述了消息的流動:全部消息都從上游流到下游.
向內/向外(inbound/outbound)
向內和向外指的是消息的請求和響應路徑:"向內"即"移向源服務器","向外"即"移向用戶代理(user agent)".
1.4 整體操做
HTTP協議是一種請求/響應協議。 與服務器創建鏈接後,客戶端以請求方法,URI和協議版本號,而後緊接着跟隨一個類MIME(MIME-like)消息,這個類MIME消息包括請求修飾符,客戶信息和可能的消息主體。服務器以一個狀態行並跟隨一個類MIME(MIME-like)消息響應,狀態行包含消息的協議版本和成功出錯的狀態碼,類MIME消息包含服務器信息,實體元信息,和可能的實體。HTTP和MIME之間的關係如附錄19.4節所闡述。
大部分的HTTP通訊是由用戶代理(user agent)開始的,由應用到一個須要源服務器資源的請求構成。最簡單的情形,能夠經用戶代理(UA)和源服務器(O)之間的單一鏈接(v)完成。
請求鏈(Request chain)--------------------- ----------à
用戶代理(UA)----------------單一鏈接(v)--------------源服務器(O)
<---------------------------------------響應鏈(response chain)
當一個或多箇中間者在請求/響應鏈中出現的時候,會出現更復雜的情形。常見的中間者有三種:代理(proxy),網關(gateway)和隧道(tunnel)。代理(proxy)是一種轉發代理(a forwarding agent),它接收絕對URI(absoulute url,相對於相對url)請求,重寫所有或部分消息,而後把格式化後的請求發送到URI指定的服務器上。網關是一種接收代理(receiving agent),它充當一個層(layer),這個層在服務器之上,必要時它會把請求翻譯成爲下層服務器的協議。隧道不改變消息而充當兩個鏈接之間的中繼點;它用於通訊須要穿過中間者(如防火牆)甚至當中間者不能理解消息內容的時候。
請求鏈(request chain)----------------------------------------à
UA-----v-----A-----v-----B-----v-----C------------v-----------------O
<----------------------------------------響應鏈(response chain)
上圖顯示了用戶代理(user agent)和源服務器之間的三個中間者(A,B和C)。整條鏈的請求或響應將會經過四個單獨的鏈接。這個特性很重要,由於某些HTTP通訊選項可能只能應用於與最近的非隧道鄰接點的鏈接,只能應用於鏈的端點(end-point)的鏈接,或者能應用於此鏈的全部鏈接。圖表儘管是線性的,每一個參與者可能忙於多路同時通訊。例如,B能夠接收來自不一樣於A的許多客戶的請求,而且/或者能夠把請求轉到不一樣於C的服務器,與此同時,它還在處理A的請求。
任何非隧道的通訊成員均可能會採用一個內部緩存(cache)來處理請求。若是沿着鏈的通訊成員對請求採用了緩存響應,請求/響應鏈就會大大縮短。下圖闡明瞭一個最終請求響應鏈,這是在假定B擁有一個來自O(經過C)的之前請求的響應副本,但此響應還沒有被UA或A緩存。
請求鏈(request chain)---------->
UA-----v----------A-----v-----B-----C----O
<---------響應鏈 (response chain)
並非全部的響應都能有效地緩存,一些請求可能含有修飾符,這些修飾符對緩存動做有特殊的要求。緩存動做和緩存響應的HTTP行爲要求將在第13節定義。
實際上,目前萬維網上有多種結構和配置的緩存(cache)和代理(proxy)正在被使用。這些系統包括節省帶寬的緩存代理(proxy cache),能夠廣播或多點傳送緩存數據的系統,經過CD-ROM分配緩存數據子集的機構,等等。HTTP系統(http system)會被應用於寬帶鏈接的企業局域網中的協做,而且能夠經過PDA進行低耗無線的,斷續鏈接的訪問。HTTP1.1的宗旨是爲了支持各類各樣的已經部署的配置,同時引進一種協議結構,讓它知足那些須要較高可靠性,即便不能達到較高可靠性的要求,也要也讓它至少能夠指示故障的網絡應用的要求。
HTTP通訊一般發生在TCP/IP鏈接上。默認端口是TCP 80,不過其它端口也能夠使用。這並不妨礙HTTP的實現被應用於互聯網(internt)或其它網的協議之上。Http僅僅指望的是一個可靠的傳輸(譯註:HTTP通常創建在傳輸層協議之上);任何提供這種保證的協議均可以被使用;協議傳輸數據單元(transport data unit)與HTTP/1.1請求和響應的消息結構之間的映象已經超出了本說明書的範圍。
大部分HTTP/1.0的實現都是針對每一個請求/響應交換產生一個新的鏈接。而http/1.1中,一個鏈接能夠被用於一個或更多請求/響應交換,雖然鏈接可能會由於各類緣由中斷(見第8.1節)。
2 符號習慣和通常語法
2.1 擴充的BNF(擴充的 巴科斯-諾爾範式)
本文檔規定的全部機制都用兩種方法描述:散文體(prose)和相似於RFC 822的擴充Backus-Naur Form(BNF)。要理解本規範,使用者需熟悉符號表示法。擴充BNF結構以下:
名字(name)=定義(definition)
名字(name)就是表明規則的名字(譯註:如:CRLF,DIGIT等等都是規則名),規則名裏不能包含「<」和「>」,經過等於號把規則名和規則定義(definiation)分離開。空白(white space)是有意義的,由於能夠用縮進(indentation,譯註:縮進就是空白,後面會講到LWS) 把規則定義顯示成多行。某些基本規則(basic rule,譯註:2.2節說明基本規則的語法)使用大寫字母包含在規則定義裏, 你如SP,LWS,HT,CRLF,DIGIT,ALPHA,等等。尖括號能夠包含在規則定義裏,只要它們的存在有利於識別規則名(譯註:LWS,HT等都是規則名)。
「字面文本」(「literal」)
字面文本(literal text)兩邊用引號。除非聲明,字面文本大小寫不敏感(譯註:如,HEX = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT 裏的A,B,C,D等等都是字面文本(literal text))。
規則1 | 規則2
由豎線(「|」)分開的元素是可選的,例如,「yes | no」表示yes或no都是可接受的。
(規則1 規則2)
圍在括號裏的多個元素視做一個元素。因此,「(elem (foo | bar) elem)」的符合的字符串是「elem foo elem」和「elem bar elem」。
*規則
前面的字符「*」表示重複。完整的形式是「<n>*<m>元素」,表示元素至少出現<n>次,至多出現<m>次。默認值是0和無窮大,因此"*(元素)"容許任何數值,包括零;"1*元素"至少須要一次;"1*2element"容許一次或兩次。
[規則]
方括號裏是任選元素;「[foo bar]」至關於「*1(foo bar)」。
N 規則
特殊的重複:「<n>(元素)」與「<n>*<n>(元素)」等價;就是說,(元素)正好出現了<n>次。這樣2DIGIT是一個兩位數字,3ALPHA是一個由三個字符組成的字符串。
#規則
相似於「*」,結構「#」是用來定義一系列元素的。完整的形式是<n>#<m>元素,表示至少<n>個元素,至多<m>個元素,元素之間被一個或多個逗號(「,」)以及可選的線性空白(LWS)隔開了。這就使得表示列表這樣的形式變得很是容易;像
( *LWS element) *( *LWS ","*LWS element ))
就能夠表示爲
1#element
不管在哪裏使用這個結構,空元素都是容許的,可是不計入元素出現的次數。換句話說 ,
「(element ), , (element) 」是容許的,可是僅僅視爲兩個元素。所以,在至少須要一個元素的地方,必須存在至少一個非空元素。默認值是0和無窮大,這樣,「#element」容許任意零個或多個元素;「1# element」須要至少一個;「1#2element」容許一個或兩個元素。
;註釋(comment)
用分號引導註釋。
隱含的(implied) *LWS
本說明書所描述的語法是基於字的。除非特別註明,線性空白可出如今任何兩個相鄰字之間(標記(token)或引用字符串(quoted-string)),以及相鄰字和間隔符之間,這並無改變一個域的解釋。任何兩個標記(token)之間必須有至少一個分割符,不然將會被理解爲單一標記。
2.2基本規則 (basic rule)
下面的規則貫穿於本規範的全文,此規則描述了基本的解析結構。US-ASCII(美國信息交換標準碼)編碼字符集是由ANSI X3.4-1986[21]定義的。
OCTET(字節) = <任意八比特的數據序列>
CHAR = <任意ASCII字符(ascii碼值從 0到127的字節)>
UPALPHA = <任意大寫字母"A"..."Z">
LOALPHA = <任意小寫字母"a"..."z">
ALPHA = UPALPHA | LOALPHA
DIGIT = <任意數字0,1,...9>
CTL = <任意控制字符(ascii碼值從0 到 31的字節)及刪除鍵DEL(127>
CR = <US-ASCII CR, 回車(13)>
LF = <US-ASCII LF, 換行符(10)>
SP = <US-ASCII SP, 空格(32)>
HT = <US-ASCII HT, 水平製表 (9)>
<"> = <US-ASCII 雙引號(34)>
HTTP/1.1將 CR LF 的序列定義爲任何協議元素的行尾標誌,但這除了實體主體(endtity-body)外(要求比較鬆的應用見附錄19.3)。實體主體(entity-body)的行尾標誌是由它的關聯媒體類型定義的,如3.7節所述。
CRLF = CR LF
HTTP/1.1 的消息頭域值能夠摺疊成多行,但緊接着的摺疊行由空格(SP)或水平製表(HT)摺疊標記開始。全部的線性空白(LWS)包括摺疊行的摺疊標記(空格SP或水平製表鍵HT),具備同SP同樣的語義。接收者在解析域值或將消息轉送到下游(downstream)以前可能會將任何線性空白(LWS)替換成單個SP(空格)。
LWS = [CRLF] 1*( SP | HT )
下面的TEXT規則僅僅適用於域內容和域值的描述,不會被消息解釋器解析。TEXT裏的字能夠包含不只僅是ISO-8859-1[22]裏的字符集,也能夠包含RFC 2047裏規定的字符集。
TEXT = <除CTLs之外的任意OCTET,但包括LWS>
一個CRLF只有做爲HTTP消息頭域延續的一部分時纔在TEXT定義裏使用。
十六進制數字字符用在多個協議元素(protocol element)裏。
HEX = "A" | "B" | "C" | "D" | "E" | "F"
| "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
許多HTTP/1.1的消息頭域值是由LWS或特殊字符分隔的字構成的。這些特殊字符必須先被包含在引用字符串(quoted string)裏以後才能用於參數值(如3.6節定義)裏。
token (標記) = 1*<除CTLs與分割符之外的任意 CHAR >
separators(分割符) = "(" | ")" | "<" | ">" | "@"
| "," | ";" | ":" | """ | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
經過用圓括號括起來,註釋(comment)能夠包含在一些HTTP頭域裏。註釋只能夠做爲域定義的一部分。在其餘域裏,圓括號被視做域值的一部分。
comment (註釋)= "(" *( ctext | quoted-pair | comment ) ")"
ctext = <除"(" 和 ")"之外的任意TEXT >
若是一個TEXT若被包含在雙引號裏,則看成一個字。
quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
qdtext = <any TEXT except <">>
斜劃線(""")能夠被做爲單個字符的引用機制,可是必需要在引號和註釋區以內。
quoted-pair = """ CHAR
3 協議參數
3.1 HTTP版本
HTTP使用一個「<major>.<minor>」數字模式來指明協議的版本號。協議的版本號是爲了讓發送端指明消息的格式和它的能力,這是爲了進一步的HTTP通訊,而不只僅是得到通訊的特徵。協議版本是不須要修改的,當消息組件的增長不會影響通訊行爲或着只增長了擴展的域值。<minor>數字是遞增的,當協議會由於添加一些特徵而作了修改的時候。但這些變化不會影響一般的消息解析算法,可是它會給消息添加語意(semantic)而且會暗示發送者具備額外的能力。<major>數字也是不斷遞增的,當協議的消息格式每次發生變化時。
HTTP消息的版本在HTTP-Version域被指明,HTTP-Version域在消息的第一行中。
HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
注意major和minor數字必須被當作兩個獨立整數,每一個整數均可以遞增,而且能夠增大到大於一位數的整數,如HTTP/2.4比HTTP/2.13低,而HTTP/2.4又比HTTP/12.3低。前導0必須被接收者忽略而且不能被髮送者發送。
一個應用程序發送請求或響應消息,若是請求或響應消息裏的HTTP-Version是」HTTP/1.1」,那麼此應用程序必須條件遵循此協議規範。最少條件遵循此規範的應用程序應該把」HTTP/1.1」包含在他們的消息裏,而且對任何不兼容HTTP/1.1的消息必須這麼作。關於什麼時候發送特定的HTTP-Version值的細節,參見RFC2145。
應用程序的HTTP版本是應用程序最少條件遵循的最高HTTP版本。
代理(proxy)和網關(gateway)應用程序須要被仔細對待,當轉發(forwarding)消息的協議版本不一樣於代理或網關應用程序的協議版本。由於消息裏協議版本說明了發送者處理協議的能力,因此一個代理/網關千萬不要發送一個高於該代理/網關應用程序協議版本的消息。若是代理或網關接收了一個更高版本的消息,它也必需要下降請求的版本,要麼以一個錯誤響應,要麼切換到隧道行爲(tunnel behavior)。
因爲自從RFC 2068[33]發佈後,產生了與HTTP/1.0代理(proxy)的互操做問題,因此緩存代理(caching proxy)必須能改變請求(request),使請求能到達他們能支持的最高版本,但網關(gateway)能夠這麼作也能夠不這麼作,而tunnel不能這麼作。代理(Proxy)/網關(gateway)的響應(Response)必須和請求(request)的HTTP版本的major數字相同。
注意:在HTTP版本間的轉換可能包含頭域(header field)的改變,而這些改變會可能會根據HTTP版本而被要求或被拒絕。
3.2 統一資源標識符(URI)
URIs的許多名字已爲人所知:WWW地址,通用文檔標識符,通用資源標識符[3],以及後來的統一資源定位器(URL)[4]和統一資源名稱(URN)[20]。就HTTP而言,統一資源定位器只是格式化的字符串,它經過名稱,地址,或任何別的特徵識別資源。
3.2.1通常語法
根據使用的背景,HTTP裏的URI能夠表示成絕對(absoulute)形式或相對形式(相對於已知的URL)。兩種形式的區別是根據這樣的事實:絕對URI老是以一個方案(scheme)名做爲開頭,其後是一個冒號。關於URL更詳盡的信息請參看"統一資源標識符(URI):通常語法和語義",RFC 2396 [42](代替了RFCs 1738 [4]和RFC 1808 [11])。本規範採用了RFC 2396裏的"URI-reference","absoluteURI","relativeURI","port","host","abs_path","rel_path",和"authority"的定義格式。
HTTP協議不對URI的長度做事先的限制,服務器必須可以處理它們資源的URI,而且應該可以處理無限長度的URI,這種無效長度的URL可能會在客戶端以GET形式的請求產生。服務器應該返回414狀態碼(此狀態碼錶明Request-URI太長),若是服務器不能處理太長的URI的時候。
注:服務器在依賴大於255字節的URI時應謹慎,由於一些舊的客戶或代理實現可能不支持這些長度。
3.2.2 http URL
經過HTTP協議,http方案(http scheme)被用於定位網絡資源(resourse)的位置。本節定義了這種方案的語法和語義。
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
若是端口爲空或未給出,就假定爲80。語義即:已識別的資源放在服務器上,在那臺主機的那個端口上監聽TCP鏈接。這時資源的請求的URI爲絕對路徑(5.1.2節)。不管什麼可能的時候,URL裏使用IP地址都是應該避免的(參看RFC 1900 [24])。若是絕對地址(abs_path)沒有出如今URL裏,那麼應該給出"/"。若是代理(proxy)收到一個主機(host)名,可是這個主機名不是全稱的域名(fully quanlified domain name),則代理應該把它的域名加到主機名上。若是代理(proxy)接收了一個全稱的域名,代理沒必要改變主機。
3.2.3 URI 比較
當比較兩個URI是否匹配時,客戶應該對整個URI比較時應該區分大小寫,而且一個字節一個字節的比較。 但下面有些特殊狀況:
- 一個爲空或未給定的端口等同於URI-refernece(見RFC 2396)裏的默認端口;
- 主機(host)名的比較必須沒必要分大小寫;
- 方案(scheme)名的比較必須是不區分大小寫的;
- 一個空絕對路徑(abs_path)等同於"/"。
除了"保留(reserved)"和"不安全(unsafe)"字符集裏的字符(參見RFC 2396 [42]) ,其它字符都等效於它們的"%HEXHEX"編碼.
例如,如下三個URI是等同的:
http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html
3.3 日期/時間格式(Date/Time Formats)
3.3.1完整日期 (Full Date)
HTTP應用曾經一直容許三種不一樣日期/時間格式:
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
第一種格式是做爲Internet標準提出來的,它是一個國定長度的,由RFC 1123 [8](RFC 822[9]的升級版本)定義的一個子集。第二種格式使用比較廣泛,可是基於廢棄的RFC 850 [12],而且沒有年份。若是HTTP/1.1客戶端和服務器解析日期,他們必須能接收全部三種格式(爲了兼容HTTP/1.0),可是它們只能產生RFC 1123裏定義的日期格式來填充頭域(header field)用到日期的地方。
注:日期值的接收者被鼓勵能健壯的接收可能由非HTTP應用發來的日期值,例若有時能夠經過代理(proxy)/網關(gateway)向SMTP或NNTP得到或轉發消息。
全部的HTTP日期/時間都必須以格林威治時間(GMT)表示。對HTTP而言,GMT徹底等同於UTC(世界協調時間)。前兩種日期/時間格式裏包含「GMT」,它是時區的三個字面的簡寫,而且當讀到一個asctime格式時必須先被假定是GMT時間。HTTP日期(HTTP-date)區分大小寫,不能包含一個額外的LWS,除非此LWS做爲在下面的Http-date語法中指定的SP。
HTTP-date = rfc1123-date | rfc850-date | asctime-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
rfc850-date = weekday "," SP date2 SP time SP "GMT"
asctime-date = wkday SP date3 SP time SP 4DIGIT
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
date2 = 2DIGIT "-" month "-" 2DIGIT
; day-month-year (e.g., 02-Jun-82)
date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
; month day (e.g., Jun 2)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" | "Tue" | "Wed"
| "Thu" | "Fri" | "Sat" | "Sun"
weekday = "Monday" | "Tuesday" | "Wednesday"
| "Thursday" | "Friday" | "Saturday" | "Sunday"
month = "Jan" | "Feb" | "Mar" | "Apr"
| "May" | "Jun" | "Jul" | "Aug"
| "Sep" | "Oct" | "Nov" | "Dec"
注意:HTTP對日期/時間格式的要求僅僅應用在協議的消息(譯註:原文是protocol stream,便於理解這裏譯做消息)裏。客戶和服務器沒必要把這種格式應用於用戶呈現(user presentation),請求記錄日誌,等等。.
3.3.2 Delta Seconds
一些HTTP頭域(header field)容許用整數秒錶示時間值,整數秒用十進制表示,此整數秒錶示消息被接收後時間。
delta-seconds = 1*DIGIT
3.4 字符集
HTTP使用術語"字符集"的定義,這和MIME中所描述的是同樣.
本文檔中的術語"字符集"涉及到一種方法,此方法是用一個或多個表將一個節序列轉換成一個字符序列(譯註:從這裏來看,這應該是一種映射關係,表保存了映射關係)。注意反方向的無條件轉換(譯註:從一個字符序列到一個字節序列的轉換)是不須要的,由於並非全部的字符都能在一個給定的字符集裏獲得,一個字符集可能提供多個字節序列表徵一個特定的字符。這個定義是爲了容許不一樣種類的字符編碼從單一簡單表映射(如US-ASCII)到複雜表的轉換方法如ISO-2022技術用到的。然而,與MIME字符集名字相關的定義必需要充分說明從字節到字符的映射。特別的,使用外部輪廓信息來精確肯定映射是不容許的.
注:這裏使用的術語"字符集"通常的被稱做一種"字符編碼"。不過既然HTTP和MIME在同一機構註冊,術語統一是很重要的。
HTTP字符集是用不區分大小寫的標記(token)表示。全部的標記集由IANA字符集註冊機構[19]定義。
charset = token
儘管HTTP容許用任意標記(token)做爲字符集(charset)值,但任何標記值若是它已經在IANA字符集註冊機構註冊了則必須表示在該註冊機構定義的字符集。對那些非IANA定義的字符集,應用程序應該限制使用。
HTTP協議的實現者應該注意IETF字符集的要求[38][41].
3.4.1丟失的字符集(Missing Charset)
一些HTTP/1.0應用程序當他們解析Content-Type頭時,當發現沒有字符集參數(charset parameter,譯註:Content-Type: text/plain; charset=UTF-8,此時charset=UTF-8就是字符集參數)可用時,這意味着接收者必須猜想實體主體(entity body,譯註:這裏翻譯成「實體主體」由於Content-Type頭是實體頭,消息頭能夠分爲實體頭,經常使用頭,請求頭,響應頭,在譯文中屢次用到「頭」和「頭域」,如消息頭,消息頭域,實際上是同一個意思,HTTP1.1協議有時候概念並非徹底統一的)的字符集是什麼。若是發送者但願避免這種狀況,他應該在Content-Type頭域裏包含一個字符集參數,即便字符集是ISO-8859-1也應該這樣作,這樣就不會讓接收者產生混淆。
不幸的是,一些舊的HTTP/1.0客戶端不能處理在Content-Type頭域裏明確指定的字符集參數。HTTP/1.1接收端必需要認真對待發送者提供的字符集;而且當用戶代理(user agent,譯註:如瀏覽器,可認爲是接收端)開始顯示一個文檔時,雖然用戶代理能夠猜想文檔的字符集,但若是content-type頭域裏提供了字符集,而且用戶代理也支持這種字符集的顯示,無論用戶代理是否願意,它必需要利用這種字符集。參見3.7.1節。
3.5 內容編碼(Content Codings)
內容編碼值(content coding value)表示一種已經或能夠應用於實體的編碼轉換(encoding transformation)。內容編碼主要用於文檔的壓縮或其它有效的變換,但這種變換須要不能丟失文檔的媒體類型(media type,譯註:文檔通常會有媒體類型,這經過在content-type裏指定)的特性,也不能丟失文檔的信息(譯註:就像有損壓縮和無損壓縮,前者不會丟失信息,後者會丟失信息)。實體常常被編碼的儲存,而後直接傳送,接收端只能解碼。
content-coding = token
全部內容編碼值(content-coding value)是不區分大小寫的。HTTP/1.1在接收譯碼 (14.3節)和內容譯碼(Content-Encoding)(14.11節)頭域裏使用內容編碼值(content-coding value)。儘管該值描述了內容編碼,更重要的是它指出了一種解碼機制,利用這種機制對實體的編碼進行解碼。
網絡分配數字權威( (IANA)充當內容編碼值標記(token)的註冊機構。最初,註冊表裏包含下列標記:
gzip(壓縮程序)
一種由文件壓縮程序"gzip"(GNU zip)產生的編碼格式(在RFC 1952中描述)。這種編碼格式是一種具備32位CRC的Lempel-Ziv編碼(LZ77)。
compress(壓縮)
一種由UNIX文件壓縮程序"compress"產生的編碼格式。這種編碼格式是一種具備可適應性的Lempel-Ziv-Welch編碼(LZW)。
對於未來的編碼,用程序名識表徵編碼格式是不可取。在這裏用到他們是由於他們在歷史的做用,雖然這樣作並很差。爲了同之前的HTTP實現相兼容,應用程序應該將"x-gzip"和"x-compress"分別等同於"gzip"和"compress"。
deflate(縮小)
deflate編碼是由RFC 1950 [31]定義的"zlib"編碼格式與RFC 1951 [29]裏描述的"deflate"壓縮機制的組合的產物。
identity(一致性)
Identity是缺省編碼;指明這種編碼代表不進行任何編碼轉換。這種內容編碼僅被用於接收譯碼(Accept-Encoding)頭域,但不能被用在內容譯碼(Content-Encoding)頭域。.
新的內容編碼值標記(token)應該被註冊;爲了實現客戶和服務器間的互操做性,實現新值的內容編碼算法規範應該能公開利用而且能獨立實現,而且與本節中被定義的內容編碼目的相一致。
3.6 傳輸編碼 (Transfer Codings)
傳輸編碼值(transfer-coding value,譯註:transfer coding和和transfer-coding這兩個術語在本協議規範裏所表達的意思其實沒什麼太大區別,「transfer-coding」可能更能表達語意,由於它是規則中的規則名,見下面紅字的規則)被用來表示一個已經,可以,或可能應用於一個實體的編碼轉換,傳輸編碼是爲了可以確保網絡安全傳輸。這不一樣於內容編碼(content coding),由於傳輸編碼(transfer coding)是消息的屬性而不是實體的屬性。
transfer-coding = "chunked" | transfer-extension
transfer-extension = token *( ";" parameter )
參數(parameter)採用屬性/值對的形式.
parameter = attribute "=" value
attribute = token
value = token | quoted-string
全部傳輸編碼值(transfer-coding value,譯註:上面紅體字等號右邊規則表達式所表達的值)是大小寫不敏感。傳輸編碼值在TE頭域(14.39節)和在傳輸譯碼(Transfer-encoding) 頭域中(14.41節)被運用。
不管什麼時候,傳輸編碼(transfer-coding)應用於一個消息主體(message body)時,若是存在多個傳輸編碼,則這些傳輸編碼中必須包括「塊」("chunked")傳輸編碼,除非經過關閉鏈接而中斷消息。當「塊」(「chunked」)傳輸編碼被用於傳輸編碼時,它必須是應用於消息主體的最後傳輸編碼。"塊"("chunked")傳輸編碼最多隻能用於消息主體(message-body)一次。規定了上述規則後,接收者就能夠肯定消息的傳輸長度(transfer-length)(4.4節)
傳輸編碼與MIME[7]的內容傳輸譯碼(Content-Transfer-Encoding,譯註:transfer應該是轉移,遷移的意思,又例如HTTP協議,應該翻譯成「超文本轉移協議」,可是歷史上都翻譯成「超文本傳輸協議」,因此這裏翻譯成「超文本傳輸協議」)值有相相似型,它被定義可以實如今7位傳輸服務上保證二進制數據的傳輸安全。不過,傳輸編碼與內容傳輸譯碼(Content-Transfer-Encoding)對純8位傳輸協議有不一樣的關注點。在HTTP中,消息主體存在不安全的隱患,由於有時候很難肯定消息主體的長度,在共享的傳輸上加密數據也會帶來安全性問題(7.2.2節)。
網絡分配數字權威(IANA)擔任註冊傳輸編碼值標(token)記的角色。起初,註冊包含以下標記:"塊"(3.6.1節),"身份"(3.6.2節),"gzip"(3.5節),"壓縮"(3.5節),和"縮小"(3.5節).
新的傳輸編碼值標記應該註冊,這同新的內容編碼值標記也須要註冊同樣。.
接收端接收到一個帶有傳輸編碼(transfer-coding)(譯註:經過消息頭域transfer-encoding指明此實體主體的傳輸編碼)的實體主體(entity body),若是它不能對這個編碼後的實體主體進行解碼,那麼它應返回501(不能實現),而且要切斷聯繫。服務器不能向HTTP/1.0客戶發送傳輸編碼.
3.6.1塊傳輸編碼(Chunked Transfer Coding)
塊編碼(chunked encoding)改變消息主體使消息主體(message body,譯註:消息主體與實體主體是有區別的,後面章節將會介紹)成塊發送。每個塊有它本身的大小(size)指示器,在全部的塊以後會緊接着一個可選的包含實體頭域的尾部(trailer)。這容許發送端能動態生成內容,並能攜帶有用的信息,這些信息能讓接收者判斷消息是否接收完整。
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是用16 進制數字字符串。塊編碼(chunked encoding)以任一大小爲0的塊結束,緊接着是尾部(trailer),尾部以一個空行終止。
尾部(trailer)容許發送端在消息的末尾包含附加的HTTP頭域(header field)。Trailer頭域(Trailer header field,譯註:Trailer頭是經常使用消息頭,在14.40節說明)被應用來指明哪些頭域被包含在塊編碼的尾部(trailer) (見14.40節)
若是服務器要用塊傳輸編碼進行響應,它不能包含尾部(trailer),除非如下至少一條爲真:
a)若是此響應的請求包括一個TE頭域,而且它指明瞭傳輸編碼中的「trailers」是可接受的,當響應的傳輸編碼(transfer-coding)是塊編碼時。這在14.39節中描述;或者
b)若是服務器是響應的源服務器,而且接收端接收塊傳輸編碼響應但不會去理會響應的尾部(trailer,譯註:尾部包含頭域,頭域就是消息的元數據(metadata))而且這種方式源服務器是能夠接受的,這時服務器是不須要把尾部(trailer)包含進消息的塊傳輸編碼中去的。換句話說,源服務器原意接受尾部(trailer)可能會在到達客戶端時被丟棄的可能性。
此要求防止了一種互操做性的失敗,當消息被一個HTTP/1.1(或更遲的)代理(proxy)接收而且轉到一個HTTP/1.0的接收端的時候。
在附錄19.4.6節介紹了一個例子,這個例子介紹怎樣對一個塊正文(chunked-body)進行解碼。
全部HTTP/1.1應用程序必須能接收和解碼塊(chunked)傳輸譯碼,而且必須忽略它們不能理解的塊擴展(chunk-extentsion,譯註:見上面的規則表達式).
3.7 媒體類型(Media Type)
HTTP在Content-Type(14.17節)實體頭域和Accept請求頭域裏利用網絡媒體[17]類型,這是爲了提供公開的,可擴展的數據打印和類型協商。
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token
參數(parameter)以一種屬性/值對的形式跟隨type/subtype(如3.6節定義) 。
類型(type),子類型(subtype),和參數(parameter)裏屬性名稱是大小寫不敏感的。參數值有多是大小寫敏感的,也可能不是,這根據參數裏屬性名的語意。線性空白(LWS)不能被用於類型(type)和子類型(subtype)之間,也不能用於參數的屬性和值之間。參數的出現或不出現對處理媒體類型(media-type)可能會有幫助,這取決於它在媒體類型註冊表裏的定義。
注意一些舊的HTTP應用程序不能識別媒體類型的參數(parameter)。當向一箇舊的HTTP應用程序發送數據時,發送端只有在被type/subtype定義須要時才使用類型參數(parameter)。
媒體類型(media-type)值須要被註冊到網絡數字分配權威(IANA[19])裏。媒體類型的註冊程序在RFC 1590[17]中大概描述。使用未經註冊的媒體類型是不被鼓勵的。
3.7.1規範化和文本缺省 (Canonicalization and Text Defaults)
網絡媒體類型以規範化的格式被註冊。一個實體主體(entity-body)經過HTTP消息傳輸,它必須在傳輸前以一種合適的規範化的格式表徵除了文本類型(text type),文本類型將會在下一段闡述。
當消息以一種規範化的格式表現時,文本類型的子類型(subtype)運用GRLF做爲文本里的換行符。HTTP放鬆了這個要求,而且容許文本媒體以一個CR或LF表明一個換行符傳輸,而且這樣作要貫穿整個實體主體(entity-body)。HTTP應用程序必須能接收CRLF,CR和LF做爲在文本媒體一個換行符。另外,若是文本字符集(character set)不能用字節13和10來分別地表徵CR和LF由於存在一些多字節字符,HTTP容許應用字符集裏等價於CR和LF的字節序列來表示換行符。對換行符的靈活處理只能應用於實體主體裏的文本媒體;在HTTP消息結構裏,一個單獨的CR或LF都不能代替CRLF(如頭域和多邊界體(multipart boundaries)結構裏)。
若是一個實體主體(entity-body)用內容編碼(content-coding)進行編碼,原始數據(譯註:被編碼前的數據)在被編碼前必須是一種定義的媒體類型格式。.
"charset"參數(parameter)被應用於一些媒體類型,來定義數據的字符集(見3.4節)。當發送者沒有在媒體類型(media-type)裏指明charset參數(parameter)時,文本類型的子媒體類型(subtype)被認爲是缺省的ISO-8859-1字符集當被接收者接收後。數據必須被合適的字符集標識。3.4.1節描述了兼容性問題。
3.7.2多部分類型(Multipart type)
MIME提供了一系列"多部分"類型---在單個消息主體內包裝一個或多個實體。全部的多部分類型共享一個公共的語法(這在RFC 2046[40]的5.1.1節中描述),而且包含一個邊界(boundary)參數做爲多部分媒體類型值的一部分。多部分類型的消息主體是一個協議元素,而且必須用CRLF來標識體部分(body-part,譯註:見RFC 2046 的5節)之間的換行。
不一樣於RFC 2046裏的多部分消息類型的描述,HTTP1.1規定任何多部分類型的消息尾聲(epilogue,譯:見RFC 2046對多部分消息類型的規則描述)必須不能存在;HTTP應用程序不能傳輸尾聲(epilogue)(即便原始的多部分消息尾部包含一個尾聲)。存在這些限制是爲了保護多部分消息主體的自我定界的特性,由於多部分邊界的結束(譯註:根據RFC2046中定義,多部分邊界結束後可能還會有尾聲)標誌着消息主體的結束。
一般,HTTP把一個多部分類型的消息主體(message-body)和任何其餘媒體類型的消息主體相同對待:嚴格看做有用的負載體。有一個例外就是"multipart/byterange"類型(附錄19.2),當它出如今206(部份內容)響應時,此響應會被一些HTTP緩存機制解析,緩存機制將會在13.5.4節和14.16節介紹。在其它狀況下,一個HTTP用戶代理會遵循MIME用戶代理同樣的或者類似的行爲,這依賴於接收何種多部分類型。一個多部分類型消息的每個體部分(bady-part)裏的MIME頭域對於HTTP並無太大意義除了MIME語意。
一般, 一個HTTP用戶代理應該遵循與一個MINE用戶代理相同或類似。若是一個應用程序收到一個不能識別的多部分子類型,這個應用程序必須將它視爲"multipart/mixed"。
注:"multipart/form-data"類型已經被規範的定義爲傳送窗體數據(譯註:通常用窗體上傳數據時,上傳的數據類型就是爲multipart/form-data類型),當用POST請求方法處理數據時。這在RFC 1867[15]裏定義。
3.8 產品標記 (product Tokens)
產品標記用產品名和版本號識別通信應用軟件。不少頭域都會利用產品標記,它容許構成應用程序重要部分的子產品被以空白分隔列舉。一般,產品以應用程序的重要性的順序來列舉的。
product = token ["/" product-version]
product-version = token
例:
User-Agent:CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4
產品標示應言簡意賅。它們不能用來作廣告或其餘不重要的信息。雖然任一標記可能出現product-version裏,但這個標記僅能用來作一個版本 (i.e., 同產品中的後續版本應該在product-version上有區別)
3.9 質量值(Quality Values)
HTTP內容協商(content negotiation,12節介紹)運用短「浮點」數字(short floating point number)來錶針不一樣協商參數的相對重要性。重要性的權值被規範化成一個從0到1的實數。0是最小值,1是最大值。若是一個參數的質量值(quanlity value)爲0,那麼這個參數的內容不被客戶端接受。HTTP/1.1應用程序不能產生多於三位小數的實數。下面規則限定了這些值。
qvalue = ( "0" [ "." 0*3DIGIT ] )
| ( "1" [ "." 0*3("0") ] )
"質量值" 是一個不當的用詞,由於這些值僅僅表現一中相對的降級。
3.10 語言標籤 (Language Tags)
一個語言標籤表徵一種天然語言,這種天然語言能說,能寫,或者被用來人與人之間的溝通。計算機語言明顯不包括在內的。HTTP在Accept-Language和Content-Language頭域裏應用到語言標籤(language tag)。
HTTP語言標籤的語法和註冊和RFC 1766[1]中定義的同樣。總之,一個語言標籤是由一部分或多部分構成:一個主語言標籤和可能爲空的子標籤系列。
Language-tag = primary-tag*("-" subtag)
primary = 1*8ALPHA
subtag = 1*8ALPHA
標籤中不容許出現空格,標籤大小寫不敏感(case-insensitive)。由IANA來管理語言標籤中的名字。典型的標籤包括:
en, en-US, en-cockney, i-cherokee, x-pig-latin
上面的任意兩個字母的主標籤是一個ISO-639語言的縮,而且兩個大寫字母的子標籤是一個ISO-3166的國家代碼。(上面的最後三個標籤是未經註冊的標籤;可是除最後一個以外全部的標籤都會未來註冊)。
3.11 實體標籤 (Entity Tags)
實體標籤被用於比較相同請求資源中兩個或更多實體。HTTP/1.1在ETag(14.19節),If-match(14.24節),If-None-match(14.26節)和If-Rang(14.27節)頭域中運用實體標籤。關於它們怎樣被看成一個緩存驗證器(cache validator)而使用和比較在13.3.3節被定義。一個實體標籤由一個給定的晦澀的引用字符串(opaque quoted string),還可能前面帶一個弱指示器組成。
entity-tag = [ weak ] opaque-tag
weak = "W/"
opaque-tag = quoted-string
一個「強實體標籤」若是被一個資源的兩個實體裏共享,那麼這兩個實體必須在字節上等價。
一個「弱實體標籤」是以"W/"前綴的,它可能會被一個資源的兩個實體共享,若是這兩個實體是等價的,而且能彼此之間能互相替代,而且也不會在語義上有太大改變。一個弱實體標籤只能用於弱比較(weak comparison)。
在一個特定資源的全部實體版本里,一個實體標籤必須能惟一。一個給定的實體標籤值能夠被於不一樣的URI請求用來得到的實體。相同實體標籤值運用於不一樣URI請求得到的實體,並不意味着這些實體是等價的。
3.12 範圍單位(Range Units)
HTTP/1.1容許一個客戶請求響應實體的一部分。HTTP/1.1在Range(14.35節)和Content-Range(14.16節)頭域裏應用範圍單位(range units)。任何實體根據不一樣的結構化單元都能被分解是子範圍
range-unit = bytes-unit | other-range-unit
bytes-unit = "bytes"
other-range-unit = token
HTTP/1.1中定義的惟一的範圍單位是"bytes"。HTTP/1.1實現時可能忽略其餘單位指定的範圍。
HTTP/1.1被設計容許應用程序實現不依靠有關對範圍的瞭解。
4 HTTP消息
4.1 消息類型(Message Types)
HTTP消息由從客戶到服務器的請求和從服務器到客戶的響應組成.
HTTP-message = Request|Response ;HTTP/1.1
請求(第5節)和響應(第6節)消息利用RFC 822[9]定義的經常使用消息的格式,這種消息格式是用於傳輸實體(消息的負載)。兩種類型的消息由開始行(start-line),零個或更多個頭域(常常被稱做「頭」),一個指示頭域結束的空行(也就是,一個以CRLF爲前綴的什麼也沒有的行),一個無關緊要的消息主體(message-body)。
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line
爲了健壯性,服務器應該忽略任意請求行(Request-Line)前面的空行。換句話說,若是服務器開始讀消息流的時候發現了一個CRLF,它應該忽略這個CRLF。
通常一個有問題的HTTP/1.0客戶端會在POST請求消息以後產生額外的CRLF。爲了重述什麼是BNF明確禁止的,一個HTTP/1.1客戶端不能在請求前和請求後加一些沒必要要的CRLF。
4.2 消息頭 (Message Headers)
HTTP頭域包括經常使用頭(4.5節),請求頭(5.3節),響應頭(6.2節)和實體頭(7.1節)域。它們遵循RFC822[0]3.1節中給出的同一個常規的格式。每個頭域由一個名字(域名)跟隨一個":"和域值構成。域名是大小寫不敏感的。域值前面可能有任意數量的LWS的。但SP(空格)是首選的。頭域能被延升多行,經過在這些行前面加一些SP或HT。應用程本應該遵循「經常使用格式」當產生HTTP消息時,由於可能存在一些應用程序,他們不能接收任何經常使用形式以外的形式。.
message-header = field-name ":" [ field-value ]
field-name = token
field-value = *( field-content | LWS )
field-content = <the OCTETs making up the field-value
and consisting of either *TEXT or combinations
of token, separators, and quoted-string>
filed-content不包括任何前導或後續的LWS(線性空白):線性空白出如今域值(filed-value)的第一個非空白字符以前或最後一個非空白字符以後。前導或後續LWS可能會被移除而不會改變域值的語意。任何出如今filed-content之間的LWS可能會被一個SP代替在解析域值以前或把這個消息往下流傳遞時。.
不一樣域名的頭域被接收的順序是不重要的。然而,首先發送經常使用頭域,而後緊接着是請求頭域或者是響應頭域,而後是以實體頭域結束,這樣作是一個好的的方法。
多個消息頭域使用同一個域名(filed-name)可能會出如今一些消息中,若是一個頭域的域值被定義成一個以逗號隔開的列表。把相同名的多個頭域結合成一個「域名:域值」對的形式而不改變消息的語意,能夠經過把每個後續的域值加到第一個裏,每個域值用逗號隔開。同名的頭域的接收順序對合並的域值的解釋有重要意義,因此代理(proxy)不能改變域值的順序,當它把此消息再次轉發時。
4.3 消息主體 (Message Body)
HTTP消息的消息主體用來承載請求和響應的實體主體(entity-body)。這些消息主體(message-body)僅僅當傳輸編碼(transfer-coding)應用於傳輸譯碼(Transfer-Encoding)頭域時才和實體主體(entity-body)不一樣,其它狀況消息主體和實體主體相同。傳輸譯碼頭域在14.41節闡述。
message-body=entity-body|<entity-body encoded as per Transfer-Encoding>
傳輸譯碼頭域被用來指明應用程序的傳輸編碼,它是爲了保證安全和適合的消息傳輸。傳輸譯碼(Transfer-Encoding)頭域是消息的屬性,而不是實體的屬性,而且沿着請求/響應鏈能被添加或刪除。(然而,3.6節描述了一些限制當使用某個傳輸編碼時)
何時消息主體(message-body)容許出如今消息中,這根據不一樣請求和響應來決定的。
請求中消息主體(message-body)的存在是被請求中消息頭域中是否存在內容長度(Content-Length)或傳輸譯碼(Transfer-Encoding)頭域來暗示的。一個消息主體(message-body)不能被包含在請求裏若是請求方法(見5.1.1節)不容許請求裏包含實體主體(entity-body)。一個服務器應該能閱讀或再次轉發請求裏的消息主體;若是請求方法不容許包含一個實體主體(entity-body),那麼消息主體應該被忽略當服務器處理這個請求時。
對於響應消息,消息裏是否包含消息主體依賴相應的請求方法和響應狀態碼。全部HEAD請求方法的請求的響應消息不能包含消息主體,即便實體頭域出如今請求裏。全部1XX(信息的),204(無內容的)和304(沒有修改的)的響應都不能包括一個消息主體(message-body)。全部其餘的響應必須包括消息主體,雖然它可能長度爲零.
4.4 消息的長度(Message Length)
一條消息的傳輸長度(transfer-length)是消息主體(message-body)的長度,當消息主體出如今消息中時;那就是說在實體主體被應用了傳輸編碼(transfer-coding)後。當消息中出現消息主體時,消息主體的傳輸長度(transfer-length)由下面(以優先權的順序)決定::
1。任何不能包含消息主體(message-body)的消息(這種消息如1xx,204和304響應和任何HEAD請求的響應)老是被頭域後的第一個空行(譯註:CRLF)終止,無論消息裏是否有實體頭域(entity-header fields)。
2。若是Transfer-Encoding頭域(見14.41節)出現,而且它的域值不是」identity」,那麼傳輸長度(transfer-length)被「塊」傳輸編碼定義,除非消息由於關閉鏈接而被終結了。
3。若是Content-Length頭域(屬於實體頭域)(見14.13節)出現,那麼它的十進制值(以字節表示)就表明實體主體長度(entity-length,譯註:實體長度其實就是實體主體的長度,之後把entity-length翻譯成實體主體的長度)也表明傳輸長度(transfer-length)。Content-Length頭域不能包含在消息中,若是實體主體長度(entity-length)和傳輸長度(transfer-length)二者不相等(也就是說,消息裏應用了傳輸譯碼(Transfer-Encoding)頭域)。若是一個消息即有傳輸譯碼(Transfer-Encoding)頭域而且也Content-Length頭域,後者會被忽略。
4。若是消息用到媒體類型「multipart/byteranges」,而且傳輸長度(transfer-length)另外也沒有指定,那麼這種自我定界的媒體類型定義了傳輸長度(transfer-length)。這種媒體類型不能被利用除非發送者知道接收者能怎樣去解析它; HTTP1.1客戶端請求裏若是出現Range頭域而且帶有多個字節範圍(byte-range)指示符,這就意味着客戶端能解析multipart/byteranges響應。
一個Range請求頭域可能會被一個不能理解multipart/byteranges的HTTP1.0代理(proxy)再次轉發;在這種狀況下,服務器必須能定界此消息利用這節的1,3或5項裏定義的方法。
5。經過服務器關閉鏈接能肯定消息的傳輸長度。(關閉鏈接並不能用來指明請求消息體的結束,由於這樣可讓服務器沒有機會繼續給予響應)。
爲了與HTTP/1.0應用程序兼容,包含HTTP/1.1消息主體的請求必須包括一個有效的內容長度(Content-Length)的頭域,除非服務器是和HTTP/1.1遵循的。若是一個請求包含一個消息主體而且沒有給出內容長度(Content-Length),那麼服務器應該以400響應(錯誤的請求)若是他不能判斷消息長度的話,或者以411響應(要求長度)若是它堅持想要收到一個有效內容長度(Content-length)。
全部的能接收實體的HTTP/1.1應用程序必須能接受"chunked"的傳輸編碼(3.6節),所以能夠容許這種機制來處理消息當消息的長度不能被提早決定時。
消息不能同時都包括內容長度(Content-Length)頭域和非identity傳輸編碼。若是消息包括了一個非identity的傳輸編碼,內容長度(Content-Length)頭域必須被忽略.
當內容長度(Content-Length)頭域出現一個具備消息主體(message-body)的消息裏,它的域值必須精確匹配消息主體裏字節數量。HTTP/1.1用戶代理必須通知用戶當一個無效的長度接收了。
4.5 經常使用頭域(General Header Fields)
有一些頭域即適用於請求也適用於響應消息,可是這些頭域並不適合被傳輸的實體。這些頭域只能應用與被傳輸的消息。
general-header = Cache-Control ; Section 14.9
| Connection ; Section 14.10
| Date ; Section 14.18
| Pragma ; Section 14.32
| Trailer ; Section 14.40
| Transfer-Encoding ; Section 14.41
| Upgrade ; Section 14.42
| Via ; Section 14.45
| Warning ; Section 14.46
經常使用頭域的名能被擴展,但這要和協議版本的變化相結合。然而,新的或實驗性的頭域可能被賦予經常使用頭域的語意,若是通訊裏的全部參與者都認爲他們是經常使用頭域。不被識別的頭域會被做爲實體頭(entity-header)頭域來看待。
5 請求(Request)
一個請求消息是從客戶端到服務器端的,在消息首行裏包含方法,資源指示符,協議版本。
Request = Request-Line ; Section 5.1
*(( general-header ; Section 4.5
| request-header ; Section 5.3
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 4.3
5.1 請求行 (Request-Line)
請求行(Request-Line)是以一個方法標記開始,後面跟隨Request-URI和協議版本,最後以CRLF結束。元素是以SP字符分隔。CR或LF是不被容許的除了最後的CRLF。
Request-Line =Method SP Request-URL SP HTTP-Version CRLF
5.1.1方法 (Method)
方法標記指示了在被Request-URI指定的資源上執行的方法。這種方法是大小寫敏感的。
Method = "OPTIONS" ;9.2節
| "GET" ;9.3節
| "HEAD" ;9.4節
|"POST" ;9.5節
|"PUT" ;9.6節
|"DELETE" ;9.7節
|"TRACE" ;9.8節
|"CONNECT" ;9.9節
| extension-method
Extension-method = token
資源容許的方法由Allow頭域指定(14.7節)。響應的返回碼老是通知客戶是否一個方法對一個資源在當前是被容許的,由於被容許的方法集合能被動態的改變。一個源服務器應該返回405狀態碼(方法不能容許)若是此方法對於一個請求資源在服務器那裏不被容許,而且返回501狀態碼(沒有實現)若是此方法不被源服務器識別或實現。方法GET和HEAD必須被全部常規目的的服務器支持。全部其它的方法是可選的;然而,若是上面的全部方法都被實現,這些方法必須遵循的語意和第9節指定的相同。
5.1.2請求URL(Request-URI)
Request-URI是一種全球統一資源標識符(3.2 節),而且它指定請求的資源。
Request-URI ="*" | absoluteURI | abs_path | authotity
Request-URI的OPTIONS依賴於請求的性質。星號"*"意味着請求不能應用於一個特定的資源,可是能應用於服務器,而且只能被容許當使用的方法不能應用於資源的時候。舉例以下
OPTIONS * HTTP/1.1
當向代理(proxy)提交請求時,絕對URI(absoluteRUI)是不可缺乏的。代理(proxy)可能會被要求再次轉寄此請求。注意:代理可能再次提交此請求到另外一個代理或直接給源服務器。爲了不循環請求,代理(proxy)必須能識別全部的服務器名字,包括任何別名,本地變量,數字IP地址。一個請求行(Request-Line)的例子以下:
GET http://www.w3.org/pub/www/TheProject.html HTTP/1.1
爲了將來HTTP版本的全部請求能遷移到絕對URI(absoluteURI)地址,全部基於HTTP/1.1的服務器必須接受絕對URL地址,即便HTTP/1.1的客戶端只向代理產生給絕對URI(absoluteURI)。
authority部分只被用於CONNECT方法(9.9節).
Request-URI大多數狀況是被用於指定一個源服務器或網關(gateway)上的資源。這種狀況下,URI的絕對路徑(abs_path)必須被用做Request-URI,而且此URI(authority)的網絡位置必須在Host頭域裏指出。例如:客戶但願直接從源服務器獲取資源,這種狀況下,它可能會創建一個TCP鏈接,此鏈接是特定於主機」www.w3.org」的80端口的,這是會發送下面行:
GET /pub/WWW/TheProject.html HTTP/1.1
Host:www.w3.org
接下來是請求的其餘部分,注意絕對路徑不能是空的;若是在原始的URI裏沒有出現絕對路徑,必須給出"/"(服務器根目錄).
Request-URI是以3.2.1節裏指定的格式傳輸。若是Request-URI用"%HEX HEX"[42]編碼,源服務器爲了解析請求必須能解碼它。服務器接收到一個無效的Request-URI時必須以一個合適的狀態碼響應。
透明代理(proxy)不能重寫接收到的Request-URI裏的」abs_path」當它轉寄此請求到下一個服務器時,除了根據上面聲明的把一個空的abs_path用」/」代替。
注:不重寫的規則防止了代理(proxy)改變請求的意思,當源服務器不能正確的利用非保留(non-reserved)的URI字符時 。實現者應該知道某些pre-HTTP/1.1代理(proxy)能重寫Request-URI。
5.2請求資源 (The Resource Identified by a Request)
請求裏資源的精肯定位是由請求裏的Request-URI和Host頭域決定的。
若是源服務器資源不依賴於請求的Host頭域指定的主機(譯註:可能會存在虛擬主機),那麼它會忽略請求的頭域當它決定其資源的時候。(對於一個支持Host的HTTP/1.1服務器,在19.6.1.1節描述了其餘的需求).
源服務器若是根據請求裏的主機區別資源(這是由於存在虛擬主機和虛擬主機名),它必須遵循下面的規則去決定請求的資源當出現一個HTTP/1.1請求時:
1. 若是Request-URI是絕對地址(absoluteURI),這時請求裏的主機存在於Request-URI裏。任何出如今請求裏Host頭域值應當被忽略。
2. 假如Request-URI不是絕對地址(absoluteURI),而且請求包括一個Host頭域,則主機由該Host頭域值決定.
3. 假如由規則1或規則2定義的主機是一個無效的主機,則應當以一個400(錯誤請求)錯誤消息返回。
缺乏Host頭域的HTTP/1.0請求的接收者可能會推測決定什麼樣的資源被請求(例如:檢查URI的路徑對於某個特定的主機是惟一的)。
5.3請求報頭域 (Request Header Fields)
請求頭域容許客戶端傳遞請求的附加信息和客戶端本身的附加信息給服務器。這些頭域做爲請求的修飾符,這和程序語言方法調用的參數語義是同樣的。
請求頭(request-header) = Accept ;14.1節
| Accept-Charset ;14.2節
|Accept-Encoding ;14.3節
|Accept-Language ;14.4節
|Authorization ;14.8節
|Expect ;14.20節
|From ;14.22節
|Host ;14.23節
|If-Match ;14.24節
|If-Modified-Since ;14.25節
| If-None-Match ;14.26節
| If-Range ;14.27節
| If-Unmodified-Since ;14.28節
| Max-Forwards ;14.31節
| Proxy-Authorization ;14.34節
| Range ;14.35節
| Referer ;14.36節
|TE ;14.39節
| User-Agent ;14.43節
請求頭域的名字是能結合於協議版本而能被擴展的。然而新的或實驗性的頭域應該被給出請求頭域的語義若是通訊的全部方都把它看做請求頭域。不能識別的頭域會被看做實體頭域(entity-header)。
6 響應 (Response)
接收和翻譯一個請求消息後,服務器發出一個HTTP響應消息。
response =Status-Line ;6.1節
*(( general-header) ; 4.5節
| response-header ;6.2節
| entity-header)CRLF) ;7.1節
CRLF
[ message-body ] ;7.2節
6.1 狀態行 (Status-Line)
響應消息的第一行是狀態行(stauts-Line),由協議版本以及數字狀態碼和相關的文本短語組成,各部分間用空格符隔開,除了最後的回車或換行外,中間不容許有回車換行.
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
6.1.1狀態碼與緣由短語 (Status Code and Reason Phrase)
狀態碼是試圖理解和知足請求的三位數字的整數碼,這些碼的完整定義在第十章。緣由短語(Reason-Phrase)是爲了給出的關於狀態碼的文本描述。狀態碼用於控制條件,而緣由短語(Reason-Phrase)是讓用戶便於閱讀。客戶端不須要檢查和顯示緣由短語。
狀態碼的第一位數字定義響應類型。後兩位數字沒有任何分類角色。第一位數字有五種值:
-1xx: 報告的 - 接收到請求,繼續進程.
-2xx 成功 - 步驟成功接收,被理解,並被接受
-3xx 重發 - 爲了完成請求,必須採起進一步措施.
-4xx 客戶端出錯 - 請求包括錯的順序或不能完成.
-5xx 服務器出錯 - 服務器沒法完成顯然有效的請求.
下面列舉了爲HTTP/1.1定義的態碼值,和對應的緣由短語(Reason-Phrase)的例子。緣由短語在這裏例舉只是建議性的----它們也許被一個局部的等價體代替而不會影響此協議的語義。
Status-Code =
"100" ; 10.1.1節: 繼續
|"101" ; 10.1.2節: 轉換協議
|"200" ; 10.2.1節: OK
|"201" ; 10.2.2節: 建立
|"202" ; 10.2.3節: 接受
|"203" ; 10.2.4節: 非權威信息
|"204" ; 10.2.5節: 無內容
|"205" ; 10.2.6節: 重置內容
|"206" ; 10.2.7節: 局部內容
|"300" ; 10.3.1節: 多樣選擇
|"301" ; 10.3.2節: 永久移動
|"302" ; 10.3.3節: 建立
|"303" ; 10.3.4節: 觀察別的部分
|"304" ; 10.3.5節: 只讀
|"305" ; 10.3.6節: 用戶代理
|"307" ; 10.3.8節 臨時重發
|"400" ; 10.4.1節: 壞請求
|"401" ; 10.4.2節: 未受權的
|"402" ; 10.4.3節: 必要的支付
|"403" ; 10.4.4節: 禁用
|"404" ; 10.4.5節: 沒找到
|"405" ; 10.4.6節: 不容許的方式
|"406" ; 10.4.7節: 不接受
|"407" ; 10.4.8節: 須要代理驗證
|"408" ; 10.4.9節: 請求超時
|"409" ; 10.4.10節; 衝突
|"410" ; 10.4.11節: 中止
|"411" ; 10.4.12節: 須要的長度
|"412" ; 10.4.13節; 預處理失敗
|"413" ; 10.4.14節: 請求實體太大
|"414" ; 10.4.15節; 請求-URI太大
|"415" ; 10.4.16節: 不支持的媒體類型
|"416" ; 10.4.17節: 請求的範圍不知足
|"417" ; 10.4.18節: 指望失敗
|"500" ; 10.5.1節: 服務器內部錯誤
|"501" ; 10.5.2節: 不能實現
|"502" ; 10.5.3節: 壞網關
|"503" ; 10.5.4節: 服務不能實現
|"504" ; 10.5.5節: 網關超時
|"505" ; 10.5.6節: HTTP版本不支持
|擴展碼
extension-code =3DIGIT
Reason-Phrase = *<TEXT,excluding CR,LF>
HTTP狀態碼是可擴展的。HTTP應用程序不須要理解全部已註冊狀態碼的含義,儘管那樣的理解顯而易見是很合算的。可是,應用程序必須瞭解由第一位數字指定的狀態碼的類型,任何未被識別的響應應被看做是該類型的x00狀態,有一個例外就是未被識別的響應不能緩存。例如,若是客戶端收到一個未被識別的狀態碼431,則能夠安全的假定請求有錯,而且它會對待此響應就像它接收了一個狀態碼是400的響應。在這種狀況下,用戶代理(user agent)應當把實體和響應一塊兒提交給用戶,由於實體極可能包括人可讀的關於解釋不正常狀態的信息。
6.2響應頭域 (Response Header Fields)
響應頭域容許服務器傳送響應的附加信息,這些信息不能放在狀態行(Status-Line)裏.。這些頭域給出有關服務器的信息以及請求URI(Request-URI)指定的資源的更進一步的訪問。
response-header = Accept-Ranges ; 14.5節
|Age ; 14.6節
|Etag ; 14.19節
|Location ; 14.30節
|Proxy-Autenticate ; 14.33節
|Retry-After ; 14.37節
|Server ; 14.38節
|Vary ; 14.44節
|WWW-Authenticate ; 14.47節
響應頭域的名字能依賴於協議版本的變化而擴展。然而,新的或者實驗性的頭域可能會給於響應頭域的語義若是通訊的成員都能識別他們並把他們看做響應頭域。不被識別的頭域被看做實體頭域。
7 實體(Entity)
若是不被請求的方法或響應的狀態碼所限制,請求和響應消息均可以傳輸實體。 實體包括實體頭域(entity-header)與實體主體(entity-body),而有些響應只包括實體頭域(entity-header)。
在本節中的發送者和接收者是不是客戶端或服務器,這依賴於誰發送或誰接收此實體。
7.1 實體報文域(Entity Header Fields)
實體(entity-header)頭域定義了關於實體主體的的元信息,或在無主體的狀況下定義了請求的資源的元信息。有些元信息是可選的;一些是必須的。
entity-header = Allow ; Section 14.7
| Content-Encoding ; Section 14.11
| Content-Language ; Section 14.12
| Content-Length ; Section 14.13
| Content-Location ; Section 14.14
| Content-MD5 ; Section 14.15
| Content-Range ; Section 14.16
| Content-Type ; Section 14.17
| Expires ; Section 14.21
| Last-Modified ; Section 14.29
| extension-header
extension-header = message-header
擴展頭機制容許在不改變協議的前提下定義額外的實體頭域,但不保證這些域在接收端可以被識別。未被識別的頭域應當被接收者忽略,且必須被透明代理(transparent proxy)轉發。
7.2 實體主體(Entity Body)
由HTTP請求或響應發送的實體主體(若是存在的話)的格式與編碼方式應由實體的頭域決定。
Entity-body= *OCTET
如4。3節所述,實體主體(entity-body)只有當消息主體存在時時才存在。實體主體(entity-body)從消息主體經過傳輸譯碼頭域(Transfer-Encoding)譯碼獲得,傳輸譯碼用於確保消息的安全和合適的傳輸。
7.2.1類型(Type)
當消息包含實體主體(entity-body)時,主體的數據類型由實體頭域Content-Type和Content-Encoding決定。這些頭域定義了兩層的順序的編碼模型:
Entity-body:=Content-Encoding( Content-Type( data) )
Content-Type指定了下層數據的媒體類型。Content-Encoding可能被用來指定附加的應用於數據的內容編碼,常常用於數據壓縮的目的,內容編碼是請求資源的屬性。沒有缺省的譯碼。
任一包含了實體主體的HTTP/1.1消息都應包括Content-Type頭域以定義實體主體的媒體類型。若是而且只有媒體類型沒有經過Content-Type頭域指定時,接收者可能會嘗試猜想媒體類型,這經過觀察實體主體的內容而且/或者經過觀察URI指定資源的擴展名。若是媒體類型仍然不知道,接收者應該把類型看做」application/octec-stream」。
7.2.2實體主體長度(Entity Length)
消息的實體主體長度指的是消息主體在被應用於傳輸編碼(transfer-coding)以前的長度。4.4節定義了怎樣去肯定消息主體的傳輸長度。
8 鏈接
8.1 持續鏈接(Persistent Connection)。
8.1.1目的
在持續鏈接以前,爲獲取每個URL指定的資源都必須創建了獨立的TCP 鏈接, 這就加劇了HTTP服務器的負擔,易引發互聯網的阻塞。嵌入的圖片與其它相關數據一般使用戶在短期內對同一服務器提交多個請求。目前已有針對這些性能問題的分析以及原型實現的結果[26][30]。 對其餘方法也有了初步探究,如T/TCP [27]。
持續HTTP 鏈接有着諸多的優勢:
--- 經過創建與關閉較少的TCP鏈接,不只節省了路由器與主機(客戶端,服務器,代理服務器,網關,隧道或緩存)的CPU時間,還節省了主機用於TCP協議控制塊的內存。
---能在鏈接上進行流水線請求方式。 流水線請求方式能容許客戶端執行屢次請求而不用等待每個請求的響應(譯註:即客戶端能夠發送請求而不用等待之前的請求的響應到來後再發請求),而且此時只進行了一個TCP鏈接,從而效率更高,減小了時間。
--- 網絡阻塞會被減小,這是因爲TCP鏈接後減小了包的數量,而且因爲容許TCP有充分的時間去決定網絡阻塞的狀態。
--- 由於無須在建立TCP鏈接時的握手上耗費時間,而使後續請求的等待時間減小。
---HTTP改進的愈來愈好,由於在不須要關閉TCP鏈接的代價下能夠報告錯誤。未來的HTTP版本客戶端能夠樂觀的嘗試一個新的特性,可是若是和老的服務器通訊時,在錯誤被報告後就要用舊的語義而進行從新嘗試鏈接。
HTTP實現應該實現持久鏈接。
8.1.2整體操做
HTTP/1.1 與早期HTTP 版本的一個顯著區別在於持續鏈接是任何HTTP/1.1鏈接的缺省方式。也就是說,除非另有指定,客戶端總應當假定服務器會保持持續鏈接,即使在接到服務器的出錯響應時也應如此。
持續鏈接提供了一種能夠由客戶端或服務器發信號來終止TCP鏈接的機制。利用Connect頭域(14。10節)能夠產生終止鏈接信號。一旦出現了終止鏈接的信號,客戶端便不可再向此鏈接提出任何新請求。
8.1.2.1 協商(Negotiation)
除非請求的Connect頭域中包含了"close"標籤,HTTP/1.1服務器總能夠假定HTTP/1.1 客戶端想要維持持續鏈接(persistent connection)。若是服務器想在發出響應後當即關閉鏈接,它應當發送一個含」close」的Connect頭域。
一個HTTP/1.1客戶端可能指望保持鏈接一直開着,但這必須是基於服務器響應裏是否包含一個Connect頭域而且此頭域裏是否包含」close」。若是客戶端不想爲更多的請求維持鏈接,它應該發送一個值爲」close」的Connect頭域。
若是客戶端和服務器之一在發送的Connect頭域裏包含」close」,那麼客戶端的請求將會變爲此鏈接的最後一個請求。。
客戶端和服務器不該該認爲持續鏈接是低於1.1的HTTP版本所擁有的,除非它被顯示地指明瞭。19.6.2節指出了跟HTTP/1.1客戶端兼容的更多信息。
8.1.2.2 流水線(pilelining)
支持持續鏈接(persistent conncetio)的客戶端能夠以流水線的方式發送請求(即無須等待響應而發送多個請求)。服務器必須按接收請求的順序發送響應。
假定持續鏈接而且在鏈接創建後進行流水線方式請求的客戶端應該準備去從新嘗試他們的鏈接若是第一個流水線請求方式嘗試失敗。若是客戶端從新嘗試鏈接,在客戶端知道鏈接是持續以前客戶端不能進行流水線發送請求。客戶端必須準備去從新發送請求若是服務器在響應全部對應的請求以前關閉鏈接
客戶端不該該利用非等冪的方法或者非等冪的方法序列(見9.1.2節)進行流水線方式的請求。不然一個過早的傳輸層鏈接的終止可能會致使不肯定的結果。一個可能但願發送一個非等冪方法請求的客戶端只有接收了上次它發出請求的響應後才能再次發送請求給服務器。
8.1.3代理服務器 (Proxy Servers)
它是很是重要的由於代理服務器正確地實現了Connect頭域的屬性,這在14.10節指出了。
代理服務器必須分別向和它相連的客戶端或者源服務器(或其餘的代理服務器)指明持續鏈接。每個持續鏈接只能應用於一個傳輸層鏈接。
代理服務器不能和一個HTTP/1.0客戶端創建一個HTTP/1.1持續鏈接(可是參見RFC2068[33]裏的關於許多HTTP/1.1客戶端利用Keep-Alive頭域的問題的討論)。
8.1.4實際的考慮 (Practical Considerations)
服務器一般有一個時限值,超過必定時間即再也不維持處於非活動的鏈接。代理服務器會選一個較高的值,由於客戶端極可能會與同一服務器創建多個鏈接。持續鏈接方式的採用對於客戶端與服務器的時限均未提出任何要求。
當客戶端或服務器但願超時終止時, 它應該按規範終止傳輸鏈接。客戶端與服務器端應始終注意對方是否終止了鏈接,並適當的予以響應。若客戶端或服務器未能及時檢測到對方已終止了鏈接,將會形成沒必要要的網絡資源浪費。
客戶端,服務器,或代理服務器可能在任意時刻會終止傳輸鏈接。好比,客戶端可能正想發出新的請求,而此時服務器卻決定關閉"閒置"的鏈接。在服務器看來,鏈接已經由於閒置被關閉了, 但客戶端認爲我正在請求。
這代表客戶端,服務器與代理服務器必須有能力從異步的鏈接終止事件中恢復。只要請求是等冪的(見9.1.2節),客戶端軟件應該能從新打開傳輸層鏈接並從新傳輸遺棄的請求序列而不須要用戶進行交互來實現。對非等冪方法的請求不能自動進行重試請求,儘管客戶代理(user agent)可能能提供一我的工操做去重試這些請求。應該用用戶代理(user-agent)軟件對應用程序語義識別的確認來替代用戶的確認。若是再次重試請求失敗,那麼就不能再進行重複請求了。
服務器儘量應該在每次鏈接中至少響應一個請求。除非出於網絡或客戶端的故障,服務器不該在傳送響應的中途斷開鏈接。
使用持續鏈接的客戶端應限制與某一服務器同時鏈接的個數。單用戶客戶端不該與任一服務器或代理服務器保持兩個以上的鏈接。代理服務器與其它服務器或代理服務器之間應維護2*N個鏈接,其中N是同時在線的用戶數。這些準則是爲了改善響應時間和和避免阻塞。
8.2 消息傳送要求(Message Transmission Requirements)
8.2.1持續鏈接與流量控制 (Persistent Connections and Flow Control)
HTTP/1.1服務器應當保持持續鏈接並使用TCP流量控制機制來解決臨時過載,而不是在終止鏈接後期望客戶端的重試。後一方法會惡化網絡阻塞。
8.2.2監視鏈接中出錯狀態的消息
HTTP/1.1(或更新)客戶端應在發送消息主體的時候同時監視網絡鏈接是否處於出錯狀態。若客戶端發現了錯誤,它應當當即中止消息主體的的傳送。若正文是以塊傳輸編碼方式發送的(3.6節),能夠用長度爲零的塊和空尾部來提早標記報文結束。若消息主體前有Content-Length頭域,則客戶端必須關閉鏈接。
8.2.3 100狀態碼的用途
100狀態碼(繼續,見10.1.1節)的目的在於容許客戶端斷定服務器是否願意接受客戶端發來的消息主體(基於請求頭域)在客戶端發送此請求消息主體前。 在有些狀況下,若是服務器拒絕查看消息主體,這時客戶端發送消息主體是不合適的或會下降效率。
HTTP/1.1客戶端的要求:
--- 若客戶端要在發送請求消息主體以前等候100(繼續)響應,則它必須發送一個Expect請求頭域(見14.20節),而且值是」100-continue」。
--- 客戶端不能發送一個值是」100-continue」的Expect請求頭域,若是此客戶端不打算髮送帶消息主體的請求。
因爲存在舊的實現方法,協議容許二義性的情形存在,這在客戶端在發送」Expect:100-continue」後而沒有接收一個417(指望失敗)狀態碼或着100(繼續)狀態碼的狀況下發生。所以,當一個客戶端發送此頭域給一個源服務器(可能經過代理),此服務器也沒有以100(繼續)狀態碼響應,那麼客戶端不該該在發送請求消息的主體前無限等待。
HTTP’/1.1源服務器的要求:
--- 當接收一個包含值爲」100-contitue」的Expect請求頭域的請求時,源服務器必須或者以100(繼續)狀態碼響應而且繼續從輸入流裏接收數據,或者以final狀態碼響應。源服務器不能在發送100(繼續)狀態碼響應以前接收請求主體。若是服務器以final狀態碼響應後,它可能會關閉傳輸層鏈接或者它也可能會繼續接收或遺棄剩餘的請求。可是既然它返回了一個final狀態碼的響應,它就不能再去那個執行請求的方法(如:POST方法,PUT方法)。
--- 如請求消息不含值爲"100-continue"的Expect請求頭域, 源服務器不該發送100(繼續)響應。當請求來自HTTP/1.0(或更早)的客戶端時也不得發送100(繼續)響應。對此規定有一例外:爲了與RFC 2068兼容,源服務器可能會發送一個100(繼續)狀態響應以響應HTTP/1.1的PUT或POSt請求,雖然這些請求中沒有包含值爲」100-continue」的Expect請求頭域。這個例外的目的是爲了減小任何客戶端由於等待100(繼續)狀態響應的延時,但此例外只能應用於HTTP/1.1請求,並不適合於其餘HTTP版本的請求。
--- 若已經接收到部分或所有請求的消息的主體,源服務器能夠不須要發100(繼續)響應。
--- 發送100(繼續)響應的源服務器必須最終能發送一個final狀態響應,一旦請求消息主體被它接收到而且已經被它處理了,除非源服務器過早切斷了傳輸層鏈接。
--- 若源服務器接收到不含值爲"100-contitue"的Expect請求頭域的請求,該請求含有請求消息主體,而服務器在從傳輸層鏈接上接收整個請求消息主體前返回一個final的狀態響應,那麼此源服務器不能關閉傳輸層鏈接直到它接收了整個請求或者直到客戶端關閉了此鏈接。不然客戶端可能不會信任接收此響應消息。然而,這一要求不該該被解釋用來防止服務器抵抗服務攻擊,或者防止服務器被客戶端實現攻擊。
對HTTP/1.1代理服務器的要求:
--- 若代理服務器接到一個請求,此請求包含值爲"100-continue"的Expect請求頭域,而且代理服務器可能知道下一站點的服務器遵循HTTP/1.1或更高版協議,或者不知道下一站點服務器的HTTP版本,那麼它必須包含此Expect頭域來轉發此請求。
--- 若代理服務器知道下一站點服務器版本是HTTP/1.0或更低,則它不能轉發此請求,而且它必須以417(指望失敗)狀態響應。
--- 代理服務器應當維護一個緩存,以記錄最近訪問下一站點服務器的HTTP版本號。
--- 若接收到的請求來自於版本是HTTP/1.0(或更低)的客戶端,而且此請求不含值爲"100-continue"的Expect請求頭域,那麼代理服務器不能轉發100(繼續)響應。 這一要求可覆蓋1xx響應轉發的通常規則(參見10.1節)。
8.2.4服務器過早關閉鏈接時客戶端的行爲
若是HTTP/1.1 客戶端發送一條含有消息主體的請求消息,但不含值爲"100-continue"的Expect請求頭域,而且客戶端直接與HTTP/1.1源服務器相連,而且客戶端在接收到服務器的狀態響應以前看到了鏈接的關閉,那麼客戶端應該重試此請求。在重試時,客戶端能夠利用下面的算法來得到可靠的響應。
1. 向服務器發起一新鏈接。
2. 發送請請求頭域。
3. 初始化變量R,使R的值爲通往服務器的往返時間的估計值(好比基於創建鏈接的時間),或在沒法估計往返時間時設爲一常數值5秒。
4. 計算T=R*(2**N),N爲此前重試請求的次數。
5. 等待服務器出錯響應,或是等待T秒(二者中時間較短的)。
6. 若沒等到出錯響應,T秒後發送請求的消息主體。
7. 若客戶端發現鏈接被提早關閉,轉到第1步,直到請求被接受,接收到出錯響應,或是用戶因不耐煩而終止了重試過程。
在任意點上,客戶端若是接收到服務器的出錯響應,客戶端
--- 不該再繼續發送請求, 而且
--- 應該關閉鏈接若是客戶端沒有完成發送請求消息。
9 方法定義(Method Definitions)
HTTP/1.1經常使用方法的定義以下。雖然方法能夠被展開,但新加的方法不能認爲能分享與擴展的客戶端和服務器一樣的語義。
Hst請求頭域(見13.23節)必須能在全部的HTTP/1.1請求裏出現。
9.1 安全和等冪(Idempotent)方法
9.1.1安全方法(Safe Methods)
實現者應當知道軟件是表明用戶在互聯網上進行交互,而且應該當心地容許用戶知道任何它們可能採起的動做(action),這些動做可能給他們本身或他人帶來沒法預料的結果。
特別的,GET和HEAD方法僅僅應該獲取資源而不是執行動做(action)。這些方法應該被考慮是「安全」的。可讓用戶代理用其餘的方法,如:POST,PUT,DELETE,這樣用戶代理就能知道這些方法可能會執行不安全的動做。
天然的,保證當服務器因爲執行GET請求而不能產生反作用是不可能的;實際上,一些動態的資源會考慮這個特性。用戶並無請求這些反作用,所以不須要對這些反作用負責。
9.1.2等冪方法(Idempotent Mehtods)
方法能夠有等冪的性質由於(除了出錯或終止問題)N>0個相同請求的反作用同單個請求的反作用的效果是同樣(譯註:等冪就是值不變性,相同的請求獲得相同的響應結果,不會出現相同的請求出現不一樣的響應結果)。方法GET,HEAD,PUT,DELETE都有這種性質。一樣,方法OPTIONS和TRACE不該該有反作用,所以具備內在的等冪性。然而,有可能幾個請求的序列是不等冪的,即便在那樣的序列中全部方法都是等冪的。(若是整個序列總體的執行的結果老是相同的,而且此結果不會由於序列的總體,部分的再次執行而改變,那麼此序列是等冪的。)例如,一個序列是非等冪的若是它的結果依賴於一個值,此值在之後相同的序列裏會改變。
根據定義,一個序列若是沒有反作用,那麼此序列是等冪的(假設在資源集上沒有並行的操做)。
9.2 OPTIONS(選項)
OPTIONS方法代表請求想獲得請求/響應鏈上關於此請求裏的URI(Request-URI)指定資源的通訊選項信息。此方法容許客戶端去斷定請求資源的選項和/或需求,或者服務器的能力,而不須要利用一個資源動做(譯註:使用POST,PUT,DELETE方法)或一個資源獲取(譯註:用GET方法)方法。
這種方法的響應是不能緩存的.。
若是OPTIONS請求消息裏包括一個實體主體(當請求消息裏出現Content-Length或者Transfer-Encoding頭域時),那麼媒體類型必須經過Content-Type頭域指明。雖然此規範沒有定義如何使用此實體主體,未來的HTTP擴展可能會利用OPTIONS請求的消息主體去獲得服務器得更多信息。一個服務器若是不支持OPTION請求的消息主體,它會遺棄此請求消息主體。
若是請求URI是一個星號("*"),,OPTIONS請求將會應用於服務器的全部資源而不是特定資源。由於服務器的通訊選項一般依賴於資源,因此」*」請求只能在「ping」或者「no-op」方法時纔有用;它幹不了任何事情除了容許客戶端測試服務器的能力。例如:它能被用來測試代理是否遵循HTTP/1.1。
若是請求URI不是一個星號("*"),,OPTIONS請求只能應用於請求URI指定資源的選項。
200響應應該包含任何指明選項性質的頭域,這些選項性質由服務器實現而且只適合那個請求的資源(例如,Allow頭域),但也可能包一些擴展的在此規範裏沒有定義的頭域。若是有響應主體的話也應該包含一些通訊選項的信息。這個響應主體的格式並無在此規範裏定義,可是可能會在之後的HTTP裏定義。內容協商可能被用於選擇合適的響應格式。若是沒有響應主體包含,響應就應該包含一個值爲「0」的Content-Length頭域。
Max-Forwards請求頭域可能會被用於針對請求鏈中特定的代理。當代理接收到一個OPTIONS請求,且此請求的URI爲absoluteURI,而且此請求是能夠被轉發的,那麼代理必需要檢測Max-Forwards頭域。若是Max-Forwards頭域的值爲「0」,那麼此代理不能轉發此消息;而是,代理應該以它本身的通訊選項響應。若是Max-Forwards頭域是比0大的整數值,那麼代理必須遞減此值當它轉發此請求時。若是沒有Max-Forwards頭域出如今請求裏,那麼代理轉發此請求時不能包含Max-Forwards頭域。
9.3 GET
GET方法意思是獲取被請求URI(Request-URI)指定的信息(以實體的格式)。若是請求URI涉及到一個數據生成過程,那麼這個生成的數據應該被做爲實體在響應中返回,但這並非過程的資源文本,除非資源文本剛好是過程的輸出(譯註:URI指示的資源是動態生成的)。
若是請求消息包含 If-Modified-Since,,If-Unmodified-Since,If-Match,,If-None-Match,或者 If-Range頭域,,GET的語義將變成「條件(conditionall) GET」。一個條件GET方法會請求知足條件頭域的實體。條件GET方法的目的是爲了減小沒必要要的網絡使用,這經過利用緩存的實體的更新,從而不用屢次請求或傳輸客戶已經擁有的數據。.
若是請求方法包含一個Range頭域,那麼GET方法就變成「部分Get」方法。一個部分GET會請求實體的一部分,這在14.35節裏描述了。 部分GET方法的目的是爲了減小沒必要要的網絡使用,這經過容許獲取部分實體,從而不須要傳輸客戶端已經擁有的數據。
GET請求的響應是可緩存的(cacheable)若是此響應知足第13節HTTP緩存的要求。
看15.1.3節關於GET請求用於表單時安全考慮。
9.4 HEAD
HEAD方法和GET方法一致,除了服務器不能在響應裏返回消息主體。HEAD請求響應裏HTTP頭域裏的元信息應該和GET請求響應裏的元信息一致。此方法被用來獲取請求實體的元信息而不須要傳輸實體主體(entity-body)。此方法常常被用來測試超文本連接的有效性,可訪問性,和最近的改變。.
HEAD請求的響應是可緩存的,由於響應裏的信息可能被用於更新之前的那個資源的緩存實體.。若是出現一個新的域值指明瞭緩存實體和當前源服務器上實體的不一樣(可能由於Content-Length,Content-MD5,ETag或Last-Modified值的改變),那麼緩存(cache)必須認爲此緩存項是過期的(stale)。
9.5 POST
POST 方法被用於請求源服務器接受請求中的實體做爲請求資源的一個新的從屬物。POST被設計涵蓋下面的功能。
-已存在的資源的註釋;
-發佈消息給一個佈告板,新聞組,郵件列表,或者類似的文章組。
-提供一個數據塊,如提交一個表單給一個數據處理過程。
-經過追加操做來擴展數據庫。
POST方法的實際功能是由服務器決定的,而且常常依賴於請求URI(Request-URI)。POST提交的實體是請求URI的從屬物,就好像一個文件從屬於一個目錄,一篇新聞文章從屬於一個新聞組,或者一條記錄從屬於一個數據庫。
POST方法執行的動做可能不會對請求URI所指的資源起做用。在這種狀況下,200(成功)或者204(沒有內容)將是適合的響應狀態,這依賴於響應是否包含一個描述結果的實體。
若是資源被源服務器建立,響應應該是201(Created)而且包含一個實體,此實體描述了請求的狀態而且此實體引用了一個新資源和一個Location頭域(見14.30節)。
POST方法的響應是可緩存的。除非響應裏有Cache-Control或者Expires頭域指示其響應不可緩存。然而,303(見其餘)響應能被利用去指導用戶代理(agent)去得到可緩存的響應。
POST 請求必須遵循8.2節裏指明的消息傳輸需求。
參見15.1.3節關於安全性的考慮.
9.6 PUT
PUT方法請求服務器去把請求裏的實體存儲在請求URI(Request-URI)標識下。若是請求URI(Request-URI)指定的的資源已經在源服務器上存在,那麼此請求裏的實體應該被看成是源服務器此URI所指定資源實體的修改版本。若是請求URI(Request-URI)指定的資源不存在,而且此URI被用戶代理(user agent,譯註:用戶代理可認爲是客戶瀏覽器)定義爲一個新資源,那麼源服務器就應該根據請求裏的實體建立一個此URI所標識下的資源。若是一個新的資源被建立了,源服務器必須能向用戶代理(user agent) 發送201(已建立)響應。若是已存在的資源被改變了,那麼源服務器應該發送200(Ok)或者204(無內容)響應。若是資源不能根據請求URI建立或者改變,一個合適的錯誤響應應該給出以反應問題的性質。實體的接收者不能忽略任何它不理解的Content-*(如:Content-Range)頭域,而且必須返回501(沒有被實現)響應。
若是請求穿過一個緩存(cache),而且此請求URI(Request-URI)指示了一個或多個當前緩存的實體,那麼這些實體應該被看做是舊的。PUT方法的響應不該該被緩存。
POST方法和PUT方法請求最根本的區別是請求URI(Request-URI)的含義不一樣。POST請求裏的URI指示一個能處理請求實體的資源(譯註:此資源多是一段程序,如jsp裏的servlet) 。此資源多是一個數據接收過程,一個網關(gateway,譯註:網關和代理服務器的區別是:網關能夠進行協議轉換,而代理服務器不能,只是起代理的做用,好比緩存服務器其實就是一個代理服務器),或者一個單獨接收註釋的實體。而PUT方法請求裏有一個實體一一用戶代理知道URI意指什麼,而且服務器不能把此請求應用於其餘URI指定的資源。若是服務器指望請求被應用於一個不一樣的URI,那麼它必須發送301(永久移動了)響應;用戶代理能夠本身決定是否重定向請求。
一個獨立的資源可能會被許多不一樣的URI指定。如:一篇文章可能會有一個URI指定當前版本,此URI區別於其文章其餘特殊版本的URI。這種狀況下,一個通用URI的PUT請求可能會致使其資源的其餘URI被源服務器定義。
HTTP/1.1沒有定義PUT方法對源服務器的狀態影響。
PUT請求必須遵循8.2節中的消息傳輸要求。
除非特別指出,PUT方法請求裏的實體頭域應該被用於資源的建立或修改。
9.7 DELETE(刪除)
DELETE方法請求源服務器刪除請求URI指定的資源。此方法可能會在源服務器上被人爲的干涉(或其餘方法)。客戶端不能保證此操做能被執行,即便源服務器返回成功狀態碼。然而,服務器不該該指明成功除非它打算刪除資源或把此資源移到一個不可訪問的位置。
若是響應裏包含描述成功的實體,響應應該是200(Ok);若是DELETE動做沒有經過,應該以202(已接受)響應;若是DELETE方法請求已經經過了,但響應不包含實體,那麼應該以204(無內容)響應。
若是請求穿過緩存,而且請求URI(Request-URI)指定一個或多個緩存當前實體,那麼這些緩存項應該被認爲是舊的。DELETE方法的響應是不能被緩存的。
9.8 TRACE
TRACE方法被用於激發一個遠程的,應用層的請求消息迴路(譯註:TRACE方法讓客戶端測試到服務器的網絡通路,迴路的意思如發送一個請返回一個響應,這就是一個請求響應迴路,)。最後的接收者或者是接收請求裏Max-Forwards頭域值爲0源服務器或者是代理服務器或者是網關。TRACE請求不能包含一個實體。
TRACE方法容許客戶端知道請求鏈的另外一端接收什麼,而且利用那些數據去測試或診斷。Via頭域值(見14.45)有特殊的用途,由於它能夠做爲請求鏈的跟蹤信息。利用Max-Forwards頭域容許客戶端限制請求鏈的長度去測試一串代理服務器是否在無限迴路裏轉發消息。
若是請求是有效的,響應應該在響應實體主體裏包含整個請求消息,而且響應應該包含一個Content-Type頭域值爲」message/http」的頭域。TRACE方法的響應不能不緩存。
9.9 CONNECT(鏈接)
HTTP1.1協議規範保留了CONNECT方法,此方法是爲了能用於能動態切換到隧道的代理服務器(proxy,譯註:能夠爲代理,也能夠是代理服務器)。
10.狀態碼定義
每個狀態碼在下面定義,包括此狀態碼依賴於方法的描述和響應裏須要的任何元信息的描述。
10.1 通知的 1xx
這類狀態代碼指明瞭一個備用的響應,包含一個Status-Line和可選的頭域,而且一一個空行結束(譯註:空行就是CRLF)。沒有必須的頭域對這類狀態碼。由於HTTP/1.0沒有定義任何1xx狀態碼,因此服務器不能發送一個1xx響應給一個HTTP/1.1客戶端,除了實驗性的目的。
客戶端必須能準備去接受一個或多個1xx狀態響應優先於一個常規響應,即便客戶端不指望100(繼續)狀態響應。不被客戶端指望的1xx狀態響應可能會被用戶代理忽略。
代理服務器必須能轉發1xx響應,除非代理服務器和它的客戶端的鏈接關閉了,或者除非代理服務器本身響應請求併產生1xx響應。(例如:若是代理服務器添加了」Expect:100-continue」頭域當轉發請求時,那麼它沒必要轉發相應的100(繼續)響應。)
10.1.1 100 繼續 (Continue)
100狀態響應告訴客戶端應該繼續請求。100響應是個中間響應,它被用於通知客戶端請求的初始部分已經被接收了而且此請求尚未被服務器丟棄。客戶端應該繼續發送請求的剩餘部分,或者若是此請求已經完成了,客戶端會忽略此100響應。服務器必須發送一個final響應在請求接收後。見8.2.3節關於此狀態碼的討論和使用。
10.1.2 101切換協議 (Switching Protocols)
服務器理解和願意遵循客戶端這樣的請求,此請求經過Upgrade消息頭域(見14.42節)指明在鏈接上應用層協議的改變。 服務器將會切換到響應裏Upgrade頭域裏指明的協議,而後緊接着跟隨一個結束此101響應的空行。
只有當協議切換時能受益,協議才應該切換。例如,當傳輸資源時,切換到一個新的HTTP版本比舊的版本要好,或者切換到一個實時的,同步的協議帶來好處時,咱們都應該考慮切換。
10.2 成功 2xx
這類狀態碼指明客戶端的請球已經被服務器成功的接收了,理解了,而且接受了。
10.2.1 200 OK
此狀態碼指明客戶端請求已經成功了。響應返回的信息依賴於請求裏的方法,例如:
GET 請求資源的相應的實體已經包含在響應裏並返回給客戶端。
HEAD 相應於請求資源實體的實體頭域已經被包含在無消息主體的響應裏。
POST 響應裏已經包含一個實體,此實體描述或者包含此POST動做執行的結果
TRACE 響應裏包含一個實體,此實體包含終端對服務器接的請求消息。
10.2.2 201 已建立(Created)
請求已經被服務器知足了而且已經產生了一個新的資源。新建立的資源的URI在響應的實體裏返回,可是此資源最肯定的URI是在Location頭域裏給出的。響應應該含有一實體,此實體包含此資源的特性和位置,用戶或用戶代理能從這些特性和位置裏選擇最合適的。實體格式被Content-Type頭域裏媒體類型指定。源服務器必須能在返回201狀態碼以前創建資源。若是動做(譯註:這裏指能建立資源的方法,如POST方法)不能被當即執行,那麼服務器應該以202(接受)響應代替。
一個201響應能夠包含一個ETag響應頭域,此頭域爲請求的變量(譯註:變量的含義見第1.3節「變量」的解釋)指明當前的實體標籤(entity tag)值,當資源被建立時,見14.19節。
10.2.3 202 接受(Accepted)
請求已經被接受了,可是尚未對此請求處理完。請求可能處理完也可能沒有最終被處理完,由於當處理髮生的時候服務器可能會發現此請求不能被處理。
202響應是非委託的。這是爲了容許服務器爲其餘處理(如:天天執行一次的過程)而接受一個請求從而不須要用戶代理和服務器之間在處理完成以前必須進行持久鏈接。響應裏的實體應該包含請求當前狀態的聲明而且應該包含一個狀態監視指針或一些用戶指望什麼時候請求被知足的評估。
10.2.4 203 非權威信息(Non-Authoritative information)
此狀態碼響應指明響應裏的實體頭域裏的元信息對源服務器來講是沒有意義的,這些元信息是從局部的或第三方的響應副本里獲得的。這些元信息多是源服務器版本的子集或超集。如,包含一個存在本地的資源註釋信息就能夠產生一個源服務器能理解的元信息的超集。203響應狀態碼的使用並非必須的而且只有在響應是非200(Ok)響應時纔是合適的。
10.2.5 204 無內容 (No Content)
服務器已經知足了請求但不須要返回一個實體,而且可能只想返回更新了的元信息。204狀態響應可能包含一個新的或更新了的,和請求變量(譯註:變量是資源的一種表現形式,這和rest架構裏的定義是同樣的,因此這裏咱們能夠理解請求變量是請求資源的一種表現形式)相聯繫的元信息(元信息以實體頭域的形式表式)。
利用此204響應,客戶端若是是一個用戶代理,它就能夠不用改變引發請求發送的文檔視圖(譯註:如一篇html文檔在瀏覽器裏呈現的樣子)。204狀態響應主要的目的是容許輸入,而沒必要引發用戶代理當前文檔視圖的改變,雖然一些新的或更新了的元信息可能會應用於用戶代理視圖裏的此文檔。
204響應不能包含一個消息主體,而且在頭域後包含一個空行結束。
10.2.6 205 重置內容(Reset Content)
205狀態響應是服務器告訴用戶代理應該重置引發請求被髮送的文檔視圖。此響應主要的目的是清空文檔視圖表單裏的輸入框以便用戶能輸入其它信息。此響應不能包含一個實體。
10.2.7 206 部份內容(Partial Content)
服務器已經完成了客戶端對資源的部分GET請求。請求必須包含一個Range頭域(14.35節)用來指出想要的範圍,而且也有可能包含一個If-Range頭域(見14.27節)來使請求成爲一個條件請求。
206狀態的響應必須包含如下的頭域:
- 或者Content-Range頭域,此頭域指明瞭響應裏的範圍;或者一個值爲」multipart/byteranges」的Content-Type頭域和爲每部分指明範圍的Content-Range頭域。若是一個Content-Length頭域出如今響應裏,它的值必須是實際的消息主體的字節數。
- Date頭域
- ETag 和/或 Content-Location頭域,若是這些頭域已經在之前相同請求的200響應裏返回過。
- Expire,Cache-Control,和/或者Vary頭域,若是域值與同一變量之前響應中的域值不同。
若是206響應是使用了強緩存驗證(見13.3.3)的If-Range請求的結果,那麼此響應不該該包含其餘的實體頭域。若是響應是使用了弱緩存驗證的If-Range請求的結果,那麼響應不能包含其餘的實體頭域;這能防止出如今緩存的實體主體和更新的頭域之間的不一致性。其餘的狀況下,響應必須包含全部的實體頭域,這些頭域可能已經在之前的相同請求的200響應裏返回過。
緩存不能把206響應和之前的緩存內容結合若是ETag或Last-Modified頭域並不能精確匹配,見13.5.4。
一個不能支持Range和Content-Range頭域的緩存不能緩存206(部分的)響應。
10.3 從新定向 3xx.
這類狀態碼指明用戶代理須要更進一步的動做去完成請求。進一步的動做可能被用戶代理自動執行而不須要用戶的交互,而且進一步動做請求的方法必須爲GET或HEAD。一個客戶端應該發現無限的重定向迴路,由於此迴路能產生網絡擁擠。
注意:之前此規範版本建議一個最多能有五個重定向。內容開發者應該知道客戶端可能存在這個限制。
10.3.1 300 多個選擇.(Multiple Choices)
資源對應有多個表現形式,客戶端請求資源的表現形式對應於其中的一個,每一個表現形式都有一個指向本身的位置(location),而且代理驅動協商(agent-driven negotiation)能選擇一個更適的表現形式並重定向請求到那個表現形式的位置。
除非是HEAD請求,不然300狀態響應應該包含一個實體,此實體包含一個資源特性和位置列表,從這個列表裏用戶或用戶代理能選擇最合適的資源的表現形式。實體格式被Content-Type頭域裏的媒體類型指定。依賴於此格式和用戶代理的能力,用戶代理選擇最合適的表現形式的行爲可能會被自動執行。然而,此規範並無定義自動執行行爲的標準。
若是服務器能肯定更好的表現形式,它應該爲此表現形式在Location頭域裏包含一個特定的URI來指明此表現形式的位置;用戶代理可能會利用此Location頭域自動重定向。300狀態響應是可緩存的除非被特別指明。
10.3.2 301 永久移動 (Moved Permanently)
請求資源被賦於一個新的永久的URI,而且任何未來對此資源的引用都會利用此301狀態響應返回的URI。具備連接編輯能力的客戶端應該能自動把請求URI的引用轉到到服務器返回的新的引用下。此響應是能緩存的除非另外聲明。
新的永久URI應該在響應中被Location頭域給定。除非請求方法是HEAD,不然此響應的頭域應該包含對此新URI超文本連接的一個超文本提示。
若是客戶端接收了一個301狀態響應,此響應相應的請求的方法不是GET或HEAD,那麼用戶代理不能自動重定向請求,除非它能被用戶確認,由於這可能會改變請求提交的條件。
注意:當客戶端在接收了301狀態碼響應後,會重定向POST請求,一些已經存在的HTTP/1.0用戶代理將錯誤的把此請求變成一個GET請求。
10.3.3 302 發現(Found)
請求的資源放在一個不一樣的暫時的URI下。由於重定向可能會偶爾被改變,客戶端應該繼續利用請求URI(Request-URI)爲未來的請求。302響應是隻有在Cache-Control或Expires頭域指明的狀況下才能被緩存。
臨時的URI應該在Location頭域裏指定。除非請求方法是HEAD,不然響應的實體應該包含指向此新URI的超文本連接的短超超文本提示。
若是302狀態代碼在一個不是GET和HEAD方法請求的響應中,用戶代理不能自動重定向請求除非用戶確承認以自動重定向,由於這能改變請求提交的的條件。
注意:RFC1945和RFC2068指定客戶端不能在重定向請求的時候改變請求方法。然而,大多數用戶代理實現把302響應當作是303響應,根據Location頭域值的URI執行GET請求,無論原始的請求方法。303和307狀態響應的目的是爲使服務器明白客戶端指望哪一種類型的重定向。
10.3.4 303 見其餘(See Other)
請求的響應被放在一個不一樣的URI下,而且應該用GET方法得到那個資源。此方法的存在主要是容許POST執行腳本的輸出重定向到用戶選擇的資源。新的URI並非原始請求資源的代替引用。303響應不能被緩存,可是再次重定向請求的響應應該被緩存。
不一樣的URI應該在Location頭域裏指定。除非請求方法是HEAD,303響應的實體應該包含一個短的指向新的URI連接的超文本提示。
注意:許多HTTP/1.1之前版本的用戶代理不能理解303狀態響應。當這些客戶端比較關注於互操做性的時候,302狀態碼應該被代替利用,由於大多用戶代理對302響應的理解就是303響應。
10.3.5 304 沒有被改變(Not Modified)
若是客戶端已經執行了條件GET請求,而且訪問服務器資源是容許的,可是服務器上的文檔並無被改變,那麼服務器應該以此狀態碼響應。304響應不能包含一個消息主體(message-body),而且在頭域後面老是以一個空行結束。
此響應必須包含下面的頭域:
-Date,除非14.18.1指明的那些規則下Date是能夠遺漏的。若是時鐘不許確的源服務器遵循這些規則,而且代理服務器和客戶端在接收了一個沒有Date頭域的響應後加上了本身的Date(這在RFC 2086裏聲明瞭,見14.19節),緩存將會正確地操做。
-ETag 和/或 Content-Location,若是這些頭域已經在相請求的200響應裏出現過。
Expires,Cache-Control,和/或 Vary,若是這些頭域的域值可能與之前相同請求的響應的域值不一致。
若是條件GET用強緩存驗證(見13.3.3)節,那麼響應不該該包含其餘的實體頭域。當條件GET用於弱緩存驗證時,那麼響應不能包含其餘的實體頭域;這能防止緩存的實體主體和更新了的頭域之間的不一致性。
若是304響應指明實體不能被緩存,那麼此緩存必須遺棄此響應,而且以無條件請求重複請求。
若是緩存利用一個304響應去更新一個緩存項,那麼此緩存必須更新緩存項裏關於響應裏新的域值的那些域值。
10.3.6 305 使用代理服務器 (User Proxy)
請求資源必須能經過代理服務器訪問,代理服務器的地址在響應的Location頭域裏指定。Location頭域指定了代理服務器的URI。接收者被指望經過代理服務器重複此請求,305響應必須能被源服務器產生。
注意:RFC 2068並無說明305響應的目的是重定向一個獨立請求,而且只能被源服務器產生。不注意這些限制會有重要的安全後果。
10.3.7 306沒有使用的(unused)
306狀態碼被用於此規範之前的版本,是再也不使用的意思,而且此狀態碼被保留。
10.3.8 307臨時重發(Temporary Redirect)
請求的資源臨時存在於一個不一樣的URI下。因爲從新向可能會偶爾改變,因此客戶端應該繼續利用此請求URI(Request-URI)爲未來的請求。307響應只有被Cache-Control或Expire頭域指明時才能被緩存。
臨時URI應該在響應的Location頭域裏給定。除非請求方法是HEAD,不然響應的實體應該包含一個指向新URI的超文本連接提示,由於許多HTTP/1.1之前的用戶代理不能理解307狀態響應。所以,此提示應該包含用戶重複原始請求到新的URI的必需的信息。
若是307狀態響應.對應的請求的方法不是GET或HEAD,那麼用戶代理不能自動重定向此請求除非它能被用戶確認它能夠重定向,由於這可能改變請求提交的條件。
10.4 客戶錯誤 4xx
狀態碼4xx類的目的是爲了指明客戶端出現錯誤的狀況。除了當響應一個HEAD請求,服務器應該包含一個實體,此實體包含一個此錯誤請求的解釋。此狀態碼對全部請求方法都是適合的。用戶代理應該展現任何響應裏包含的實體給用戶。
若是客戶端發送數據,利用TCP的服務器實現應該當心確保客戶端回覆包含在響應裏的接收包,這在服務器關閉此輸入鏈接前。若是在關閉鏈接後,客戶端繼續發送數據給服務器,那麼服務器的TCP棧將發送一個重置包給客戶端,
10.4.1 400 壞請求(Bad Request)
請求不能被服務器理解,因爲錯誤的語法。客戶端不該該沒有改變請求而重複請求。
10.4.2 401 未受權的 (Unauthorized)
請求須要用戶受權。響應必須包含一個WWW-Authenticate頭域(見14.47),此頭域包含一個適用於請求資源的受權的激發。客戶端會以一個Authorization頭域重複此請求。若是請求包含了一個受權證書,若是服務器以401響應,它指明這些證書的受權被拒絕。若是401響應包含一個一樣的受權激發和之前的響應同樣,而且用戶代理已經嘗試至少受權了一次,那麼用戶應該被呈現包含在響應裏的實體,由於這些實體可能包含相關的診斷信息。HTTP受權訪問在「HTTP Authentication:Basic and Digest Access Authentication」[43]裏解釋。
10.4.3 402 必需的支付 (Payment Required)
此狀態碼爲未來的應用保留。
10.4.4 403 禁用 (Forbidden)
服務器理解此請求,但拒絕知足此請求。受權是沒有做用的而且請求不能被重複。若是請求方法是HEAD而且服務器想讓客戶端知道請求爲何不能被知足,那麼服務器起應該在響應實體裏描述此拒絕的緣由。若是服務器不但願告訴客戶端拒絕的緣由,那麼404狀態碼(Not Found)響應將被使用。
10.4.5 404 沒有找到(Not Found)
服務器並無找到任何能夠匹配請求URI的資源。條件是長期的仍是暫時的也沒有被服務器指明。410(Gone)狀態響應應該被使用,若是服務器知道一箇舊的資源不能長期的使用而且沒有轉發地址時。 此狀態碼一般別用於當服務器不但願指出爲何請求被拒絕,或者沒有任何其餘響應是適合的。
10.4.6 405 不被容許的方法(Method Not Allowed)
此狀態碼錶示請求行(Request-Line)裏的方法對此資源來講不被容許。響應必須包含一個Allow頭域,此頭域包含以一系列對此請求資源有效的方法。
10.4.7 406 不接受的 (Not Acceptable)
根據客戶端請求的接受頭域(譯註:如:Accept, Accept-Charset, Accept-Encoding, 或者 Accept-Language),服務器不能產生讓客戶端能夠接受的響應。
除非是HEAD請求,響應應該包含一個實體,此實體包含一系列實體的特性和位置,經過他們用戶或用戶代理能選擇最合適的資源的表現形式。實體格式被媒體類型指定。依賴於此格式和用戶代理的能力,選擇最合適的會被自動執行。然而,此規範並無定義自動執行選擇的標準。
注意:HTTP/1.1服務器被容許返回這樣的響應,此響應根據接受頭域(譯註:如:Accept, Accept-Charset, Accept-Encoding, or Accept-Language)是不可接受的。在一些狀況下,這可能更傾向於發送一個406響應。用戶代理被鼓勵觀察響應來決定是否此響應是可接受的。
若是響應是不可接受的,用戶代理應該暫時中止更多的數據的接收而且詢問用戶去決定進一步的動做。
10.4.8 407 代理服務器受權所需(Proxy Authentication Required)
此狀態碼和401(Unauthorized)類似,可是指明客戶端必須首先利用代理服務器對本身受權。代理服務器必須返回一個Proxy-Authenticate頭域(見14.33節),此頭域包含一個適用於代理服務器的受權激發。客戶端可能會重複此請求利用一個合適的Proxy-Autorization頭域(見14.34節)。HTTP訪問受權在「HTTP Authentication;Basic and Digest Access Authentication」[43]。
10.4.9 408 請求超時(Request Timeout)
客戶端在服務器等待的時間裏不能產生請求。客戶端端可能在之後會重複此請求。
10.4.10 409 衝突 (Confilict)
請求不能完成因爲和當前資源的狀態衝突。此狀態碼只被容許出如今指望用戶可能能解決此衝而且能從新提交此請求的狀況下。響應主體應該包含足夠的爲用戶認識此資源衝突的信息。理想的狀況下,響應實體應該包含足夠爲用戶或用戶代理解決此問題的信息;然而,這是不可能的而且也是不須要的。
衝突最可能發生在響應PUT請求的時候。例如,若是版本被使用而且被提交的實體包含資源的改變,這些改變和之前的請求的改變想衝突,那麼服務器應該使用409響應去指明它不能完成此請求。在這種狀況下,此響應實體應該包含這兩個版本的不一樣,響應的格式在響應的Content-Type頭域裏指定。
10.4.11 410 不存在(gone)
請求資源再也不能夠在服務器上獲得而且也不知道轉發地址(譯註:轉向此資源的地址)。此條件是長期條件。具備連接編輯能力的客戶端應該在用戶確認後刪除請求URI的引用。若是服務器不知道或不能方便斷定條件是不是長期的,那麼此404(沒有發現)狀態響應將被代替利用。響應是可緩存的,除非另外申明。
410響應主要的目的是通知接收者資源不能被獲得而且告訴接收者指向那個資源的鏈接已經被移動了。這樣一個事件對時間要求比較嚴格的服務來講是比較廣泛的,而且對屬於我的但已經不在服務器站點工做的人的資源來講,這個事件來也是比較廣泛的。把全部長期不能獲得的資源標記成「gone」或保持這些標記任意長時間,這是沒有必要的。
10.4.12 411 必需的長度 (Length Required)
此響應服務器拒絕接受沒有包含Content-Length頭域的請求。客戶端能夠重複此請求若是它添加了一個有效的Content-Length頭域,此頭域包含了請求消息裏消息主體的長度。
10.4.13 412 先決條件失敗 (Precondition Failed)
先決條件在一個或多個請求頭域裏指定,412響應是代表先決條件在服務器上測試等於false。此響應容許客戶端把先決條件放到請求消息的元信息裏(頭域數據)。
10.4.14 413 請求實體太大
服務器拒絕處理請求由於請求實體太大以至達到服務器不肯意去處理。服務器可能關閉此鏈接去防止客戶端繼續請求。
若是條件是暫時的,服務器應該包含一個Retry-After頭域用來指明此請求是暫時的而且什麼時間後客戶端應該重試。
10.4.15 414 請求URI太長(Request-URI Too Long)
服務器拒絕爲請求服務由於此請求URI太長了以致於服務器不能理解。這種狀況是不多的,只發生在當客戶端把POST請求不合適地轉換爲帶有大量查詢信息的GET請求時。
10.4.16 415 不被支持的媒體類型(Unsupported Media Type)
服務器拒絕爲請求服務由於請求的實體的格式不能被請求的資源支持。
10.4.17 416 請求範圍不知足 (Requested Range Not Satisfiable)
服務器返回一個此狀態碼的響應,若是請求包含一個Range請求頭域(見14.35節),而且此頭域裏range-specifier值不和選擇資源的當前的extent值重疊,而且請求沒有包含一個If-Range請求頭域。(對byte-ranges來講,這意味着byte-range-spec的全部first-byte-pos
值大於選擇的資源的當前長度。
當此狀態碼響應在一個byte-range請求後返回時,此響應應該包含一個Content-Range實體頭域用來指定選擇資源的當前長度(見14.16節)。此響應不能利用multipart/byteranges媒體類型。
10.4.18 417 指望失敗
Expect請求頭域裏指定的但願不能被服務器知足,或者,若是服務器是代理服務器,服務器有有不肯定的理由肯定請求不能被下一站的服務器知足。
10.5 服務器錯誤 5xx (Server Error)
這類狀態碼指明服務器處理請求時產生錯誤或不能處理請求。除了HEAD請求,服務器應該包含一個實體,此實體用來解釋錯誤,和是不是暫時或長期條件。用戶代理應該展現實體給用戶。此響應狀態碼能應用於任何請求方法。
10.5.1 500 服務器內部錯誤 (Internal Server Error)
服務器遇到了一個意外條件,此條件防止服務器知足此請求。
10.5.2 501 不能實現 (Not Implemented)
服務器不能支持知足請求的功能需求。這個響應是很合適的當服務器不能識別請求方法時而且不能支持它請求的資源的時候。
10.5.3 502 壞網關 (Bad Gateway)
此響應說明:服務器,看成爲網關或代理時,它從上行服務器接收了一個無效的響應並嘗試知足客戶端的請求。
10.5.4 503 難以得到的服務.(Service Unavailable)
服務器不能處理請求因爲服務器暫時的過載或維護。這就是說這是暫時條件,此條件將會在一些延時後被減輕。延遲的長度能夠在Retry-After頭域裏指定。若是沒有Retry-After被給,那麼客戶端應該處理此響應就像它處理500響應同樣。
注意:503狀態碼的存在並非意指服務器當產生過載時必須利用它。一些服務器可能但願拒絕此鏈接。
10.5.5 504 網關超時(Gateway Timeout)
服務器,看成爲網關或代理服務器時,不能接收一個從被URI指定的上行服務器的響應(例如:HTTP,FTP,LDAP服務器)或者它爲完成請求而須要訪問的一些其餘的輔助性服務器(例如:DNS服務器)。
注意:一些部署的代理服務器將會返回400或500響應當DNS查找超時。
10.5.6 505 HTTP版本不支持 (HTTP version Not Supported)
服務器不能支持,或拒絕支持,此HTTP協議版本消息。505響應指明服務器不能或不肯意完成這樣的請求,這在3.1中描述了。此響應應該包含一個實體,此實體描述了爲何此協議版本不被支持和其餘的能被服務器支持的協議版本。
11.入口驗證(Access Authentication)
HTTP提供一些可選的響應受權激發機制,這些機制能被用於服務器激發客戶端請求而且使客戶端受權。經常使用訪問受權框架,還有「basic」和「digest」受權規範,都在「HTTP Authentication:basic and Digest Access Authentication」[43]規範裏指定。HTTP/1.1規範採用了「激發(chanllenge)」和「證書(credentials)」的定義。
12.內容協商 (Content Negotiation)
大多數響應包含一個實體,此實體包含人類用戶能理解的信息。一般,但願提供給用戶相應於請求最容易獲得的實體。對服務器和緩存來講,不幸的是,並非全部的用戶都對這個最容易獲得的實體有喜愛,而且並非全部的用戶代理(如web瀏覽器)都能一致的呈現這些實體。因此,HTTP提供了一些「內容協商」機制 — 當有多個可得的表現形式的時候,對特定的響應選擇最好的表現形式的處理過程。
注意:沒有稱作「格式協商」(譯註:「格式」指的是「媒體類型」)的,由於可替換的表現形式可能會同原來的有相同的媒體類型,只是利用了此媒體類型不一樣的性質,例如一種不一樣的語言。
任何包含一個實體主體的響應包括錯誤響應均可能會受協商的支配。
有兩種類型的內容協商在HTTP中:服務器驅動協商和代理驅動協商。這兩種類型的協商具備正交性而且能被單獨使用或聯合使用。一個聯合使用方法的協商會被叫作透明協商,當緩存利用代理驅動協商的信息的時候,此代理驅動協商的信息被爲後續請求提供服務器驅動協商的源服務器提供。
12.1 服務器驅動協商(Server-driven Negotiation)
若是響應的最好的表現形式的選擇是經過服務器上的算法來實現,那麼這種方式的協商稱作服務器驅動協商。選擇是基於響應可得的表現形式(根據不一樣的維度,響應會不一樣;例如,語言,內容編碼,等等)和請求消息裏特定的頭域或關於請求的其餘信息(如:網絡客戶端的地址)。
服務器驅動協商是有優勢的,當從可行的表現形式裏進行選擇的算法對用戶代理進行描述是比較困難的時候(譯註:代理驅動協商),或者當服務器指望發送「最好的猜想」給客戶端而只經過一個響應(以免後續請求的迴路(一個請求會返回一個響應)延遲若是此「最好的猜想「對用戶適合的時候)的時候。爲了改善服務器的猜想,用戶代理應該包含請求頭域(Accept,Accept-Language,Accept-Encoding,等等),這些頭域能描述它對響應的喜愛。
服務驅動協商有以下缺點:
1. 對服務器不可能確切的決定對用戶來講什麼是最好的,由於那須要對用戶代理和用戶對此響應目的的全面理解(如:用戶到底想把響應展現到屏幕仍是打印到紙上?)。
2. 使用戶代理描述請求裏的能力是很是無效的(假設只有響應的一小部分有多個表現形式)還有會侵犯用戶的隱私。
3. 使源服務器的實現變得複雜,也對爲請求產生響應的算法實現變得複雜。
4. 可能會限制公有緩存(public cache)爲多個客戶請求利用相同響應的能力
HTTP/1.1包含下面的請求頭域來使服務器驅動協商啓動,這些請求頭域描述了用戶代理的能力和用戶喜愛:Accept(14.1節),Accept-Charset(14.2節),Accept-Encoding(14.3節),Accept-Language(14.4節),和User-Agent(14.43節)。然而,一些源服務器並不僅侷限於這些維度,這些服務器能基於請求的任何方面來讓響應不一樣,這些方面包括請求頭域以外的信息或在此規範裏沒有定義的擴展頭域。
Vary頭域能被用來表達服務器選擇表現形式(representation)利用的參數,表現形式受服務器驅動協商的支配。見14.44節描述了Vary頭域如何被服務器的使用,13.6節描述了Vary頭域被緩存的使用。
12.2 代理驅動協商 (Agent-driven Negotiation)
對代理驅動協商來講,響應的最好表現形式的選擇被用戶代理執行,這在接收到源服務器一個初始的響應後。選擇是基於響應的一系列可得的表現形式,這些表現形式被包含在初始響應的頭域或初始響應的實體主體(entity-body)裏,每一個表現形式被一個屬於本身的URI指定。從這些表現形式中選擇可能被自動執行(若是用戶代理有能力這樣作)或者被用戶從超文本鏈接菜單中手工選擇。
代理驅動協商是有優勢的,當響應可能會根據通常用途的維度(如:類型,語義,編碼)而不一樣的時候,當源服務器不能經過查看請求而斷定用戶代理能力的時候,當共有緩存(public cache)被用來分派服務器的承載和減小網絡使用的時候。
代理驅動協商也一樣存在須要第二次請求而得到最好表現形式的缺點。第二次請求只有當緩存被使用時纔是有效率的。另外,此規範沒有定義用戶代理自動選擇表現形式的機制,因此不能防止任何這樣的機制被用於HTTP/1.1
HTTP/1.1定義了300(多個選擇)和406(不接受的)狀態響應,當使用代理驅動協商時服務器不能或不肯意利用服務器驅動協商來提供一個不一樣的響應的是時候。
12.3 透明協商(Transparent Negotiation)
透明協商是服務器驅動協商和代理驅動協商的結合體。當一個緩存被提供了構成響應的一系列可得的表現形式(就像在代理驅動協商裏的響應同樣)而且維度的差別能徹底被緩存理解,那麼此緩存變得有能力表明源服務器爲那個資源的後續請求去執行服務器驅動協商。
透明協商的優勢在於它能分發源服務器的協商工做而且能移去代理驅動協商的第二次請求的延遲,由於緩存能正確的猜想到合適的響應。
此規範沒有定義透明協商的機制,因此,它不能防止任何這樣的機制被用於HTTP/1.1。
13 HTTP中的緩存
HTTP典型應用於能經過採用緩存技術而提升性能的分佈式信息系統。HTTP/1.1協議包括的許多使緩存儘量的工做的元素。由於這些元素與協議的其餘方面有着千絲萬縷的聯繫,並且他們相互做用、影響,所以有必要單獨的來介紹基本的緩存設計。
若是緩存不能改善性能,他將一無用處。HTTP/1.1中緩存的目的是爲了在不少狀況下減小發送請求,同時在許多狀況下能夠不須要發送完整響應。前者減小了網絡迴路(譯註:一個請求會返回一個響應,請求響應這個過程就是一個迴路)的數量;咱們利用一個「過時(expiration)」機制來爲此目的(見13.2節)。後者減小了網絡應用的帶寬;咱們用「驗證(validation)」機制來爲此目的。
對行爲,可行性,和關閉的操做的要求放鬆了語義透明性的目的。HTTP/1.1協議容許服務器,緩存,和客戶端能顯示地下降透明性當在必要的時候。然而,由於不透明的操做能混淆非專業的用戶,同時可能和某個服務器應用程序不兼容(例如訂購商品),所以此協議透明性在下面狀況下才能被放鬆要求:
-- 只有在一個顯示的協議層的請求時,透明性才能被客戶端或源服務器放鬆
-- 當出現一個對終端用戶的顯示的警告時,透明性才能被緩存或被客戶端放鬆
所以,HTTP/1.1協議提供這些重要的元素:
1.提供完整語義透明的協議特徵,當這些特徵被通訊的全部方須要時
2. 容許源服務器或用戶代理顯示的請求和控制不透明操做的協議特徵
3. 容許緩存給這樣的響應綁定警告信息的協議特徵,這些響應不能保留請求的語義透明的近似
一個基本的原則是客戶端必須可以發現語義透明性的潛在的放鬆。
注意:服務器,緩存,或者客戶端的實現者可能會面對設計上的判斷,而這些判斷沒有顯示地在此規範裏討論。若是一個判斷可能會影響語義透明性,那麼實現者應該能維持語義透明性,除非一個仔細的完整的分析能說明打破透明性的好處。
13.1.1緩存正確性(Cache Correctness)
一個正確的緩存必須能用最新的響應來響應請求,此響應當在下面的條件知足時才適合此請求(見13.2.5,13.2.6,和13.12)
此緩存響應已被檢測與假設經過源服務器重驗證後源服務器返回的響應相等價。
此緩存響應是足夠保鮮(fresh)的(見13.2節)。缺省的狀況下,這意味着此響應必須知足客戶端,源服務器,和緩存的最嚴格的保鮮要求(見14.9節);若是源服務器指定了保鮮壽命,這說明它是源服務器本身的保鮮要求。
因爲客戶端和源服務器的最嚴格的保鮮要求,若是一個緩存的響應不是足夠保鮮的,那麼在仔細考慮的狀況下,緩存可能仍然返回此緩存的響應經過合適的Warning頭域(見13.1.5和14.46節),除非此響應被阻止(例如:經過」no-store」 cache-directive ,或者經過一個」no-cache」cache-request-directive;見14.9節)。
此緩存響應是一個304(沒有被改變),305(代理重定向),或 錯誤(4xx或者5xx)響應消息。
若是緩存不能同源服務器通訊,那麼一個正確的緩存應該用它緩存的響應去響應請求,若是此緩存的響應能正確的服務於請求;若是不能服務器於此請求,那麼緩存必須能返回一個錯誤或警告指示存在通訊失敗。
若是緩存從服務器端接收到一個響應(或者是一個完整的響應,或者一個304(沒有被改變)的響應),此響應應該是正常狀況下要發送到請求的客戶端的,而且此響應並非新鮮的,那麼此緩存應該把此響應轉發給請求客戶端不須要添加一個新的Warning頭域(可是沒有移去已經存在的Warning頭域)。緩存並非簡單的由於傳輸中響應變得陳舊而嘗試去重驗證響應;這可能會致使一個無限的循環。用戶代理接收一個陳舊的沒有Warning頭域的響應應該提示用戶一個警告信息。
13.1.2警告信息(Warnings)
不管什麼時候,緩存返回一個響應,此響應既不是第一手的(first-hand)也不是足夠保鮮(在13.1.1節的條件2),那麼緩存必須利用一個Warning經常使用頭域來警告產生的效果。Warning頭域和當前定義的警告在14.46節裏描述。這些警告容許客戶端去採起合適的動做。
警告可能被用於其餘的目的,和緩存相關的目的和其餘的目的。警告和錯誤狀態碼的區別在因而否是真正的失敗。
警告被賦予三位數字warn-codes。第一個數字指明:警告是否必須或沒必要須從緩存項裏刪除,在一個成功的重驗證以後。
1xx 警告描述了響應的保鮮或重驗證狀態信息,而且這些信息應該在一個成功的重驗證以後刪除。1xx警告碼多是由緩存產生的,當緩存驗證一個緩存項時。此警告碼不能被客戶端產生。
2xx 警告描述了實體主體或實體頭域的某些方面的信息,這些信息不能被重驗證修改,而且這些信息不能在一個成功重驗證以後被刪除。
見14.46節關於警告碼的定義。
HTTP/1.0緩存將緩存全部響應中的警告,而且不會刪除第一類警告。穿過HTTP/1.0緩存響應中的警告會攜帶一個額外的warning-date域,這是爲了防止未來的HTTP/1.1接收端信任一個錯誤的緩存警告。
警告一樣攜帶一個警告文本。此文本多是任何合適的天然語義(可能基於客戶端請求的Accept頭域),同時包含一個可選擇的關於何種字符集被使用的聲明。
多個警告可能會綁定一個響應(或者被源服務器或者被一個緩存發送的),這包括多個警告能夠共用一個警告碼。例如,服務器可能會以英語和法語提供相同的警告。
當多個警告綁定一個響應時,有時候不可能把全部的警告都展現給客戶。HTTP版本不能指定一個嚴格的優先值去決定警告的優先和順序顯示,可是能夠探索一些方法。
13.1.3緩存控制機制 (Cache-control Mechanism)
HTTP/1.1基本的緩存機制(服務器指定過時時間和驗證器)對緩存是隱含的指令。某些狀況下,服務器或客戶端可能須要給HTTP緩存提供顯示的指令。咱們利用Cache-Control頭域爲此目的。
Cache-Control頭域容許客戶端或服務器在請求或響應裏傳輸多個指令。這些指令經常覆蓋缺省的緩存算法。做爲一個經常使用規則,若是頭域值中存在一個明顯的衝突,那麼最具嚴格解釋的頭域值會被應用(也就是說,能保留語義透明性的值)。然而,一些狀況下,cache-control指令被顯示地指定用來削弱語義透明性的類似性(例如,」max-stale」 或者 「public」)。
Cache-control指令在14.9節被描述。
13.1.4顯示的用戶代理警告(Explicit User Agent Warnings)
不少用戶代理容許用戶覆蓋基本緩存機制。例如,用戶代理可能容許用戶指定緩存實體(即便實體明顯是陳舊的)歷來不要被驗證。或者,用戶代理可能習慣於給任何請求加上「Cache-Control:max-stale=3600」。用戶代理不能缺省的執行不透明行爲,或者不能缺省的執行致使非正常的無效率的緩存行爲,可是可能被顯示地設置去這樣作經過一個顯示的用戶動做。
若是用戶已經覆蓋基本的緩存機制,那麼用戶代理應該給用戶指示什麼時候顯示不能知足服務器透明要求的信息(特別地,若是顯示的實體被認爲是陳舊的)。由於此協議一般容許用戶代理去斷定響應是不是陳舊或不是陳舊的,因此此指示只須要當實際發生時顯示。此指示沒必要是對話框;它應該是一個圖標(例如,一個正在腐爛的魚)或者一些其餘的指示器。
若是用戶以一種方式已經覆蓋了緩存機制,這種方式可能不正常地減小緩存效率,那麼用戶代理應該繼續指示用戶的狀態(例如,經過一個圖片顯示)以便用戶不能不注意地消費過分的資源或者忍受過分的延遲。
13.1.5規則和警告的例外狀況
在某些狀況下,緩存的操做者應該設置緩存返回陳舊的響應,即便此響應沒有被客戶端請求。這個斷定原本不該該輕易決定,可是因爲某些緣由可能會這樣作,特別是當緩存和源服務器鏈接很差時。無能什麼時候當緩存會返回一個陳舊的響應時,緩存必須給此響應作個標記(利用Warning頭域),由於這樣能使客戶端提示用戶響應是陳舊的。
用戶代理照樣能採起步驟去得到第一手的或保鮮的響應。因爲這個緣由,若是客戶端顯示地請求第一手的或保鮮的響應,緩存就不能返回一個陳舊的響應,除非因爲技術或策略方面的緣由。
13.1.6由客戶控制的行爲(Client-controlled Behavior)
當源服務器是過時信息得主要來源時,有時候客戶端可能須要控制緩存去斷定是否返回一個緩存響應而不須要緩存經過服務器驗證它。客戶端經過利用一些Cache-Control頭域來達到此目的。
客戶端的請求可能會指定本身願意接受一個沒有驗證的響應的最大的年齡(age);指定0值會強迫緩存重驗證全部的響應。客戶端照樣會指定在響應過時前的最小保持時間。這些選項增長了對緩存行爲的限制,同時這樣作並不能進一步地放鬆緩存語義透明的近似。
客戶端可能照樣會指定它會接受陳舊響應直到陳舊數達到最大數量。這放鬆了對緩存的限制,同時這可能違反了源服務器指定對語義透明性的限制,可是這可能支持無鏈接的操做或者高得到性當鏈接很差時。
13.2 過時模型 (Expiration Model)
13.2.1 服務器指定模型(Server-Specified Expiratiion)
HTTP緩存會工做的很好,這是由於緩存能徹底地避免客戶端對源服務器的請求。避免對源服務器請求的主要機制是服務器未來會提供一個顯示過時時間(explicit expiration time),此顯示過時時間用來指示響應可能會知足後續的請求。也就是說,客戶端請求響應時,緩存能返回一個保鮮(fresh)的響應而不須要從源服務器那裏得到。
咱們但願服務器給響應設置顯示過時時間(explicit expiration time),服務器相信在過時時間以前實體不會改變。這能保持語義透明性(譯註:語義透明性狀況1.3節裏關於「語義透明」的解釋),只要服務器對過時時間仔細選擇。
過時機制只能應用於能從緩存得到的響應,不能應用於客戶端請求的第一手(first-hand,見1.3節術語)的響應。
若是源服務器但願強制一個語義透明緩存去驗證每一個請求,它會使顯示過時時間(explicit expiration time)設爲過去。這就是說響應老是陳舊的,因此此緩存應該驗證此響應當緩存利用此響應去服務於後續的請求時。見14.9.4節,有更多強迫重驗證的方法
若是源服務器但願強迫任何HTTP/1.1緩存(無論此緩存是怎樣設置的)去驗證每個請求,源服務器應該在Cache-Control頭域裏指定「must-revalidate」緩存控制指令(見14.9節)。
源服務器利用Expires頭域或在Cache-Control頭域裏經過max-age緩存控制指令,來指定顯示過時時間(explicit expiration time)。
過時時間不能被用於強制客戶代理去從新刷新它的顯示或重載資源;過時的語義只能應用於緩存機制,而且這個機制值只須要檢測資源的過時狀態當請求那個資源的一個新請求發生時。見13.13節,關於緩存和歷史機制的區別。
13.2.2 啓發式過時
由於源服務器不能老是提供一個顯示過時時間(explicit expiration time),HTTP緩存一般會設置一個啓發式過時時間(heuristic expiration time),它採用一種算法,此算法利用其它的值(例如Last-Modified時間)去估計一個彷佛合理的過時時間。HTTP/1.1規範沒有提供特定的算法,可是的確是增強了對這些算法結果的最壞狀況的限制。由於啓發式過時時間可能會對語義透明性妥協,他們本應該被謹慎地使用,而且咱們鼓勵源服務器儘量提供顯示過時時間。
13.2.3 年齡(Age)計算
爲了瞭解緩存項(譯註:緩存項是用來響應請求的,它包含緩存的響應實體)是不是保鮮的(fresh),緩存須要知道其年齡是否已超過保鮮壽命(freshness lifetime)。咱們在13.2.4節中討論如何計算保鮮壽命,本節討論如何計算響應或緩存項的年齡。
在此討論中咱們用「now」來表示主機進行計算時時鐘的「當前值」。使用HTTP協議的主機,特別是運行於源服務器和緩存的主機,應該使用NTP[28] 或其餘相似協議來將其時鐘同步到一個全球性的精確時間標準上。
HTTP1.1協議要求源服務器儘量在發送每條響應時都附加一個Date頭域,要儘量在每一個響應裏給出響應產生的時間(見14.18節)。咱們利用術語「date_value」去表示Date頭域的值,這是一種適合於運算操做的表示方法。
當從緩存裏獲取響應消息時,HTTP/1.1利用Age響應頭域來傳送響應消息的估計年齡。Age響應頭域值是緩存對響應從產生或被重驗證開始到如今的時間估計值。
實際上,年齡的值是響應從源服務器途徑每個緩存的逗留時間的總和,再加上響應在網絡路徑上傳輸的時間。
咱們用「age_value」來表示Age頭域的值,這是一種適於算術操做的表示方法。
一個響應的年齡(age)能夠經過兩種徹底不一樣的途徑來計算::
若是本地時鐘與源服務器時鐘同步的至關好,則用 now - date_value ,若結果爲負,則取零。
若是途徑響應路徑(response path)的全部緩存均遵循HTTP1.1協議,則用age_value。
若是咱們有兩種獨立的方法計算響應的年齡(譯註:注意這裏是響應的年齡),咱們能夠合併兩者以下:
corrected_received_age = max(now – date_value,age_value)
而且只要咱們或者有同步的時鐘或者響應途徑的全部緩存遵循HTTP/1.1,咱們就能獲得一個可信賴的結果。
因爲網絡附加延時,一些重要時隙會在服務器產生響應與下一個緩存或客戶端接收之間流逝。若是不經修訂,這一延遲會帶來不正常的低年齡。
因爲致使產生年齡值的請求(譯註:就是存在Age頭域的請求)是早於年齡值的產生,咱們能校訂網絡附加延遲經過記錄請求產生的時間。而後,當一個年齡值被接收後,它必須被解釋成相對於請求產生的時間,而不是相對響應接收的時間。無論有多少延遲,此算法會致使穩定的結果。因此,咱們計算:
corrected_initial_age = corrected_received_age + (now - request_time)
這裏「request_time」是請求的發送時間。
緩存收到響應時,它計算響應年齡的算法以下:
/*
* age_value
* is the value of Age: header received by the cache with this response.
* date_value
* is the value of the origin server's Date: header
* request_time
* is the (local) time when the cache made the request
* that resulted in this cached response
* response_time
* is the (local) time when the cache received the response
* now
* is the current (local) time
*/
apparent_age = max(0, response_time - date_value); //緩存收到響應時響應的年齡
corrected_received_age = max(apparent_age, age_value);
response_delay = response_time - request_time;
corrected_initial_age = corrected_received_age + response_delay;
resident_time = now - response_time; //即收到響應到如今的時間間隔
current_age = corrected_initial_age + resident_time;
緩存項(cache entry)的current_age是緩存項從被源服務器最後驗證開始到如今的時間間隔(以秒記)加上corrected_initial_age。當從緩存項裏產生一條響應時,緩存必須在響應裏包含一個Age頭域,它的值應該等於緩存項的current_age值。
Age頭域出如今響應裏說明響應不是第一手的(first-hand)(譯註:第一手的說明,響應是直接來自於源服務器到達接收端的,而不是來自於緩存裏保存的副本)。然而相反的狀況並不成立,由於響應裏缺乏Age頭域並不能說明響應是第一手的(fisrt-hand),除非全部請求路徑上的緩存都遵循HTTP/1.1協議(也就是說,之前HTTP版本緩存沒有定義Age頭域)。
13.2.4 過時計算(Expiration Calculations)
爲了肯定一條響應是保鮮的(fresh)仍是陳舊的(stale),咱們須要將其保鮮壽命(freshness lifetime)和年齡(age)進行比較。年齡的計算見13.2.3節,本節講解怎樣計算保鮮壽命,以及斷定一個響應是否已通過期。在下面的討論中,數值能夠用任何適於算術操做的形式表示。
咱們用術語「expires_value」來代表Expires頭域的值。咱們用術語「max_age_value」來表示Cache-Control頭域裏「max-age」控制指令的值(見14.9.3節)。
max-age指令優於Expires頭域執行,因此若是max-age出如今響應裏,那麼定義以下:
freshness_lifetime = max_age_value
不然,若Expires頭域出如今響應裏,定義以下:
freshness_lifetime = expires_value - date_value
注意上述運算不受時鐘偏差影響,由於全部信息均來自源服務器。
若是Expires, Cache-Control:max-age, 或 Cache-Control:s-maxage (見 14.9.3) 均未在響應中出現,且響應沒有包含對緩存的其餘控制,那麼緩存能夠用啓發式算法計算保鮮壽命(freshness lifetime)。緩存器必須對年齡大於24小時的響應附加113警告,若是此響應不帶這種警告。
並且,若是響應有最後修改時間,啓發式過時值應不大於從那個時間開始間隔的某個分數。典型設置爲間隔的10% 。
計算響應是否過時很是簡單:
response_is_fresh = (freshness_lifetime > current_age)
13.2.5澄清過時值(Disambiguation Expiration Values)
因爲過時值很容易被設置,有可能兩個緩存會包含同一資源的不一樣保鮮值。
若是客戶端執行請求接收到一個非第一手的響應,此響應在此客戶端擁有的緩存裏仍然是保鮮的,而且緩存裏的緩存項裏的Date頭域的值比此新響應的Date頭域值要新,那麼客戶端應該忽略此響應。若是這樣,它可能會從新以「Cache-Control:max-age=0」指令(見14.9節)請求去強制任何中間緩存經過源服務器對其進行檢查。
若是緩存對有不一樣驗證器(validator)的同一個表現形式(representation)有兩個保鮮響應,那麼緩存必須利用Date頭域值最近的響應。這種狀況可能發生因爲緩存會從其餘緩存獲得響應,或者因爲客戶端請求對一個保鮮緩存項的重載或重驗證(revalidation)。
13.2.6澄清多個響應(Disambiguating Multiple Response)
由於客戶端可能收到經多個路徑而來的響應,因此有些響應會通過一些緩存,而其餘的響應會通過其餘的緩存,客戶端收到響應的順序可能與源服務器發響應的順序不一樣。咱們但願客戶端利用最新的響應,即便舊響應仍然是保鮮的。
實體標籤(entity tag)和過時值都不能影響響應的順序,由於可能會出現晚一點的響應可能會故意攜帶過早的過時時間。日期值的精度被規定只有一秒。
當客戶端試着從新驗證一個緩存項的時候(譯註:這裏的客戶端應該包含一個本地緩存),並且接收到的響應的Date頭域晚於已存在的緩存項,那麼客戶端應該從新進行無條件請求,而且包含
Cache-Control: max-age=0
去強制任何中間緩存經過源服務器來驗證(validate)這些中間緩存的副本,或者
Cache-Control: no-cache
去強制任何中間緩存去從源服務器得到一個新的副本。
13.3 驗證模型(Validation Model)
當緩存有一箇舊緩存項而且緩存想利用此緩存項來做爲客戶端請求的響應時,緩存必須首先經過源服務器(或者可能經過一個有保鮮響應的中間緩存)對其進行檢驗看看此緩存項是否可用。咱們稱作「驗證(validating)」此緩存項。由於咱們不想對完整響應的傳輸付出太大代價,並且若是緩存項無效時也不會產生額外的迴路(譯註:迴路的意思,如:從請求到響應就一條迴路),HTTP1.1協議支持使用條件方法。.
協議支持條件方法的關鍵特徵是圍繞「緩存驗證器(cache validator)」展開的。當源服務器產成一個完整響應時,它同時會附加一些驗證器給響應,這些驗證器和緩存項一塊兒保存。當客戶端(用戶代理或緩存服務器)對對應有緩存項的資源執行條件請求時,客戶端包含一個相關的驗證器(validator)在請求裏。
服務器(譯註:服務器多是緩存服務器)則覈對請求裏的驗證器和當前本地的驗證器是否匹配,若是他們匹配(見13.3.3),則返回一個特定狀態碼(一般爲304(沒有改變))的響應而且此響應不包含實體主體(entity body)。若是不匹配,服務器就返回完整響應(包含實體主體)。這樣,咱們就避免了傳輸完整響應若是驗證器匹配,同時咱們也避免了額外的迴路若是驗證器不匹配。
在HTTP1.1協議中,一個條件請求和普通的請求差很少,除了條件請求攜帶一些特殊的頭域(這些頭域包含驗證器),包含這些特殊的頭域隱含地代表請求方法(一般是GET方法)爲條件請求方法。
協議中包括緩存驗證條件的正和負。也就是說請求方法將會執行若是驗證器的匹配或不會執行若是驗證器不匹配。
注意:缺乏驗證器的響應可能會被緩存,並且會被緩存用來爲請求提供服務直到緩存的副本過時,除非顯示地用緩存控制指令來禁止緩存這樣作。然而,緩存不能執行條件方法獲取資源若是它沒有此資源實體的驗證器,那意味着緩存副本將會不可更新在它過時後。
13.3.1最後修改日期 (Last-Modified Dates)
Last-Modifed實體頭域值常常被用做一個緩存驗證器。簡而言之,緩存項被認爲是有效的若是實體自從Last-Modifed值以後沒有改變。
13.3.2 實體標籤緩存驗證器(Entity Tag Cache Validators)
ETag響應頭域值是實體標籤,它提供了一個「不透明(opaque)的緩存驗證器。這能獲得更可靠的驗證當在不方便存放修改日期的狀況下,當在HTTP日期值的一秒精度不能知足須要的狀況下,或當在源服務器但願避免使用修改日期產生的衝突的狀況下。
實體標籤在3.11節描述了。使用了實體標籤的頭域在14.19,14.24,14.26和14.44節裏描述了。
13.3.3 強,弱驗證器 (Weak and Strong Validators)
因爲源服務器和緩存會比較兩個驗證器來肯定他們是否表明相同的實體,因此一般但願實體(entity,實體主體或實體頭域)發生任何變化時驗證器也相應變化,這樣的驗證器爲強驗證器。.
然而,可能存在這樣的請求,服務器傾向於僅在實體發生重要的語義變化時才改變驗證器,而在實體的某些方面不發生重大改變時就不改變驗證器。在資源變化時驗證器未必變化的稱爲弱驗證器.。
實體標籤一般是強驗證器,但協議提供一種機制來使實體標籤變成弱驗證器。能夠認爲強驗證器在實體的每一字節變化時而變化,而弱驗證器僅在實體的語義變化時才變化。換言之,咱們能認爲強驗證器是特定實體的標識,而弱驗證器是同一類語義等價實體的標識。
注: 強驗證器的例子:一個整數他會隨着每次實體發生變化而遞增。一個實體的修改時間,若是以秒爲精度,能被看成弱驗證器,由於在一秒內資源可能改變兩次。是否支持弱驗證器是選擇的。然而,弱驗證器能夠能高效的去緩存等效對象。
.
客戶端產生請求並把驗證器包含在一個驗證頭域裏的時候或在服務器比較兩個驗證器的時候均用到驗證器。強驗證器可在任何狀況下使用,而弱驗證器僅在不依賴嚴格相等時纔可用。當客戶端產生條件GET請求來請求一個完整實體時,任何類型的驗證器均可以使用。然而,子範圍(sub-range)請求時只能使用強驗證器,由於客戶端可能會獲得一個不一致的實體。
客戶端能夠在發出簡單(非子範圍)GET請求裏既能夠包含弱驗證器也能夠包含強驗證器。客戶端不能利用弱驗證器在其它的請求形式裏。
HTTP1.1協議定義驗證的惟一功能就是比較。有兩種驗證器的比較方法,這依賴因而否能利用弱驗證器進行比較。
.
- 強比較方法:在考慮相等的狀況下,兩驗證器必須徹底一致,而且兩個驗證器都是強驗證器。.
- 弱比較方法:在考慮相等的狀況下,兩驗證器必須徹底一致,但至少有一個驗證器可能在不影響結果的狀況下被標明爲「weak」。
實體標籤是強驗證器除非它被顯示地標記爲弱(weak)的。3.11節給出了實體標籤的語法。
最後修改時間(譯註:Last-Modifed頭域的值)被用做請求的驗證器時默認爲弱驗證器,,除非知足下列規則才斷定它是強驗證器:.
- 驗證器被源服務器用來和當前實體的驗證器進行比較而且源服務器知道相關的實體不會在當前驗證器函蓋的秒數內改變兩次,
或者
- 驗證器可能被客戶端用於If-Modified-Since 或者 If-Unmodified-Since頭域裏,由於客戶端有一個關於此實體的緩存項,而且
- 緩存項包含一個日期值,此日期值給出了源服務器發送源響應(譯註:源服務器產生的響應)的時間,而且
- Last-Modifed頭域值至少提早於日期值(Date頭域值)60秒。
或者
- 驗證器已經被中間緩存同此實體的緩存項裏的驗證器比較過 ,而且
- 緩存項包含日期值(Date頭域值),此日期值指明瞭源服務器發送源響應的時間,而且
- Last-Modifed頭域值至少提早於日期值(Date頭域值)60秒。
此種方法依賴於如下事實,若是兩個響應被服務器在同一秒內被髮出,但這兩個響應都有相同的最後修改(Last-Modified)時間,那麼至少有一個響應的日期值(譯註:Date頭域的值)和最後修改時間值(Last-Modifed頭域的值)是相等的。60秒的限制能保證Date和Last-Modifed頭域的值在不一樣時刻產生。一個實現可能會利用大於60秒的值,若是它認爲60秒過短。
若是客戶端但願執行子範圍(sub-range)請求來請求一個只有最後修改(Last-Modifed)時間和而沒有透明驗證器的值時,它可能會認爲只有最後修改(Last-Modified)時間是強的。
若緩存或源服務器收到一個條件請求,而不是獲得完整響應的GET請求時,他必須使用強比較方法去計算此條件。
此規定容許HTTP1.1的,緩存和客戶端安全地執行子範圍(sub-range)請求來請求從HTTP/1.0得來的值。
13.3.4 關於什麼時候使用實體標籤和最後修改時間的規則
咱們對源服務器,客戶端和緩存採用一套規則和建議來規定不一樣的驗證器什麼時候應該被使用,出
於何種目的被使用。
HTTP/1.1 源服務器:
- 應該發送一個實體標籤驗證器除非源服務器產生這樣一個實體標籤不可行。
- 可能會發送弱實體標籤而不是強實體標籤,若是使用弱實體標籤能提升性能的話或者若是發送一個強實體標籤不可行的狀況下。
- 應該發送一個Last-Modifed值若是可行的話,除非打破語義透明性(這可能由利用If-Modified-Since頭域裏的日期產生)可能會致使嚴重的後果。
換句話說,對http1.1源服務器來講,比較好的作法是同時發送強實體標籤和Last-Modified值。.
爲了合法,強實體標籤必須隨相關聯的實體值改變而改變。弱實體標籤應該隨相關聯的實體在語義上發生改變而改變。
注意:爲保證語義透明緩存,源服務器必須避免爲兩個不一樣的實體重複利用一個特定的強實體標籤值。緩存項應該能保持任意長的時間,而無論過時時間(expiraton time),因此緩存可能會再去嘗試去利用在過去某一時刻得到的驗證器去驗證緩存項。
HTTP/1.1 客戶端:
- 若實體標籤被源服務器提供,HTTP/1.1客戶端必須在任何緩存條件請求(利用了If-Match或If-None-Match的請求)裏利用實體標籤.。
- 僅當Last-Modified值被源服務器提供時,HTTP/1.1客戶端應該在非子範圍緩存條件請求(利用If-Modified-Since)裏利用此值。
- 僅當Last-Modified值被HTTP/1.0源服務器提供,HTTP/1.1客戶端可能會在子範圍緩存條件請求(利用了If-Unmodified-Since)裏利用此值。
- 若是一個實體標籤和Last-Modified值被源服務器提升,HTTP/1.1客戶端應該在緩存條件請求裏利用這兩個驗證器。這容許HTTP/1.1和HTTP/1.1緩存能合適地進行響應。
HTTP/1.1源服務器,當接收到一個條件請求而且此請求同時包含Last-Modifed日期(例如,在If-Modified-Since,或If-Unmodified-Since頭域裏)和一個或多個實體標籤(例如在If-Match,If-None=Match,或If-Range頭域裏)做爲緩存驗證器時,源服務器不能返回一個304狀態響應(Not Modified)除非這樣作能噹噹前實體的驗證器和請求裏全部的條件頭域裏的驗證器一致。
HTTP/1.1緩存服務器,當接收到一個條件請求而且此請求裏同時包含Last-Modified日期和一個或多個實體標籤做爲緩存驗證器時,它不能返回一個本地的副本給客戶端除非那個副本的驗證器和全部請求裏條件頭域裏的驗證器一致。
注意:這些規則背的經常使用的原則是HTTP/1.1服務器和客戶端應該在請求和響應裏儘量傳輸非冗餘的信息。接收這些非冗餘信息的HTTP/1.1系統將會假設它接收了驗證器。
HTTP/1.0客戶端和緩存將會忽略實體標籤。一般,Last-Modified值被這些系統接收後將會保證透明和高效的緩存行爲,因此HTTP/1.1源服務器這時將會提供Last-Modified值。在這些狀況下,當HTTP/1.0系統利用一個Last-Modified值做爲一個驗證器可能會帶來嚴重的後果時,HTTP/1.1服務器將不會提供Last-Modified值。
13.3.5非驗證條件(Non-validating Conditionls)
實體標籤背後的原則是隻有服務的做者才知道資源的語義而去選擇一個合適的緩存驗證機制,而且任何驗證器比較方法的標準均可能會帶來風險。因此,任何其餘的頭域的比較(除了Last-Modified,爲了兼容HTTP/1.0)歷來不會被用於驗證緩存項。
13.4 響應的可緩存性(Response Cacheability)
除非被緩存控制(見14.9節)指令明確地限制,緩存系統能夠將一成功的響應做爲緩存項,能夠返回緩存項裏的響應副本而不須要驗證它若是此副本是保鮮的,而且也能夠在驗證成功後返回它。若是既沒有和響應相關的緩存驗證器也沒有和響應相關的顯示過時時間(explicit expiration time,譯註:見13.3.1節裏關於什麼是顯示過時時間的說明),咱們不會認爲它是可緩存的,可是某些緩存可能會違反這個指望(例如,當不能進行網絡鏈接時)。客戶端能常常發現從緩存裏得到的響應,只須要經過把Date頭域值同當前時間做比較。
注意:某些HTTP1.0緩存可能違反這一指望而不提示警告。
還有,某些狀況下可能不便保留一實體,或將其返回給後續請求.
然而,在一些狀況下,緩存不適合保存一個實體,或者不適合把它放於後續請求的響應裏。這可能由於服務做者認爲徹底語義透明性是有必要的,或着由於安全和隱私的考慮。某些緩存控制指令是爲了讓服務器能指明某些資源實體或其中的一部分不能被緩存。
注意在14.8節裏描述了防止一個共享緩存去保存和返回一個之前請求的響應,若是那個請求包含一個Authorization頭域。
除非緩存控制指令防止此響應被緩存,一個接收的響應若是它的狀態碼是200,203,206,300,301或410,那麼此響應應該被緩存保存並且可用於後續的請求,但這必須受限於過時機制(expiration mechanism)。然而,緩存若是不支持Range和Content-Range頭域,那麼它不能緩存206響應(部份內容)響應。
接收到的響應若是是其餘的狀態碼(如,302和307),那麼此響應不能被用於服務於後續的請求,除非緩存控制指令或其餘的頭域明確地容許它能這樣作。例如,這些頭域包含下面的頭域:Expires頭域(見14.21);「max-age」,「s-maxage」,「must-revalidate」,「prox-revalidate」,「public」或「private」緩存控制指令(見14.9)。
13.5 從緩存裏構造響應
緩存的目的是存儲請求的響應信息,爲了響應未來的請求。在不少狀況下,緩存能返回響應的合適部分給請求者。然而,若是緩存擁有一個基於之前響應的緩存項,它可能必須把新響應的部分和它緩存項裏的內容合起來。
13.5.1End-to-end和Hop-by-hop頭域
爲定義緩存和非緩存代理服務器的行爲,咱們將HTTP頭域分紅兩類:
- end-to-end頭域,他們被傳輸給最終請求或響應的接收者。響應裏end-to-end頭域必需做爲緩存項的一部分存儲,而且必須在從緩存項造成的響應裏傳輸。
- hop-by-hop頭域,他們被只對傳輸層上的鏈接有意義,而且不能被緩存保存或被代理轉發。
下面的HTTP/1.1頭域是hop-by-hop頭域:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
全部其餘被HTTP/1.1定義的頭域均爲end-to-end頭域。
13.5.2不可更改的頭域 (Non-modifiable Headers)
HTTP1.1的某些特徵,如數字認證,基於某一些end-to-end頭域。一個透明代理不該該改變end-to-end頭域,除非這些頭域的定義要求或容許它這樣作。
一個透明代理(譯註:代理通常是緩存,緩存能夠叫緩存代理,緩存服務器,代理服務器)不能改變請求或響應裏的下面的頭域,並且它不能添加這些頭域到沒有這些頭域的請求或響應裏:
- Contents-location
- Content-MD5
- ETag
- Last-Modified
一個透明代理不能改變響應裏下面的的頭域:
- Expires
但它能夠添加這些頭域若是響應裏沒有這些頭域的時候。若是一個Expires頭域被添加,它必須等於響應裏Date頭域的值。
一個代理(譯註:緩存就是一個代理,咱們通常稱作緩存代理,或緩存服務器,或緩存代理服務器,都是一個意思)不能在消息中改變或添加下面的頭域若是此消息包含no-transform緩存控制指令,或在任何請求裏也不能添加或改變這些頭域。
- Content-Encoding
- Content-Range
- Content-Type
一個非透明代理可能會改變或添加這些頭域給一個消息若是此消息不包含no-transform緩存控制指令,可是若是代理這樣作了,它必須添加一個警告214(轉換被應用)(見14.46節)。
警告:end-to-end頭域的沒必要要的改變可能會致使認證機的失敗若是更強的認證機制被應用於後續的HTTP版本中。此認證機制可能依賴於沒有在此出現的頭域值。
請求或響應裏的Content-Length頭域被添加或被刪除會根據4.4節的規則。一個透明代理必須保留實體主體的entity-length(見7.2.2),儘管它能夠可能改變transfer-length(4.4節)。
13.5.3聯合頭域(Combining Headers)
當一個緩存對服務器發出驗證請求時,並且服務器提供304(沒有改變)響應或206(部份內容)響應時,那麼緩存將構造一個響應發送給請求客戶端。
若是狀態碼是304(沒有改變),緩存利用緩存項裏的實體主體(entity-body)做爲客戶端請求響應的實體主體。若是響應狀態碼是206(部份內容)而且Etag或Last-Modified頭域能精確匹配,那麼緩存可能把存入緩存項裏的內容和接收到的響應裏的新內容合併而且利用最後合併的結果做爲輸出響應(見13.5.4)。
存儲於緩存項裏端end-to-end頭域被用於構造響應,除了:
- 任何存儲的警告碼是1xx(見14.46)Warning頭域必須從緩存項和轉發的響應裏刪除。
- 任何存儲的警告碼是2xx的Warning頭域必需要在緩存項和轉發的響應裏保留。
- 任何在304或206響應裏的end-to-end頭域必須替換緩存項裏相應的頭域
除非緩存決定去刪除緩存項,不然它必須照樣能用接收的響應裏的相應的end-to-end頭域去替換存儲在緩存項裏的頭域,除了上面描述的Warning頭域。若是輸入響應裏的一個頭域匹配緩存項裏多個頭域,那麼全部這些舊的頭域必須被替換。
從另外一方面說,輸入響應的全部end-to-end頭域會覆蓋緩存項裏全部相應的end-to-end頭域(除了緩存的警告碼是1xx的Warning頭域,它將會被刪除即便沒有被覆蓋)。
注意:此規則容許源服務器去利用304(沒有改變)或一個206(部份內容)響應去更新任何同一實體或實體的子範圍的之前響應的頭域,雖然它可能沒有意義或這樣作不正確。這條規則不容許源服務器去利用304(沒有改變)或206(部份內容)響應去徹底地刪除一個之前響應的頭域。
13.5.4聯合字節範圍(Combing Byte Ranges)
一條響應可能僅傳送一個實體主體的某一部分,這是因爲請求包含一個或多個Range指定的範圍,或者因爲鏈接會被過早地斷開。在幾回這樣得傳輸後,緩存可能已經接收了同一個實體主體的多個範圍部分。
若是緩存有一個實體的非空子範圍,而且一個輸入(incoming)響應(譯註:輸入響應是進入緩存的響應,輸出響應是從緩存出去的響應)攜帶了另外一個子範圍,那麼緩存可能會把新的子範圍和已經存在的子範圍聯合起來若是二者遵循下面的規則:
- 輸入響應和緩存項都有緩存驗證器。
- 當利用強比較方法的時候,兩個緩存驗證器徹底匹配(見13.3.3)。
若是任何一個要求不能知足,緩存必須利用最近的部分響應(這基於任何響應的Date頭域值,而且會利用輸入響應若是這些Date頭域值相等或丟失了),並且必須丟棄其餘的部分信息。
13.6 緩存已經協商過的響應(Caching Negotiated Responses)
在Vary頭域出如今響應裏的時候,服務器驅動內容協商(12.1節)的使用會改變緩存利用響應去響應後續請求利用的條件和過程。見14.44節關於服務器利用Vary頭域的描述。
服務器應該利用Vary頭域去通知一個緩存什麼樣的請求頭域應該被使用從而從一個可緩存的並受限於服務器驅動協商的響應的多個表現形式中選擇合適的表現形式。Vary頭域裏指定的頭域被稱作選擇請求頭域(selecting request-header)。
當緩存接收到一個後續的請求,此請求的URI對應一個或多個包含了Vary頭域的緩存項時,此緩存不能利用這樣一個緩存項去構造出一個響應去服務於新來的請求,除非全部出如今新請求裏的選擇請求頭域匹配存儲在源請求裏被存儲的請求頭域。
在兩個請求裏,咱們定義這兩個選擇請求頭域匹配,若是而且只有第一個請求的選擇請求頭域能被轉換爲第二個請求裏的頭域經過添加或刪除線性空白(被容許出如今相應的BNF裏的線性空白)和/或把多個消息頭域結合成一個頭域經過4.2節裏的規則。
一個Vary頭域值是「*」老是不能匹配的,而且後續那個資源的請求只能合適地被源服務器解析。
若是緩存項裏的選擇請求頭域(selecting request-header)不能匹配新請求的選擇請求頭域,那麼緩存不能利用緩存項去知足請求除非它能以一個條件請求把此新請求接力到源服務器而且此源服務器以一個304(沒有改變)的狀態碼進行響應幷包含一個實體標籤或者Content-Location頭域指明將要被使用的實體。
若是一個實體標籤被賦予一個緩存的表現形式,那麼此轉發的請求將是條件的而且全部那個資源的緩存項的實體標籤將會被包含於If-None-Match頭域裏。這向服務器表達當前緩存擁有的實體集,以致於若是這些實體裏的任何實體匹配請求的實體,服務器會利用Etag頭域在304(沒有改變)響應裏去告訴緩存哪一個緩存項是合適的。若是新響應的實體標籤匹配已經存在的緩存項,那麼新響應應該被利用去更新已經存在的緩存項的頭域,並且此結果必須返回給客戶端。
若是任何已經存在的緩存項包含只有相關實體的部份內容,那麼此實體的實體標籤不該該被包含在If-None-Match頭域裏除非這個請求是爲了請求實體的一個範圍,此範圍徹底能夠被緩存項知足。
若是緩存接收到一個成功的響應,此響應的Content-Location頭域匹配於已經存在的緩存項的Content-Location頭域對同一請求URI來講,而且此響應的實體標籤不一樣於已經存在的緩存項的實體標籤,並且此響應的Date頭域值比已經存在的緩存項更近,那麼已經存在的緩存項不能被返回去響應未來的請求而且將會從緩存裏刪除。
13.7 共享和非共享緩存 (Shared and Non-Shared Caches)
出於安全和保密考慮,有必要區分共享和非共享緩存。非共享緩存是僅供一個用戶使用的緩存,此種狀況下,可用性由適當的安全機制控制。全部其它的緩存均被認爲是共享緩存。此協議的其它部分給一些對共享緩存的限制以防止隱私丟失或訪問控制的失敗。
13.8 錯誤和不徹底的響應緩存行爲
緩存收到不完整響應(例如響應的字節數比Content-Length頭域指定的值要小)也能夠存儲它,可是必須把它看做部分響應。部分相應能夠合併(見13.5.4);合併結果多是完整的響應或可能還是部分的響應。.緩存不能把部分響應返回給客戶端除非有明確要求能夠這樣作例如利用206(部份內容)狀態碼響應。緩存不能使用一個200(OK)狀態碼返回一個部分響應。
若是緩存在試圖重驗證一個緩存項而收到一個5xx響應時,它既能夠將此響應轉發給請求的客戶端,或者作的就像服務器不能響應似的。在後面的狀況下,它可能返回一個之前的接收的響應除非緩存項包含一個「must-revalidate」緩存控制指令(見14.9節)。
13.9 GET 和 HEAD 的反作用(Side Effects of GET and HEAD)
除非源服務器明確地禁止緩存保存它們的響應,對任何資源應用的GET和HEAD方法不該該有反作用,這些反作用會致使錯誤的行爲若是這些響應將從緩存產生。他們可能會仍然有反作用,但緩存在決定緩存時沒必要考慮這些反作用。緩存老是指望去觀察一個源服務器對緩存的明確限制。
一個例外:有些應用習慣於在在GETs和HEADs方法裏使用查詢URLs(在rel_path_part裏包含一個「?」)去執行一個操做而帶來很大的反作用,緩存不能把此URIs的響應看做一個保鮮的除非服務器提供一個顯示過時時間(explicit expiration time)。這意味着此URIs的之前從HTTP/1.0服務器產生的響應不能來自於緩存。見9.1.1節相關的信息。
13.10 在更新或刪除後的無效性
對源服務器上的某資源執行方法的反作用可能會使一個或多個已經存在的緩存項的不透明性無效。那就是說,雖然他們可能會繼續是保鮮的,可是他們不能準確的反應出源服務器將會對這一個新的請求返回什麼。
HTTP協議沒法保證全部此類緩存項均被標明無效。例如,引發源服務器上資源變化的請求可能不會穿過存有一個緩存項的代理。然而,一些規則幫助減小錯誤行爲的可能。
在此節裏,短語「使實體無效」意味着緩存會將全部那個實體的實例從它的存儲裏移除,或者把這些實體的實例標記爲「無效的」而且在他們可能做爲後續請求的響應時會被進行重驗證。
一些HTTP方法必須讓緩存去使一個實體無效 。這些實體被請求URI指定,或在Location或在Content-Location頭域裏被指定(若是出現的話)。這些方法是:
- PUT
- DELETE
- POST
爲了防止服務器攻擊拒絕,一個基於Location或Content-Location頭域裏的URI的無效性處理必須只有在host部分和請求URI裏的host部分相同時才被執行。
一個緩存若是不能理解請求裏的方法,那麼它應該使請求URI指定的任何實體無效。
13.11 強制寫經過( Write-Through Mandatory)
全部可能對源服務器資源進行修改的方法都要寫經過給源服務器(譯註:直接穿過緩存在服務器上修改)。這一般包括全部方法除了GET和HEAD方法。緩存在將此種請求轉發給服務器並得到相應的響應前不能對請求客戶端作出響應。 這個不能防止代理緩存(譯註:也能夠叫緩存服務器,緩存)在服務器已經發送最終回覆以前發送100(繼續)響應。
相反狀況(一般叫「寫回」或「拷貝回」緩存)在HTTP1.1中是不容許的,這是因爲提供一致更新很是困難,而且服務器,緩存和網絡的故障會出如今比寫回早。
13.12 緩存替換 (Cache Replacement)
若是一個新的可緩存的響應被緩存接收,同時對這一資源的響應已經在緩存裏存在,那麼緩存應該利用最新的響應去回覆當前的請求。緩存可能會把此新響應放進存儲裏,而且若是它知足全部其餘的要求,緩存將會利用此響應來響應任何未來的請求。若是緩存想把此新的響應加進緩存的存儲,13.5.3的規則必須應用。
說明:一個新響應若是它的Date頭域值比已經存在的緩存響應的Date頭域值老,那麼它是不能緩存的。
13.13 歷史列表 (History Lists)
用戶代理常用歷史機制,如「Back」按鈕和歷史列表,來從新展現在一個會話裏接收的一個稍早的實體。
歷史機制和緩存機制是不一樣。歷史機制不該該嘗試展現一個當前資源狀態的語義透明視圖。其歷史機制只是爲了展現在得到資源時看到了什麼。
默認狀況,一個過時時間不會應用於一個歷史機制。若是實體仍然在存儲裏,歷史機制應該顯示它即便實體過時了,除非用戶叫用戶代理去刷新過時的文檔。
這不能被解釋去防止歷史機制告訴用戶視圖可能過時了。
注意:若是歷史機制不必地防止了用戶看陳舊的資源,那麼這會強制服務做者去避免利用HTTP過時控制和緩存控制。服務做者可能會認爲這是很是重要的當用戶沒有被呈現錯誤消息或警告消息當他們利用導向按鈕(如BACK按鈕)去看之前得到的資源時。即便有時這些資源本不能被緩存保存或應該可能會很快過時,用戶界面可能會強制服務做者去求助於其餘防止緩存的方法(例如,一次性URLs)爲了不歷史機制功能的不合適的做用。
14 頭域定義
本節定義了全部HTTP/1.1種標準頭域的語法和語義。對於實體頭域,發送者和接收者指的是客戶端和服務器,取決於誰發送和誰接收此實體。
14.1 Accept
Accept請求頭域被用於指定服務器返回給客戶端可接受的響應媒體類型。Accept頭域能被用於指明請求是指望服務器返回某些指望的媒體類型的響應,例如請求一個內嵌的圖像。
Accept = "Accept" ":"
#( media-range [ accept-params ] )
media-range = ( "*/*"
| ( type "/" "*" )
| ( type "/" subtype )
) *( ";" parameter )
accept-params = ";" "q" "=" qvalue *( accept-extension )
accept-extension = ";" token [ "=" ( token | quoted-string ) ]
星號」*」字符用於把媒體類型組合成一個範圍,」*/*」指明瞭全部的媒體類型而」type/*」指明瞭type類型的全部子類型。Media-range可能包含一個媒體類型參數。
每個media-range可能會跟隨一個或多個accept-params,以「q」參數指明一個相對的喜好程度的質量因子。第一個「q」參數(若是有的話)把accept-params和media-range參數分離了。喜好程度質量因子容許用戶或用戶代理去指明對那個media-range的相對喜好程度,qvalue的範圍是從0到1(見3.9節)。缺省是q=1。
注意:利用「q」參數名字將媒體類型參數(譯註:media-range裏的parameter)和accept-extension分離開來是基於歷史的實踐。雖然這防止裏任何媒體類型參數以「q」命名並使用於media-range裏,但在一個media-range裏使用「q」被認爲是不可能發生的,這是由於在IANA的媒體類型註冊表裏是沒有「q」參數的而且在Accept頭域裏利用任何媒體類型參數也是不多的。未來的媒體類型不鼓勵任何以「q」命名的參數註冊。
例子::
Accept :audio/*;q=0.2,audio/basic
該例應該被解釋成「我喜歡audio/basic,可是能夠給我發送任何最容易得的audio類型,但在喜好程度質量要降低80%」。
若是沒有Accept頭域出現,那麼會假設客戶端能接受全部媒體類型。若是Accept頭域在請求消息裏出現,而且若是服務器根據聯合的Accept頭域值斷定它不能發送可接受的(acceptable)的響應,那麼服務器應該發送406(不可接受的)響應。
一個更加詳盡的例子以下:
Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c
這可能被口頭地解釋成「text/html 和 text/x-c是更喜好的媒體類型,可是若是他們不存在,那麼發送text/x-dvi實體,但若是text/x-dvi也不存在,那麼發送text/plain實體。」
Media-range能被更具特指的media-range或媒體類型覆蓋。若是多個media-range應用了一個特指的類型,那麼最特指的引用應該優先。例如:
Accept: text/*, text/html, text/html; level=1, */*
擁有下面的優先順序:
text/html; level=1
text/html
text/*
*/*
一個媒體類型的喜好程度質量因子是和一個給定的媒體類型聯繫在一塊兒的,它是由查找能最高優先匹配那個媒體類型的media-range決定的。例如:
Accept:: text/*; q=0.3, text/html; q=0.7, text/html; level=1,
text/html; level=2; q=0.4, */*; q=0.5
可能會引發下面值被聯繫:
text/html;level=1 = 1
text/html = 0.7
text/plain = 0.3
image/jpeg = 0.5
text/html;level=2 = 0.4
text/html;level=3 = 0.7
注意:一個用戶代理可能會爲一個特定的media-range提供一個缺省的質量值的集合。然而,除非用戶代理是一個不能和其餘的呈現代理交互的封閉的系統,不然這個缺省的集合應該是被用戶可設置的。
14.2 Accept-Charset
Accept-Charset請求頭域能夠用來指出請求客戶端能接受什麼樣的字符集響應。這個頭域容許客戶端能通知服務器指定何種此客戶端更能理解的或更具特殊目的的字符集的響應。
Accept-Charset = "Accept-Charset" ":"
1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
字符集值在3.4節裏描述。每個字符集可能被給於一個想聯繫的質量值用來表示用戶對那個字符集的喜好程度。缺省值是q=1.例如:
Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
特殊的「*」值若是出如今Accept-Charset頭域裏,那麼將匹配任何字符集(character set)(包含ISO-8859-1)。若是沒有「*」出如今Accept-Charset頭域裏,那麼全部出現的字符集的質量值爲0,除了ISO-8859-1,它的質量值爲1若是沒有出如今Accept-Charset頭域裏。
若是Accept-Charset頭域沒有出現,那麼缺省狀況是任何字符集會接受。若是Accept頭域出如今請求消息裏而且服務器不能發送客戶端想要的Accept-Charset裏指定的字符集的響應,那麼服務器將發送一個406(不能接受的)錯誤響應,然而發送一個不能不能讓客戶端接受的字符集的響應也是容許的。
14.3 Accept-Encoding
Accept-Encoding請求頭域和Accept頭域類似,但Accept-Encoding是限定服務器返回給客戶端能夠接受的內容編碼(content-coding,見3.5節)。
Accept-Encoding = "Accept-Encoding" ":"
1#( codings [ ";" "q" "=" qvalue ] )
codings = ( content-coding | "*" )
使用的例子以下:
Accept-Encoding: compress, gzip
Accept-Encoding:
Accept-Encoding: *
Accept-Encoding: compress;q=0.5, gzip;q=1.0
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
服務器測試一個內容編碼(content-coding)是不是可接受的,是根據Accept-Encoding頭域,並利用下面的規則來決定:
若是一個內容編碼(content-coding)在Accept-Encoding頭域裏出現,那麼它是能夠接受的(acceptable),除非它的qvalue爲0。(這在3.9節裏定義,一個qvalue爲0說明是「不可接受的」)
若是「*」字符出如今Accept-Encoding頭域裏,那麼它匹配任何沒有出如今Accept-Encoding頭域的可得的內容編碼。
若是多個內容編碼是可接受的,那麼qvalue爲最高的且非0的內容編碼是最喜歡的。
「identity」內容編碼老是可接受的,除非qvalue爲0,或者Accept-Encoding頭域包含「*;q=0」而且同時沒有包含「identity」內容編碼。若是Accept-Encoding頭域值爲空,那麼只有「identity」編碼是可接受的。
若是Accept-Encoding頭域在請求裏出現,而且若是服務器不能發送一個Accept-Encoding頭域裏指定的編碼響應,那麼服務器應該發送一個406(不接受的)錯誤的響應。
若是沒有Accept-Encdong頭域出如今請求消息裏,服務器應該假設客戶端將接受任何內容編碼。在這種狀況下,若是「identity」是這些可得的內容編碼中的一個,那麼服務器將利用「identity」內容編碼,除非服務器有另外的信息指明其餘的內容編碼對客戶端是有意義的。
注意:若是請求不能包含一個Accept-Encoding頭域,而且若是「identity」內容編碼是不能接受的,那麼一般不能被HTTP/1.0客戶端理解的內容編碼(也就是說,「gzip」和「compress」)一般是最喜好的;一些老的客戶端有時候會不合適的顯示以其餘內容編碼的消息。服務器應該照樣能基於特定的用戶代理或服務器的信息作除決定用何種內容編碼響應。
注意:大多數HTTP/1.0應用程序不能識別或遵循一個內容編碼跟隨一個qvalue。這意味着qvalue將不能工做而且在x-gzip或x-compress裏不能被容許。
14.4 Accept-Language
Accept-Language請求頭域和Accept請求頭域相似,可是它是限定服務器返回給客戶端喜好的天然語言。
Accept-Language = "Accept-Language" ":"
1#( language-range [ ";" "q" "=" qvalue ] )
language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
每一個language-range均被賦以一個質量值,它表明用戶對此language-range裏涵蓋語言的喜好程度。質量值缺省爲1,例如:
Accept-Language: da, en-gb;q=0.8, en;q=0.7
好像在說:「我更喜歡Danish,可是也能夠接收British English和其餘的English的類型的語言。」一個language-range匹配一個語言標籤(譯註:如上面例子的da,en-gb,en)若是它能精確和此語言標籤相等,或者它能精確匹配此標籤的前綴(在「-」之前的部分)。特殊的「*」,若是出如今Accept-Language頭域裏,代表能匹配任何不在此頭域裏的任何標籤。
注意:前綴匹配規則意味着用戶能理解匹配此前綴的全部語言。
一個語言標籤的質量因子是Accept-Language頭域裏最能匹配此語言標籤的language-range的質量值。若是Accept-Language頭域裏沒有language-range匹配此語言標籤,那麼此語言的質量因子被賦予0。若是沒有Accept-Language頭域出如今請求裏,那麼服務器應該假設全部語言將是可接受的。若是一個Accept-Language頭域出如今請求裏,那麼全部質量因子大於0的語言是可接受的。
若是發送一個和用戶喜好的語言相反,這將在15.1.4裏討論。
因爲個別的用戶的理解程度不同,建議客戶端應用程序讓用戶對語言的偏好進行選擇。若是客戶不能進行選擇,那麼Accept-Language頭域不能在請求裏給出。
注意:當讓用戶做出選擇時,咱們要實現者一個事實那就是客戶不熟悉語言的細節,而且不會提供一個合適的指導。例如,用戶可能會認爲當選擇了「en-gb」會提供任何類型的英語文檔即便British English是不可得的。一個用戶代理應該能建議去增長一個「en」去獲得最合適的匹配行爲。
14.5 Accept-Range
Accept-Range響應頭域容許服務器指明它對客戶的範圍請求(range request,譯註:當在請求消息裏出現Range頭域時代表此請求是範圍請求)的接受程度。
Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges
acceptable-ranges = 1#range-unit | "none"
源服務器若是接受字節範圍請求(byte-range request)那麼能夠發送
Accept-Ranges: bytes
可是沒有必要這樣作。客戶端在沒有接收此頭域時也能夠產生字節範圍請求(byte-range request)。範圍單位(range units)被定義在3.12節。
服務器若是不能接受任何類型的範圍請求(range request),將會發送
Accept-Ranges:none
去告訴客戶不要嘗試範圍請求(range request)。
14.6 Age
Age響應頭域表示發送者(譯註:通常是緩存)對響應產生(或重驗證)時刻後通過時間的估計。一個緩存的響應是保鮮的(fresh)若是此響應的年齡沒有超過它的保鮮壽命(freshness response)。Age值怎樣計算在13.2.3節裏描述了。
Age = "Age" ":" age-value
age-value = delta-seconds
Age值是十進制非負整數,而且以秒爲單位.。
若是緩存接收到一個Age值大於它所能表示的上限,或它的年齡計算出現溢出,那麼它必須傳送Age頭域的值爲2147483648 (2^31)。一個HTTP/1.1服務器若是包含一個緩存,那麼它必須包含一個Age頭域在它擁有緩存產生的任何響應裏。緩存應該利用一個至少31位的運算類型。
14.7 Allow
Allow實體頭域中列出了請求URI(Request-URI)指定資源所支持的幾種方法。此頭域的目的是嚴格地讓接收端知道資源所適合的方法。Allow頭域必須出如今405(方法不被容許)響應中。
Allow = "Allow" ":" #Method
使用示例:
Allow: GET, HEAD, PUT
這一頭域不能阻止客戶端使用其餘方法。然而只有在Allow頭域域中給出的方法才應該被執行。Allow頭域裏指定的方法被源服務器定義,而且在每次請求的響應裏都應該出現這些方法。
Allow頭域裏能夠被提供在一個PUT請求裏,這是爲了說明新的或改變的資源支持這些方法。服務器不須要去支持這些方法,並且應該包含一個Allow頭域在響應裏而且給出實際支持的方法。
代理服務器不能改變Allow頭域即使不理解此頭域裏指明的全部方法,由於用戶代理可能和源服務器通訊有其餘的目的。
14.8 Authorization (受權)
用戶代理每每但願經過服務器給本身受權,用戶代理這樣作是經過在請求裏包含一個Authorization請求頭域,可是一般在接收了一個401響應後就沒有必要讓服務器給本身受權了。Authorization頭域由包含用戶代理對那個請求資源域的受權信息的證書(credentials)組成。
Authorization = "Authorization" ":" credentials
HTTP訪問受權在「HTTP Authenticatiion:Basic and Digest Access Authentication」[43]中描述。若是一個請求被受權而且一個域(realm)被指定,那麼這個證書應該對此域裏全部的其餘請求是有效的(假設在此受權模式下,證書不會根據一個激發值或利用一個同步的時鐘而變化)。
當一個共享緩存(shared cache)(見13.7節)接收一個請求,而且此請求包含一個Authorization頭域時,那麼它不能返回此請求相應的響應來回復任何其餘的請求,除非下面指定的異常發生:
若是此響應包含「s-maxage」緩存控制指令,那麼此緩存可能會利用那個響應來響應一個後續的請求。可是(若是指定的age過時了)一個代理緩存必須首先經過源服務器來重驗證此響應,利用新請求裏的Authorization請求頭域去讓源服務器受權此新請求。(這是爲「s-maxage=0」定義的行爲。)若是響應包含「s-maxmax=0」,那麼代理必須老是重驗證此響應在重利用它以前。
若是此響應包含「must-revalidate」緩存控制指令,那麼緩存可能會利用那個響應來響應一個後續的請求。可是若是此響應是陳舊的,那麼全部緩存必須首先經過源服務器重驗證那個響應,利用新請求裏的Authorization請求頭域去讓源服務器去受權此新請求。
若是響應包含共有緩存指令,那麼它可能會響應任何後續的請求。
14.9 Cache-Control
Cache-Control經常使用頭域被用於指定指令,此指令必須被在請求/響應鏈上的全部緩存機制遵照。這些指令指定防止緩存干涉請求或響應的行爲。這些指令常常覆蓋缺省的緩存算法。緩存指令是單方向的,由於請求中指令的存在並不意味着響應中也會有一樣的指令。
請注意HTTP/1.0緩存可能並不實現Cache-Control,而是隻實現Pragma: no-cache(參見14.31節)。
代理或網關應用程序必須讓緩存指令經過無論這些指令對本身的影響,由於這些指令可能對請求/響應鏈上的全部接收者都適用。不可能爲一個特定的緩存指定一個緩存指令。
Cache-Control = "Cache-Control" ":" 1#cache-directive
cache-directive = cache-request-directive
| cache-response-directive
cache-request-directive =
"no-cache" ; Section 14.9.1
| "no-store" ; Section 14.9.2
| "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
| "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
| "min-fresh" "=" delta-seconds ; Section 14.9.3
| "no-transform" ; Section 14.9.5
| "only-if-cached" ; Section 14.9.4
| cache-extension ; Section 14.9.6
cache-response-directive =
"public" ; Section 14.9.1
| "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1
| "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1
| "no-store" ; Section 14.9.2
| "no-transform" ; Section 14.9.5
| "must-revalidate" ; Section 14.9.4
| "proxy-revalidate" ; Section 14.9.4
| "max-age" "=" delta-seconds ; Section 14.9.3
| "s-maxage" "=" delta-seconds ; Section 14.9.3
| cache-extension ; Section 14.9.6
cache-extension = token [ "=" ( token | quoted-string ) ]
當指令不伴有1#field-name參數出現時,該指令適用於整個請求或響應。當這樣一個指令伴有一個1#field-name參數時,它僅應用於被命名的頭域,而不能應用於請求或響應的其餘部分。這一機制支持可擴展性;HTTP協議未來的版本的實現能夠經過將指令應用於HTTP/1.1中未定義的頭域。
緩存控制指令可分爲以下幾類:
- 對什麼是可緩存的限制;這可能只由源服務器指定。
- 對什麼能被緩存保存的限制;這可由源服務器或用戶代理指定。
- 對基本過時機制的改進;這可能由源服務器或用戶代理指定。
- 對緩存重驗證及重載的控制;這可能僅由用戶代理指定。
- 對實體傳輸的控制
- 緩存系統的擴展。
14.9.1什麼是可緩存的
缺省狀況下,若請求方法、請求頭域和響應狀態碼指明瞭響應爲可緩存的,則此響應就是能夠緩存的。13.4節總結了可緩存性的這些缺省狀況。下列緩存控制響應指令(Cache-Control response deirctives)容許源服務器覆蓋缺省的響應可緩存性:
public
指明響應響應能夠被任何緩存保存,即使該響應一般是不可緩存的或該響應只被一個非共享緩存保存的狀況下。(參見14.8節,關於Authorization頭域的更多詳述。)
private
代表響應消息的部分或全部部分是爲一個用戶準備的而且不得被共享緩存保存。這使源服務器能夠申明響應的特定部分是針對一個用戶,而且對其餘用戶的請求而言不是有效的響應。一個私有(非共享)緩存能夠緩存此響應。
注:單詞private的使用僅用來控制響應在何處可被緩存,而不能保證消息內容的私有性。
no-cache
若是no-cache緩存控制指令沒有指定一個field-name,那麼一個緩存不能利用此響應在沒有經過源服務器對它進行成功的重驗證的狀況下去知足後續的請求。這容許源服務器去防止響應被緩存保存,即便此緩存已經被設置能返回給客戶端請求一個陳舊的響應。
若no-cache緩存控制指令指定一個或多個field-name,那麼一個緩存能夠利用此響應去知足後續的請求,但這要受限於對緩存的任何其它限制。然而,指定的filed-name必須不能在後續請求的響應裏被髮送若是此響應沒有在源服務器那裏獲得成功重驗證的狀況下。這容許源服務器能防止緩存重利用響應裏的某些頭域,但仍然能夠容許緩存響應的剩餘部分。
注意:大多數HTTP/1.0緩存將不能識別或遵循這個指令。
14.9.2什麼能被緩存保存
no-store
no-store緩存控制指令的目的在於防止無心的泄露或保留了敏感信息(好比存放在備份磁帶的信息)。 no-store緩存控制指令應用於整個消息,而且能夠在響應裏或在請求裏被髮送。若是在請求裏被髮送,一個緩存不能保存此請求或此請求響應的任何部分。若是在響應裏被髮送,一個緩存不能保存此響應或引發此響應請求的任何部分。此緩存控制指令能應用於非共享緩存和共享緩存。「不能保存」在這個上下文裏(context,譯註:也能夠叫背景)的意思是指緩存不能有意的把信息保存在非易失性存儲裏,並且必須盡力去刪除易失性存儲上的信息當它轉發完畢後。
即便當此指令在一個響應裏時,用戶也可能會顯示地在緩存系統以外保存這個響應(例如,利用一個「另存爲」對話框)的地方。歷史緩存(譯註:見13.13節)可能保存這個響應做爲它們正常操做的一個部分。
此指令的目的是爲了知足某些用戶聲明的需求,還有就是給那些對偶然信息發佈(這經過未預料地對緩存數據組織的訪問)比較在乎的做者也提供方便。在一些狀況下,利用此緩存控制指令可能會加強隱私,可是咱們注意到它並非在任何狀況下都是可信任的或都是能充分地保護隱私。特別是,惡毒得或者有損害的緩存可能不能識別到或遵循此指令,而且網絡通訊隨時也容易受到竊聽。
14.9.3對基本過時機制的改進
實體的過時時間(譯註:這裏的過時時間也就是「顯示過時時間」,見13.3.1裏關於「顯示過時時間」的說明)可由源服務器利用「Expires」頭域(參見14.21節)指定。 或者,它也能夠在響應裏利用max-age緩存控制指令指定。當max-age緩存控制指令出如今一個緩存的響應裏的時候,若是此緩存的響應當前年齡(current age,譯註:見13.2.3節關於current age的定義)比假如一個新的請求此時去請求那個資源而獲得響應裏的age值(以秒爲單位)要大,那麼此緩存的響應就是陳舊的(stale)。對在一個響應裏應用max-age緩存控制指令意味着此響應是可緩存的(也就是說「公有的」)除非更多其餘的具備限制性的緩存控制指令出如今響應裏。
若響應同時含有Expires頭域和max-age緩存控制指令,那麼max-age緩存控制指令應該覆蓋Expires頭域,即便Expires頭域更具限制性。此規則容許源服務器對一個給定的響應提供一個更長的過時時間給HTTP/1.1緩存(或之後的版本),這對比HTTP/1.0緩存來講。這個規則可能會頗有用,若是某個HTTP/1.0緩存不合適地計算了年齡或過時時間因爲不一樣步的時鐘。
許多HTTP/1.0緩存實現可能會把響應裏小於或等於該響應裏Date頭域值的Expires頭域值當作與「no-cache」緩存響應控制指令(Cache-Control response directive)等效。若是一個HTTP/1.1緩存接收到這樣一個響應,而且此響應沒有包含一個Cache-Control頭域,它應該把此響應當作一個不能緩存的,這是爲了保持和HTTP/1.0服務器兼容。
注意:一個源服務器可能但願把一個相對新的HTTP緩存控制特性,例如「private」緩存控制指令,用在一個存有舊版本緩存的網絡上,並且此舊版本緩存不能理解此特性。源服務器應該須要把新特性和響應裏值小於或等於Date值的Expires頭域聯合起來,這樣以便防止舊版本的緩存不合適的保存此響應。
s-maxage
若是一個響應包含一個s-maxage緩存控制指令,那麼對於一個共享緩存(不能對私有緩存)來講,s-maxage指定的值將會覆蓋max-age緩存控制指令或Expires頭域。s-maxage緩存控制指令照樣意指proxy-revalidate緩存控制指令(見14.9.4節)的語義,也就是說,此共享緩存不能利用此緩存項在它變舊後,在沒有經過源服務器首先重驗證它的狀況下,去響應後續的請求。s-maxage緩存控制指令老是被私有緩存忽略。
注:大多數不遵循此規範的老版本緩存沒有實現任何緩存控制指令。 一個源服務器若是但願利用一個緩存控制指令去限制(但不能阻止)遵循HTTP/1.1的緩存去進行緩存處理,那麼它可能會採用max-age控制指令去覆蓋Expires頭域,而且它會認可HTTP/1.1之前版本的緩存不會去觀察max-age緩存控制指令。
其它緩存控制指令容許一個用戶代理(user agent)去改變基本的過時機制。這些指令可能會被指定在請求裏:
max-age
代表客戶端願接受一個這樣一個響應,此響應的年齡不大於客戶端請求裏max-age指定時間(以秒爲單位)(譯註:若是大於的話,代表此響應是陳舊的)。除非max-stale緩存控制指令也包含在響應裏,不然客戶端是不能接收一個陳舊響應的。
min-fresh
代表客戶端願接受一個這樣的響應,其保鮮壽命不小於其響應當前年齡(譯註:current age,見13.2.3節關於current_age的定義)與客戶端請求裏的min-fresh指定時間之和(以秒爲單位)。也就是說,客戶端想要一個響應至少在min-fresh指定的時間內是保鮮的。
max-stale
代表客戶端願接受已通過期的響應。 若客戶端請求裏爲max-age指定了一個值,則代表客戶端願接受過時時間不超過它在max-stale裏指定秒數的響應。若max-age未指定一個值,則客戶端願接受任意年齡的陳舊響應。
若是緩存返回了一個陳舊響應,這是因爲max-stale緩存控制指令出如今請求裏,或因爲此緩存被設置成能覆蓋響應的過時時間,那麼此緩存必須把一個Warning頭域放進這個陳舊響應裏,此Warning頭域裏應該是110警告碼(響應是陳舊的)。
一個緩存能夠被設置爲能夠不須要驗證就能夠返回陳舊的響應,但這不該與任何「必須」等級關於緩存驗證(例如,一個「must-revalidate」緩存控制指令)的要求衝突。
若新請求與緩存項都包含一個「max-age」緩存控制指令,那麼取兩個值的小者去爲此請求決定緩存項的保鮮程度。
14.9.4緩存重驗證和加載控制(Cache Revalidation and Reload Controls)
有時,用戶代理可能但願或出於須要,堅持想讓一個緩存經過源服務器去重驗證它的緩存項,或者從源服務器那裏從新加載它的緩存項。end-to-end重驗證可能會有必要的,若是緩存或源服務器已經估計了緩存響應(cached response)的過時時間。end-to-end重載多是有必要的,若是緩存項因爲某緣由已經變得陳舊了。
end-to-end重驗證可能被請求:當客戶端沒有本地緩存副本,在這種狀況下,咱們稱它爲「沒指定的end-to-end重驗證(unspecified end-to-end revalidation)」;當客戶端有本地緩存副本,在這種狀況下,咱們稱它爲「指定的end-to-end重驗證(specific end-to-end revalidation)」。
客戶端能指定下面三種動做,利用緩存控制請求指令(Cache-Control request directives):
end-to-end reload
請求包括「no-cache」緩存控制指令,或爲了與HTTP/1.0客戶端兼容的「Pragma: no-cache」緩存控制指令。頭域名不能被包含在no-cache緩存控制指令裏。服務器不能利用一個緩存副原本響應這樣一個請求。
specific end-to-end revalidation
這樣的請求包含一個「max-age=0」緩存控制指令,它強制每一個途徑源服務器的緩存去經過下一個緩存或服務器來重驗證它所擁有的緩存項(若是有的話)。此初始請求包含一個帶有客戶端當前驗證器的緩存驗證條件。
unspecified end-to-end revalidation
這樣的請求包含一個「max-age=0」緩存控制指令,它強制每一個途徑源服務器的緩存去經過下一個緩存或服務器來重驗證它所擁有的緩存項(若是有的話)。此初始請求不包含一個緩存驗證條件;沿着路徑上的第一個緩存(若是有的話),若是它擁有那個資源的一個緩存項,那麼此緩存會包含一個帶有緩存當前驗證器的緩存驗證條件。
max-age
當一箇中間緩存被一個max-age=0的緩存控制指令強迫去重驗證它的緩存項,而且客戶端已經在請求裏包含了它擁有的驗證器,此驗證器可能不一樣於當前緩存項裏保存的驗證器。在這種狀況下,緩存應該在不影響語義透明性的狀況下利用兩個驗證器中的一個去執行請求。
然而,驗證器的選擇可能會影響性能。最好的辦法對中間緩存來講,就是當執行請求時利用它本身的驗證器。若是服務器以303(沒有改變)回覆,那麼此緩存能返回一個它本身的當前已經驗證了的副本給客戶端同時以一個200(OK)狀態碼。若是服務器以一個新實體和一個新的緩存驗證器來回復請求,那麼此中間緩存能把返回的驗證器同客戶端請求裏的驗證器做比較,這經過利用一個強比較方法。若是客戶端的驗證器和源服務器的相等,那麼此中間緩存器只是簡單的返回304(沒有改變)響應。不然,它返回一個新的實體而且狀態碼是200的響應。
若是一個請求包含一個no-cache緩存控制指令,那麼它不該該min-fresh,max-stale,或max-age緩存控制指令。
only-if-cache
在一些狀況下,例如糟糕的網絡鏈接,一個客戶端可能但願一個緩存只返回它當前保存的響應,而且不須要經過源服務器對其進行從新加載或重驗證。若是這樣做客戶端可能會包含一個only-if-cached緩存控制指令在請求裏。若是緩存接收了這樣的指令,那麼它應該利用一個與請求所要求的緩存項去響應,或者以504(網關超時)狀態碼響應。然而,若是一組緩存做爲一個統一的系統來操做,而且有很是好的內部鏈接,那麼這個請求可能會轉發到緩存組的內部。
must-revalidate
因爲一個緩存可能被設置去忽略服務器指定的過時時間,而且又因爲一個客戶端請求可能包含一個max-stale緩存控制指令(它只有一個小影響),因此此協議照樣包含一個讓源服務器強迫緩存項被重驗證的機制。當must-revalidate緩存控制指令出如今響應裏並被一個緩存接收後,此緩存不能利用此緩存項,若是在它變得陳舊而且沒有經過源服務器對它進行重驗證的狀況下,去響應一個後續的請求。(也就是說,若是(基於源服務器的Expires或max-age值)緩存響應是陳舊的,那麼,此緩存每次必須進行end-to-end重驗證)
must-revalidate緩存控制指令對某個協議特性的可信賴性操做要有必要支持。在全部狀況下,一個HTTP/1.1緩存必須遵循must-revalidate緩存控制指令;特別地,若是此緩存不能直接和源服務器通訊,那麼它必須產生一個504(網關超時)響應。
服務器應該發送must-revalidate緩存控制指令,只有在客戶端或緩存對那個實體的重驗證請求的操做失敗的時候,例如一個不動聲息的沒有執行的金融事務。接收端不能採起任何違反此緩存控制指令的自動的行爲,而且不能自動地提供一個被驗證無效的實體副本若是此副本經過源服務器重驗證失敗(譯註:驗證失敗說明緩存裏保存的副本經過源服務器驗證是無效的;驗證成功說明緩存裏保存的副本經過源服務器驗證是有效的,它能夠用來響應後續的請求)。
儘管這不被推薦,用戶代理(user agent)若是在糟糕的網絡鏈接限制下,可能會違反此緩存控制指令,可是,若是這樣的話,它必須顯示地去警告用戶這是一個沒有驗證的響應,並且用戶戶代理還應該須要用戶的確認信息。
proxy-revalidate
proxy-revalidate緩存控制指令和must-revalidate緩存控制指令有相同的語義,除了它並不能應用於非共享的用戶代理的緩存。它能被用於一個已經被受權請求的響應,去容許用戶的緩存能保存或者事後能返回此響應而不須要去重驗證它(由於它已經被那個用戶受權了一次),可是服務於多個用戶的代理仍然須要每次去重驗證它(這是爲了保證每一個用戶已經被受權)。注意這樣的受權響應照樣須要public緩存控制指令,這是爲了容許他們徹底能被緩存。
14.9.5 No-Transform緩存控制指令
no-ransform
中間緩存(代理)的實現者們已經發現轉換某個實體主體的媒體類型轉是頗有用的。一個非透明代理可能,例如,會在不一樣圖像格式之間進行轉換,這是爲了節約空間或在低速的鏈接上減小通訊流量。
然而,當這些轉換應用於某些應用的實體主體時,會引起嚴重的運做方面的問題。好比,醫學圖象應用,科學數據分析和端到端認證都依賴於接收到的實體主體與原實體主體一比一的關係。
因此,若是消息包括了no-ransform緩存控制指令, 那麼中間緩存或代理就不該該改變13.5.2節中列出的頭域。這意味着緩存或代理不得改變由這些報頭定義的實體主體的任何方面,包括實體主體自己的值。
14.9.6緩存控制擴展(Cache control Extendions)
Cache-Control頭域可經過一個或多個cache-extension標記的使用來實現其擴展。其中每一標記都賦予一可選的值。 信息擴展(那些無須改變緩存機行爲的)能夠不經改變其它緩存控制指令的語義而添加。行爲擴展是經過修改現有緩存控制指令的基本行爲來實現的。 新緩存控制指令與標準緩存控制指令都被提供,以致於不理解新緩存控制指令的應用程序會缺省地採用標準緩存控制指令規定的行爲,而那些理解新指令的應用程序則將其看作修改了標準緩存控制指令的要求。這樣,緩存控制指令的擴展能夠在無須改變基本協議的狀況下就可以實現。
這一擴展機制依賴於這樣一個HTTP緩存,此緩存聽從全部緩存控制指令的緩存,聽從某些擴展,並且會忽略全部它不能理解的緩存控制指令。
例如,考慮一個假想的名爲「community」的新的緩存響應控制指令,此指令被當作是對private緩存控制指令的修飾。咱們定義這個新的緩存控制指令以代表:除了非共享緩存能保存此響應以外,還有在community裏以它值命名的社區,只有在此社區裏的成員所共享的任何緩存才能保存此響應。例如,若是一個源服務器但願容許UCI社區裏的成員在他們共享緩存裏能夠使用一個私有響應,那麼此源服務器應該包含:
Cache-Control: private, commuity="UCI"
一個見到此頭域的緩存將會正確的操做,即便此緩存不能理解這個community緩存擴展,由於緩存照樣能看到而且能理解private緩存控制指令因此這樣能致使缺省的安全行爲。
14.10 Connection
Connection經常使用頭域容許發送者指定某一特定鏈接中的選項,這些選項不得由代理(proxy)在之後的鏈接中傳送。
Connection頭域遵循以下語法:
Connection = 「Connection」 「:」 1#(connection-token)
connection-token = token
HTTP/1.1代理必須在轉發報文以前解析Connection頭域,而後針對此頭域中每個connection-token,從報文中移開全部與connection-token裏同名的頭域。 鏈接選項是由Connect頭域中的connection-token指明的,而非任何對應的附加的頭域,由於這些附加頭域在缺乏與鏈接選項相關的參數時可能沒法被傳送。
Connect頭域裏列出的消息頭域不得包含end-to-end頭域,例如Cache-Control頭域。
HTTP/1.1定義了"close"鏈接選項,這是爲了讓發送者代表在完成響應後鏈接將被關閉。
例如
Connection:close
代表不管是出如今請求或響應的頭域中,都代表鏈接不該被視爲在完成現有請求/響應後是「持續的(persistent)」(參見8.1節)。
不支持持續鏈接的HTTP/1.1應用程序必須在每一消息中都加上"close"鏈接選項。
接收到含有Connect頭域的HTTP/1.0(或更低版本)消息的系統必需要爲每個connection-token去刪除或忽略消息中與之同名的頭域。這樣作避免了早於HTTP/1.1版本的代理錯誤地轉發這些頭域。
14.11 Content-Encoding
「Content-Encoding」實體頭域是對媒體類型的修飾。當此頭域出現時,其值代表對實體主體採用了何種的內容編碼,從而能夠知道採用何種解碼機制以獲取Content-Type頭域中指出的媒體類型。Content-Encoding頭域主要目的是能夠在不丟失下層媒體類型的身份下對文檔進行壓縮。
Content-Encoding = "Content - Encoding" ":" 1#content-coding
內容編碼在3.5節裏定義。下面是一個應用的例子:
Content-Encoding:gzip
內容編碼(content-coding)是請求URI指定實體的特性。一般,實體主體之內容編碼(content-coding)的方式存儲,然而只有在此實體主體被呈現給用戶以前才能被解碼。然而,非透明代理可能會把實體主體的內容編碼(content-coding)改爲接收端能理解的內容編碼(content-coding),除非「no-transform」緩存控制指令出如今消息裏。
若是實體的內容編碼不是「identity」,那麼此響應必須包含一個Content-Encoding實體頭域(見14.11節),此頭域必須列出不是identity的內容編碼。
若實體的內容編碼(content-coding)是一個不被源服務器接受的請求消息,則響應必須以415狀態碼響應(不支持的媒體類型)。
若實體採用多種編碼,則內容編碼必須在Content-Encdoing頭域裏列出,並且還必須按他們被編碼的順序列出。額外的關於編碼參數的信息可能會在其它的實體頭域裏提供,這在此規範裏沒有定義。
14.12 Content-Language
Content-Language實體頭域描述了實體面向用戶的天然語言。請注意,這不必定等同於實體主體中用到的全部語言。
Content-Language = 「Content-Language」 「:」 1#language-tag
語言標籤由3.10節定義。Content-Language頭域的主要目的在於讓用戶根據本身喜好的語言來識別和區分實體。這樣,若是實體主體的內容是面向丹麥語言的用戶,那麼下面的頭域是適合的:
Content-Language: da
若未指明Content-Language頭域,那麼缺省是內容是支持全部不一樣語言的用戶。這既可能意味着發送者認爲實體主體的內容與任意天然語言無關,也可能發送者不知此內容該面向何種語言。
要面向多種聽衆,在Content-Language頭域裏可列出多種語言。例如,同時用毛裏土語和英語發行「Treaty of Waitangi」就能夠用下面表示:
Content-Language: mi,en
然而,在實體中有多種語言並不表明此實體必定是爲多個國家語言的用戶準備的。好比《初學拉丁文》之類的語言啓蒙教程,顯然是針對英語用戶的。這裏,合適的Content-Language頭域裏應只包括「en」。
Content-Language可應用於任意媒體類型 -- 它不限於文本式的文檔。
14.13 Content-Length
Content-Length實體頭域按十進制或八位字節數指明瞭發給給接收者的實體主體的大小,或是在使用HEAD方法的狀況下,指明若請求爲GET方法時應該發送的實體主體的大小。
Content-Length = 「Content-Length」 「:」 1*DIGIT
示例:
Content-Length: 3495
除非被4.4節裏規定的規則禁止,不然應用程序應該利用此頭域指明消息主體(message-body)的傳輸長度。
任何大於或等於0的Content-Length均爲有效值。 4.4節描述瞭如何判斷消息主體的長度,若是一個Content-Length沒有在消息裏給定。
請注意此頭域的含義與MIME中的關於此頭域的定義有很大的不一樣,MIME中,它在content-type類型爲「message/external-body」的消息裏是可選的。在HTTP中,除非被4.4節裏定義的規則被禁用,不然一旦消息的長度要在傳送前被肯定,就應發送此頭域。
14.14 Content-Location
Content-Location實體頭域可用來爲消息裏的實體提供對應資源的位置,當此實體的訪問位置和請求URI不是同一位置時。一個服務器應該爲響應實體的變量(variant,譯註:見1.3節 術語)提供一個Content-Location頭域;尤爲是在資源有多個對應的實體時,而且這些實體會有各自的位置,能夠經過這些位置單獨地訪問到各個實體,這時服務器應該爲一個特定的變量(variant)提供一個Content-Location頭域。
Content – Location = 「Content-Location」 「:」 (absoluteURI | relativeURI)
Content-Location的值一樣爲實體定義了基URI(base URI)。
Content-Location的值並不能做爲源請求URI的替代物;它只能是陳述了請求時對應的特定實體資源的位置。未來的請求也許會用Content-Location裏的URI做爲請求URI,若是請求指望指定那個特定實體資源的話。
一若是一個實體含有一個Content-Location頭域,而且此頭域裏的URI不一樣於得到此實體URI,那麼緩存不會利用此實體去響應使用了Content-Locaton裏URI的後續請求。然而,Content-Location能被用於區分同一個請求資源的多個實體,這在13.6節裏描述了。
若Content-Location擁有的是相對URI(relative URI),則此相對URI(relative URI)是相對於請求URI來解析的。
PUT或POST請求中含有Content-Location頭域是沒有給出定義的;服務器可自由忽略它。
14.15 Content-MD5
如RFC 1864[23]中所定義的,Content-MD5實體頭域含有的是實體主體的MD5摘要,這是爲了給一個end-to-end消息的實體主體的提供完整性檢測。(注:MIC有利於檢測實體主體傳送中的偶發性的改動,但不必定能防範惡意襲擊。)
Content-MD5 = "Content-MD5" ":" md5-digest
MD5-digest=< 由RFC 1864 定義的base64的128位MD5摘要>
Content-MD5頭域可由源服務器或客戶端生成,用做實體主體的完整性檢驗。只有源服務器或客戶端可生成Content-MD5頭域;不得由代理服務器和網關生成,不然會有悖於其做爲端到端完整性檢驗的價值。任何實體正主體的接收者,包括代理和網關,均可檢查此頭域裏的摘要值與接收到的實體主體的摘要值是否相符。
MD5摘要的計算基於實體主體的內容,包括任何應用的內容編碼(content-coding),但不包括應用於消息主體的任何傳輸編碼。若接收到的消息具備傳輸編碼,那麼傳輸編碼必須在檢驗Content-MD5值與接收到的實體以前被解除。
這樣形成的後果是:摘要徹底按照實體主體(entity-body)若未經傳輸編碼(transfer encoding)編碼而被以發出的順序進行逐字節計算獲得的。
HTTP 將RFC 1864拓寬到容許對MIME複合媒體類型(如multipart/*,message/rfc822)計算摘要,但這並不改變如前所述的摘要計算方法。
由此產生了一系列影響。複合媒體類型的實體主體可能包含許多body-part,每個body-part都有它本身的MIME和HTTP頭域(包括Content-MD5,Content-Transfer-Encoding,和Content-Encoding頭域),若是一個body-part有一個Content-Transfer-Encoding或Content-Encoding頭域,那麼應該認爲此body-part的內容已經應用了此編碼,而且認爲此body-part被包含在Content-MD5的摘要裏是在應用了此編碼以後。Transfer-Encoding頭域不須要出如今body-part裏。
,
不可在計算或覈對摘要以前就將任何其它換行轉換爲CRLF:實際傳輸的文本中使用的換行必須原封不動的參與摘要計算。
注:雖然HTTP的Content-MD5的定義和RFC 1864中關於MIME實體主體的徹底同樣, 但HTTP 實體主體在對Content-MD5的應用上仍然有幾處與MIME實體主體有所區別。首先,HTTP不象MIME會用Content-Transfer-Encoding頭域,而是會使用Transfer-Encoding和與Content-Encoding頭域。 其次,HTTP比MIME更多地使用二進制內容類型,在此種狀況下,用於計算摘要的字節順序也即由類型定義的傳輸字節的順序。最後,HTTP容許文本類傳輸時採用數種換行,而不僅是規範的使用CRLF的的標準形式。
14.16 Content-Range
Content-Range實體頭域與部分實體主體一塊兒發送,用於指明部分實體主體在完整實體主體裏那一部分被採用。 範圍的單位(Range unit)在3.12節中定義。
Content-Range = "Content-Range" ":" content-range-spec
content-range-spec = byte-content-range-spec
byte-content-range-spec = bytes-unit SP
byte-range-resp-spec "/"
( instance-length | "*" )
byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
| "*"
instance-length = 1*DIGIT
除非沒法或很難判斷,此頭域應指明完整實體主體的總長度。星號「*」表示生成響應時的instance-length未知。
與byte-ranges-specifier值(參見14.35.1節)不一樣的是,byte-range-resp-spec必須只能指明一個範圍,而且必須包含首字節和尾字節的絕對位置。
一個帶有byte-range-resp-spec的byte-content-range-spec,若是它的last-byte-pos值小於first-byte-pos值,或它的instance-length值小於或等於它的last-byte-pos值,那麼就說明是無效的。收到無效的byte-content-range-spec將被忽略,而且任何隨其傳輸的內容都將被忽略。
響應時發送狀態碼416(請求的範圍沒法知足)的服務器應該包含一個Content-Range頭域,且裏面的byte-range-resp-spec的值爲「*」。instance-length指明瞭選定資源的長度。狀態碼爲206(部份內容)的響應不該該包含一個byte-range-resp-sepc爲「*」的Content-Range頭域。
假定實體共含1234字節,byte-content-range-spec值的例子以下:
. The first 500 bytes:
bytes 0-499/1234
. The second 500 bytes:
bytes 500-999/1234
. All except for the first 500 bytes:
bytes 500-1233/1234
. The last 500 bytes:
bytes 734-1233/1234
當HTTP消息裏包含單一範圍時,(好比,對單一範圍請求的響應,或對一組能無縫相連的範圍請求的響應),那麼此內容必須跟隨一個Content-Range頭域,而且還應該包含一個Content-Length頭域來代表實際須要被傳輸字節的長度。例如,
HTTP/1.1 206 Partial content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-Range: bytes 21010-47021/47022
Content-Length: 26012
Content-Type: image/gif
當HTTP報文包含多個範圍時(好比,對多個未重疊範圍請求的響應),它們會被看成多部分類型的消息來傳送。爲此目的多部分媒體類型爲「multipart/byteranges」,它在附錄19.2裏介紹了。見19.6.3裏關於兼容性的問題描述。
對單一範圍請求的響應不得使用multipart/byteranges媒體類型。若對多個範圍請求的響應結果爲一個單一範圍,那麼能夠以一個multipart/byteranges媒體類型發送而且此媒體類型裏只有一個部分(part)。一個客戶端沒法對multipart/byteranges消息解碼,那麼它不能在一個請求中請求多個字節範圍。
當客戶端在一個請求中申請多個字節範圍時,服務器應按他們在請求中出現的順序範圍返回他們所指定的範圍。
若服務器出於句法無效的緣由忽略了字byte-range-spec,它應把請求裏的無效範圍當作不存在。(正常狀況下,這意味着返回一個包含完整實體的200響應。)
若是服務器接收到一個請求,此請求包含一個沒法知足的Range請求頭域(也即,全部byte-range-spec裏的first-byte-pos值大於當前選擇資源的長度),那麼它將返回一個416響應(請求的範圍沒法知足)(參見10.4.17節)。
注: 客戶端對沒法知足Range請求頭域不能期望服務器必定返回416(請求的範圍沒法知足)響應而非200(OK)的響應,由於不是全部服務器都能處理Range請求頭域。
14.17 Content-Type
Content-Type實體頭域指明發給接收者的實體主體的媒體類型,或在HEAD方法中指明若請求爲GET時將發送的媒體類型。
Content-Type = "Content-Type" ":" media-type
媒體類型有3.7節定義。 此頭域的示例以下:
Content-Type: text/html; charset=ISO-8859-4
7.2.1節提供了關於肯定實體媒體類型方法的進一步論述。
14.18 Date
Date經常使用頭域代表產生消息的日期和時間,它和RFC822中的orig-date語義同樣。此頭域值是一個在3.3.1裏描述的HTTP-date;它必須用RFC1123[8]裏的date格式發送。
Date="Date"":"HTTP-date
舉個例子
Date:Tue,15 Nov 1994 08:12:31GMT
源服務器在全部的響應中必須包括一個日期頭域,除了下面這些狀況:
若是響應的狀態代碼是100(繼續)或101(轉換協議),那麼響應根據服務器的須要能夠包含一個Date頭域。
若是響應狀態代碼表達了服務器的錯誤,如500(內部服務器錯誤)或503(難以得到的服務),那麼源服務器就不適合或不能去產生一個有效的日期。
若是服務器沒有時鐘,不能提供合理的當前時間的近似值,這個響應不必包括Date頭域,但在這種狀況下必須遵守 14.18.1節中的規則。
一個收到的消息若是沒有Date頭域的話就會被接收者加上一個,若是這條消息要被這個接收者緩存或者這條消息須要穿過一個須要日期的協議網關。一個沒有時鐘的HTTP實現不能在沒有重驗證響應時去緩存(保存)此響應。一個HTTP緩存,特別是一個共享緩存,應該使用一種機制使,例如NTP[28],去讓它的時鐘與外界可靠的時鐘保持同步。
客戶端在包括實體主體(entity-body)的消息中應該包含一個Date頭域,例如在PUT和POST請求裏,即時這樣作是可選的。一個沒有時鐘的客戶端不能在請求中發送Date頭域。
一個Date頭域中的HTTP-date不該該是一個消息產生時刻以後的日期和時間。它應該表示與消息產生時的日期和時間的最近似值,除非沒有辦法產生一個合理的精確日期和時間。一個恰當的至關精確的日期和時間。理論上說,日期應該是在實體(entity)產生以前的那一刻,實際上,日期是在不影響其語義值的狀況下消息產生期間的任意時刻。
14.18.1沒有時鐘的源服務器運做
一些源服務器實現可能沒有可得時鐘。一個沒有可得時鐘的源服務器不能給一個響應指定Expires或Last-Modified頭域值,除非經過一個具備可信賴時鐘的系統或用戶,把此值與此資源聯繫在一塊兒。能夠給Expires賦予一個過去值,此值爲服務器設置時間或此設置時間以前的值。(這容許響應的「pre-expiration」不須要爲每一個資源保存分離的Expires值)。
14.19 ETag
Etag響應頭域提供了請求對應變量(variant)的當前實體標籤。與實體標籤一塊兒使用的頭域由14.24,14.26和14.44。實體標籤可用於比較來自同一資源的不一樣實體。(參見13.3.3節)
Etag = "Etag" ":" entity-tag
例:
ETag: "xyzzy"
ETag: W/"xyzzy"
ETag: ""
14.20 Expect
Expect請求頭域用於指明客戶端須要的特定服務器行爲。
Expect = "Expect" ":" 1#expectation
expectation = "100-continue" | expectation-extension
expectation-extension = token [ "=" ( token | quoted-string )
*expect-params ]
expect-params = ";" token [ "=" ( token | quoted-string ) ]
一個服務器若是不能理解或遵循一個請求裏Expect頭域的任何expectation值,那麼它必須以合適的錯誤狀態碼響應。若是服務器不能知足任何expection,服務器必須以417(指望失敗)狀態碼響應,或者若是服務器對請求遇到其它問題,服務器必須發送4xx狀態碼。
本頭域爲未來的擴展被定義成一個擴展的語法。若服務器接收到的請求含有它不支持的expectation-extension,那麼它必須以417(指望失敗)狀態響應。
expectation值的比較對於未引用標記(unquoted token)(包括「100-contine」標記)是而言是不區分大小寫的,對引用字符串(quoted-string)的expectation-extension而言是區分大小寫的。
Expect機制是hop-by-hop的:即HTTP/1.1代理(proxy)必須返回417(指望失敗)響應若是它接收了一個它不能知足的expectation。 然而,Expect請求頭域自己是end-to-end頭域;它必需要隨請求一塊兒轉發。
許多舊版的HTTP/1.0和HTTP/1.1應用程序並不理解Expect頭域。
參見8.2.3節中100(繼續)狀態的使用。
14.21 Expires
Expires實體頭域(entity-header)給出了在何日什麼時候以後響應即被視爲陳舊的。一個陳舊的緩存項不能被緩存(一個代理緩存或一個用戶代理的緩存)返回給客戶端,除非此緩存項被源服務器驗證(或者被一個擁有實體的保鮮副本的中間緩存)。見13.2節關於過時模型的進一步的討論。
Expires頭域的出現並不意味着源資源(譯註:存放於源服務器的資源)在Expire指定時間時、以前或以後將會改變或將會不存在。
Expires頭域裏日期格式是絕對日期(absolute date)和時間,由3.3.1節中HTTP-date定義;它必須是RFC1123裏的日期格式:
Expires="Expires " ":" HTTP-date
使用示例爲:
Expires: Thu, 01 Dec 1994 16:00:00 GMT
注:若響應包含一個Cache-Control頭域,而且含有max-age緩存控制指令(參見14.9.3節),則此指令覆蓋Expires頭域。
HTTP/1.1客戶端和緩存必須把其餘無效的日期格式,特別是包含「0」的日期格式當作是過去的時間(也就是說,「已通過期」)。
爲了將響應標爲「已通過期」,源服務器必須把Expires頭域裏的日期設爲與Date頭域值相等。(參見13.2.4節裏關於過時計算的規則。)
爲標記響應爲「永不過時」,源服務器必須把Expires頭域裏的日期設爲晚於響應發送時間一年左右。HTTP/1.1服務器不該發送超過未來一年的過時日期。
對於缺省不可被緩存的響應而言,除非被Cache-Control頭域(見14.9節)指明,不然若是Expires頭域裏日期值爲響應未來的時間,那麼就代表此響應是可緩存的。
14.22 From
From請求報頭域,若是有的話,應該包含用戶代理當前操做用戶的email地址。這個地址應該是機器可用的地址,這被RFC 822 [9]裏的「mailbox」定義同時也在RFC 1123 [8]裏修訂了:
From = "From" ":" mailbox
例如:
From: webmaster@w3.org
頭域能夠被用於記錄日誌和做爲識別無效或多餘請求的資源。他不該該用做不安全形式的訪問保護。這個頭域的解釋是:請求是表明所指定的人執行的,此人應該承擔這個方法執行的責任。特別的,機器人代理程序應該包含這個頭域,這樣此人應該對運行此機器人代理程序負責,而且應該能被聯繫上若是在接收端出現問題的話。
此頭域裏的網絡email地址是能夠和發出請求的網絡主機(host)分離的。例如,當一個請求經過一個代理(proxy)時,初始請求發送者的地址應該被使用。
客戶端在沒有用戶的容許是不該該發出From頭域的,由於它可能和用戶的我的利益或者他們站點的安全政策相沖突。強烈建議在任何一次請求以前用戶能取消,受權,和修改這個頭域的值。
14.23 Host
Host請求頭域說明了正在請求資源的網絡主機和端口號,這能夠從源URI或引用資源(一般是一個HTTP URL,這在3.3.3節裏描述)。Host頭域值必須表明源服務器或網關(被源URL指定)的命名受權(naming authority)。這容許源服務器或網關去區分有內在歧義的URLS,例如,擁有一個IP地址的服務器,它的根「/」URL對應有多個主機名。
Host = "Host" ":" host [ ":" port ] ; 3.2.2節
一個「host」若是沒有跟隨的端口信息,那麼就採用是請求服務的的默認端口(例如,對一個HTTP URL來講,就是80端口)。例如,一個對源服務器http://www.w3.org/pub/WWW/的請求,能夠用下面來表示:
GET /pub/WWW/HTTP/1.1
Host: www.w3.org
一個客戶端必須在全部HTTP/1.1請求消息裏包含一個Host頭域。若是請求URI沒有包含請求服務的網絡主機名,那麼Host頭域必須給一個空值。一個HTTP/1.1代理必須確保任何它轉發的請求消息裏必須包含一個合適的Host頭域,此頭域指定了代理請求的服務地址。全部基於網絡的HTTP/1.1服務器必須響應400(壞請求)狀態碼,若是請求消息裏缺乏Host頭域。
見5.2和19.6.1.1節裏有針對Host頭域的其餘要求。
14.24 If-Match
If-Match請求頭域是用來讓方法成爲條件方法。若是一個客戶端已經從一個資源裏得到一個或多個實體(entity),那麼他能夠經過在If-Match頭域裏包含相應的實體標籤(entity tag)來驗證這些實體的一個或多個是否就是服務器當前實體。實體標籤(entity tag)在3.11節裏定義。這個特性使更新緩存信息只須要一個很小的事務開銷。它照樣被用於防止經過更新請求對一個資源其它版本的不經意修改。做爲一種特殊狀況,「*」匹配資源的當前任何實體。
If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
若是If-Match頭域裏任何一個實體標籤假設與類似的GET請求(沒有If-Match頭域)返回實體的實體標籤相匹配,或者若是給出「*」而且請求資源的當前實體存在,那麼服務器能夠執行請求方法就好像If-Match頭域不存在同樣。
服務器必須用強比較方法(見13.3.3)來比較If-Match裏的實體標籤(entity tag)。
若是沒有一個實體標籤匹配,或者給出了「*」但服務器上沒有當前的實體,那麼服務器不能執行此請求的方法,而且返回412響應(先決條件失敗)。這種行爲是頗有用的,特別是在當客戶端但願防止一個更新方法(updating method)(例如PUT方法)去修改一個客戶端上次請求的但如今已經改變了的資源時,
若是請求在假設在沒有If-Match頭域的狀況下致使了除2XX或412之外的其餘狀態碼響應,那麼If-Match頭域必須被忽略。
「If-Match: *」 的含義是:此方法將被執行,若是源服務器(或緩存,極可能使用Vary機制,見14.44節)選擇的表現形式(representation)存在的話,可是若是此表現形式不存在,那麼此方法不能被執行。
若是一個請求想要更新一個資源(例如PUT)那麼它能夠包含一個If-Match頭域來指明:當相應於If-Match值(一個實體標籤)的實體再也不是那個資源的表現形式時,此請求方法不能被採用。這容許用戶代表:若是那個資源已經改變了而他們不知道的話,他們不但願請求成功。
例如:
If-Match: "xyzzy"
If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-Match: *
既有If-Match頭域又有If-None-Match或If-Modified-Since頭域的請求的結果在本規範沒有定義。
14.25 If-Modified-Since
If-Modified-Since請求頭域被用來讓方法成爲條件方法:若是請求變量(variant)自今後頭域裏指定的時間以後沒有改變,那麼服務器不該該返回實體;而是應該以304(沒有改變)狀態碼進行響應,同時返回消息不須要消息主體(message-body)。
If-Modified-Since = "If-Modified-Since" ":" HTTP-date
一個例子是:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
若是一個GET請求方法含有If-Modified-Since頭域但沒有Range頭域,那麼此方法請求的實體只有請求裏If-Modified-Since頭域中指定日期以後被改變後才能被服務器返回。決定這個算法包括下列狀況:
a)若是請求假設會致使除狀態200以外的任何其它狀態態碼,或者若是If-Modified-Since日期是無效的,那麼響應就和正常的GET請求的響應徹底同樣。比服務器當前時間晚的日期是無效的。
b)若是自從一個有效的If-Modified-Since日期以來,變量已經被修改了,那麼服務器應該返回一個響應同正常GET請求同樣。
c)若是自從一個有效的If-Modified-Since日期以來,變量沒有被修改,那麼服務器應該返回一個304(沒有改變)響應。
這種特徵的目的是以一個最小的事務開銷來更新緩存信息。
註釋:Range請求頭域修改了If-Modified-Since的含義;詳細信息見14.35。
註釋:If-Modified-Since的時間是由服務器解析的,它的時鐘可能和客戶端的不一樣步。
註釋:當處理一個If-Modified-Since頭域的時候,一些服務器使用精確的日期比較方法,而不是稍差的比較方法,來決定是否發送響應304(沒有改變)響應。當爲緩存驗證而發送一個If-Modified-Since頭域的時候,爲了獲得最好的結果,客戶端被建議去利用精確的日期字符串,此字符串是之前的Last-Modified頭域裏被接收的。
註釋:若是客戶端,對同一請求,在If-Modified-Since頭域中使用任意日期代替Last-Modified頭域裏獲得的日期,那麼客戶端應該知道這個日期是由服務器經過對時間的理解來解釋的。因爲客戶端和服務器之間時間編碼的不一樣,客戶端應該考慮時鐘不一樣步和舍入的問題。若是在客戶端第一次請求時刻與後來請求裏頭域If-Modified-Since指定的日期之間,文檔已經改變,這就可能會出現競爭條件,還有,若是If-Modified-Since從客戶端獲得的日期沒有獲得服務器時鐘的矯正,就有可能出現時鐘誤差等問題的。客戶端和服務器時間的誤差最有多是因爲網絡的延遲形成的。
既有If-Modified-Since頭域又有If-Match或If-Unmodified-Since頭域的請求的結果在本規範沒有定義。
14.26 If-None-Match
If-None-Match頭域被用於一個方法使之成爲條件的。一個客戶端若是有一個或多個從某資源得到的實體,那麼他能驗證在這些實體中有不存在於服務器當前實體中的實體,這經過在If-None-Match頭域裏包含這些實體相關的實體標籤(entity tag)來達到此目的。這個特性容許經過一個最小事務開銷來更新緩存信息。它一樣被用於防止一個方法(如,PUT)不經意的改變一個已經存在的資源,而客戶端還相信那個資源並不存在時。
做爲特殊狀況,頭域值「*」匹配資源的任何當前實體。
If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
若是If-None-Match頭域裏的任何實體標籤(entity tag)假設與一個類似的GET請求(假設沒有If-None-Match頭域)返回實體的實體標籤相匹配,或者,若是「*」被給出而且服務器關於那個資源的任何當前實體存在,那麼服務器不能執行此請求方法,除非資源的修改日期不能匹配此請求裏If-Modified-Since頭域(假設有的話)裏提供的日期 。換言之,若是請求方法是GET或HEAD,那麼服務器應以304(沒有改變)來響應,而且包含匹配實體的相關緩存頭域(特別是Etag) 。對於全部其它方法,服務器必須以412(先決條件失敗)狀態碼響應。
13.3節說明了如何判斷兩實體標籤是否匹配。弱比較方法只能用於GET或HEAD請求。
若是If-None-Match頭域裏沒有實體標籤匹配,那麼服務器能夠執行此請求方法就像If-None-Match頭域不存在同樣,可是必須忽略請求裏的任何If-Modified-Since頭域。那就是說,若是沒有實體標籤匹配 ,那麼服務器不能返回304(沒有改變)響應。
若是假設在沒有If-None-Match頭域存在的狀況下,請求會致使除2xx及304狀態碼以外響應,那麼If-None-Match頭域必須被忽略。(見13.3.4節關於假如同時存在If-Modified-Since和If-None-Match頭域時服務器的行爲的討論)
「If-None-Match: *」的意思是:若是被源服務器(或被緩存,可能利用Vary機制,見14.44節)選擇的表現形式(representation)存在的話,請求方法不能被執行,然而,若是表現形式不存在的話,請求方法是能被執行的。這個特性能夠防止在多個PUT操做中的競爭。
例:
If-None-Match: "xyzzy"
If-None-Match: W/"xyzzy"
If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
If-None-Match: *
若是一個請求含有If-None-Match頭域,還含有一個If-Match或If-Unmodified-Since頭域的話,此請求的指向結果在此規範裏沒有定義。
14.27 If-Range
若是客戶端在其所指的緩存中有一個實體的部分副本,並但願其緩存中有此實體的完整副本,那麼此客戶端應該在一個條件GET(conditional GET)(在GET請求消息裏利用了If-Unmodified-Since和If-Match頭域,或利用了其中一個)請求裏利用Range請求頭域(request-header)。然而,若是因爲實體被改變而使條件失敗,那麼此客戶端可能會發出第二次請求從而去得到整個當前實體主體(entity-body)。
If-Range頭域容許客戶端短路(short-circuit)第二次請求。說的通俗一點,這意味着:若是實體沒有改變,發送我想要的部分(譯註:發送range指明的實體範圍);若是實體改變了,那就把整個新的實體發過來。
If-Range = 「if-Range」 「:」( entity-tag | HTTP-date)
若客戶端沒有一個實體的實體標籤(entity tag),但有一個最後修改日期(Last-Modified date),它能夠在If-Range頭域裏利用此日期。(服務器經過檢查一兩個字符便可區分合法HTTP-date與任意形式的entity-tag。)If-Range頭域應該只能與一個Range頭域一塊兒使用,而且必須被忽略若是請求不包含一個Range頭域或者若是服務器不支持子範圍(sub-range)操做。
若是If-Range頭域裏給定的實體標籤匹配服務器上當前實體的實體標籤(entity tag),那麼服務器應該提供此實體的指定範圍,並利用206(部份內容)響應。若是實體標籤(entity tag)不匹配,那麼服務器應該返回整個實體,並利用200(ok)響應。
14.28 If-Unmodified-Since
If-Unmodified-Since請求頭域被用於一個方法使之成爲條件方法。若是請求資源自今後頭域指定時間開始以後沒有改變,那麼服務器應該執行此請求就像If-Unmodified-Since頭域不存在同樣。
若是請求變量(variant,譯註:見術語)在此頭域指定時間後之後已經改變,那麼服務器不能執行此請求,而且必須返回412(前提條件失敗)狀態碼。
If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-日期
此域的應用實例:
If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
若是請求正常狀況下(即假設在沒有If-Unmodified-Since頭域的狀況下)致使任何非2xx或412狀態碼,那麼If-Unmodified-Since頭域將會忽略。
若是此頭域中指定的日期無效,那麼此頭域會被忽略。
在請求裏有If-Unmodified-Since頭域而且有If-None-Match或者If-Modified-Since頭域中的一個,這種請求的處理結果在此規範中沒有被定義。
14.29 Last-Modified
Last-Modified實體頭域(entity-header)指明瞭變量(variant)被源服務器所確信的最後修改的日期和時間。
Last-Modified = 「Last-Modified」 「:」 HTTP-date
應用示例以下:
Last-Modified : Tue, 15 Nov 1994 12:45:26 GMT
此頭域的確切含義取決於源服務器的實現和源資源(original resource)的性質。 對文件而言,它可能僅僅指示文件上次修改的時間。對於包含動態部分的實體而言,它多是組成其各個部分中最後修改時間最近的那個部分。對數據庫網關而言,它多是記錄的最新修改時間戳。對虛擬對象來講,它多是最後內部狀態改變的時間。
源服務器不得發送一個遲於消息產生時間的Last-Modified日期。假如資源最後修改日期可能指示未來的某個時間,此服務器應該用消息產生的時間替換那個日期。
源服務器得到實體的Last-Modified值應該儘可能靠近服務器產生響應的Date值。這容許接收者對實體修改時間做出準確的估計,特別是若是實體的改變時間接近響應產生的時間。
HTTP/1.1服務器應該發生Last-Modified頭域無能什麼時候。
14.30 Location
Location響應頭域被用於爲了完成請求或識別一個新資源,使接收者能重定向於Location指示的URI而不是請求URI。對於201(Created)響應而言,Location是請求創建新資源的位置。對於3xx響應而言,Location應該指明瞭服務器自動重定向資源喜好的URI。Location頭域值由一個絕對URI組成。
Location = 「Location」 「:」 absoluteURI
一個例子以下:
Location : http://www.w3.org/pub/WWW/People.html
注: Content-Location頭域(14.14節)不一樣於Location頭域,Content-Location頭域指定了請求裏封裝實體的源位置。有可能一個響應即包含location也包含Content-Location頭域。在13.10節裏有關於一些方法的要求。
14.31 Max-Forwards
Max-Forwards請求頭域提供一種機制,那就是利用TRACE(9.8節)和OPTIONS(9.2節)方法去限制代理或網關的數量,這些代理或網關能傳遞請求到下一個入流(inbound)服務器。這是很是有幫助的,當客戶端嘗試去跟蹤一個好像陷入失敗或陷入循環的請求鏈時。
Max-Forwards = 「Max – Forwards」 「:」 1*DIGIT
Max-Forwards值是十進制的整數,它指定了請求消息剩餘重定向的次數。
對於一個TRACE或OPTIONS請求,若是包含一個Max-Forwards頭域,那麼接收此請求的代理或網關必須能在轉發(forwarding)此請求以前檢查和更新Max-Forwards頭域值。若是接收的值爲0,那麼接收者不能轉發此請求;而是,它必須做爲最後的接收者響應。若是接收的Max-Forwards值比0大,那麼此轉發的消息必須包含一個更新了的Max-Forwards頭域,更新的值是在接收時的值上減去1。
對本規範定義的全部其它方法以及任何沒有明確做爲方法定義部分的擴展方法的請求裏,Max-Forwards頭域可能會被忽略。
14.32 Pragma
Pragma經常使用頭域被用於包含特定執行指令,這些指令可能被應用於請求/響應鏈中任何接收者。從協議的觀點來看,pragma指令指定的行爲是可選的;然而,一些系統可能要求行爲必須知足指令的要求。
Pragma = 「Pragma」 「:」 1#pragma-directive
pragma-directive =」no-cache」 | extension-pragma
extension-pragma =token [ 「=」 ( token | quoted-string) ]
當no-cache指令出如今請求消息中,應用程序應該轉發(forward)此請求到源服務器,即便它擁有此請求響應的緩存副本。pragma指令和no-cache緩存控制指令(見14.9)用相同的語義,而且它爲了同HTTP/1.0向後兼容而定義的。當一個no-cache請求發送給一個不遵循HTTP/1.1的服務器時,客戶端應該即包含pragma指令,也應該包含no-cache緩存控制指令。
pragma指令必須能穿過代理和網關應用程序,無論對於那些應用程序有沒有意義。由於這些指令可能對請求/響應鏈上的全部接受者有用。不可能爲一個特定的接收者定義一個pragma;然而,任何對接收者不相關的pragma指令都應該被接收者忽略。
HTTP/1.1緩存應該把"Pragma:no_cache"看成好像客戶端發送了"cache_control:no-cache"。在http中不會有新的pragma指令會被定義。
14.33 Proxy-Authenticate
Proxy-Authenticate響應頭域必須被包含在407響應(代理受權)裏。此頭域值由一個challenge和parameters組成,challenge指明瞭受權方案,而parameters應用於此請求URI的代理。
Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
關於HTTP訪問受權過程的描述在「HTTP Authentication:Basic and Digest Access Authentication」[43]中介紹了。不像WWW-Authenticate頭域,Proxy-Authenticate頭域只能應用於當前鏈接,而且不該該傳遞給下行(downstrem)客戶端。然而,一箇中間代理可能須要從請求下行客戶端而得到它本身的證書(credentials),這在一些狀況下就好像代理正在轉發Proxy-Authenticate頭域同樣。
14.34 Proxy-Authorization
Proxy-Authorization請求頭域容許客戶端讓一個須要受權的代理能給本身(或客戶端的用戶)受權。Proxy-Authorization頭域值由包含用戶代理受權信息的證書組成,此受權信息是關於對代理和/或請求資源域來講的。
Proxy-Authorization = 「Proxy-Authorization」 「:」 credentials
HTTP訪問受權過程在「HTTP Authentication: Basic and Digest Access Authentication」[43]中描述。不像Authorization頭域,Proxy-Authorization頭域只能應用於下一個利用Proxy-Authenticate頭域進行受權的輸出代理。
14.35 Range
14.35.1字節範圍 (Byte Ranges)
既然全部的HTTP實體都以字節序列形式的HTTP消息表示,那麼字節範圍的概念對任何HTTP實體都是有意義的.(不過並非全部的客戶和服務器都須要支持字節範圍操做.。)
HTTP裏的字節範圍應用於實體主體的字節序列(沒必要和消息主體同樣)。
字節範圍操做可能會在一個實體裏指定一個字節範圍或多個字節範圍。
ranges-specifier = byte-ranges-specifier
byte-ranges-specifier = bytes-unit "=" byte-range-set
byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
byte-range-spec = first-byte-pos "-" [last-byte-pos]
first-byte-pos = 1*DIGIT
last-byte-pos = 1*DIGIT
byte-range-spec裏的first-byte-pos值給出了一個範圍裏第一個字節的偏移量.。last-byte-pos值給出了這個範圍裏最後一個字節的偏移量;也就是說,肯定的字節位置必須在實體的範圍以內。字節偏移是以0爲基準(譯註:0表明第一個字節,1表明第二個字節)。
若是存在last-byte-pos值,那麼它必定大於或等於那個byte-range-spec裏的first-byte-pos,不然byte-range-spec在句法上是非法的。接收者接收到包括一個或多個無效的byte-range-spec值的byte-range-set時,它必須忽略包含那個byte-range-set的頭域.。
若是last-byte-pos值不存在,或者大於或等於實體主體的當前長度,則認爲last-byte-pos等於當前實體主體長度減一。
經過選擇last-byte-pos,客戶可以限制得到實體的字節數量而不須要知道實體的大小。
suffix-byte-range-spec = 「-「 suffix-length
suffix-length = 1*DIGIT
suffix-byte-range-spec用來表示實體主體的後綴,其長度由suffix-length值給出.。(也就是說,這種形式規定了實體正文的最後N個字節。)若是實體短於指定的suffix-length,則使用整個實體主體。
若是一個句法正確的byte-range-set至少包括一個這樣的byte-range-spec,它的first-byte-pos比實體主體的當前長度要小,或至少包括一個suffix-length非零的 suffix-byte-range-spec,那麼byte-range-set是能夠知足的,不然是不可知足的。若是byte-range-set不能知足,那麼服務器應該返回一個416響應(請求範圍不能知足)。不然,服務器應該返回一個206響應(部份內容)
byte-ranges-specifier(字節-範圍-說明符)值的例子(假定實體主體的長度爲10000):
-- 第一個500字節(字節偏移量0-499,包括0和499): bytes=0-499
-- 第二個500字節(字節偏移量500-999,包括500和999): bytes=500-999
-- 最後500字節(字節偏移量9500-9999,包括9500和9999): bytes=-500 或 bytes=9500-
-- 僅僅第一個和最後一個字節(字節0和9999): bytes=0-0,-1
-- 關於第二個500字節(字節偏移量500-999,包括500和999)的幾種合法但不規範的敘述:
bytes=500-600,601-999
bytes=500-700,601-999
14.35.2範圍請求(Range Retrieval Requests)
使用條件或無條件GET方法能夠請求一個或多個實體的字節範圍,而不是整個實體,這利用Range請求頭域,請求返回的結果就是Range頭域指示的請求資源實體的範圍。
Range = "Range" ":" ranges-specifier
服務器能夠忽略Range頭域。然而,.HTTP/1.1源服務器和中間緩存本應該儘量支持字節範圍,由於Range高效地支持從部分傳輸失敗的恢復,而且支持高效地從大的實體中獲取部份內容。
若是服務器支持Range頭域,而且指定的範圍或多個範圍對實體來講是適合的:
1. 若是在無條件GET請求裏出現Range頭域,那麼這將會改變返回結果(譯註:原本是返回整個實體,但出現Range頭域後,就返回了一部分)若是GET請求假設在沒有Range頭域時被服務器成功處理。換句話說,返回的狀態碼不是200(ok)而是206(部分響應)。
2. 若是在條件GET(請求裏利用了If-Modified-Since和If-None-Match中任意一個或他們兩個,或者利用了If-Unmodified-Since和If-Match中的任意一個或他們兩個)請求裏出現Range頭域,那麼這將改變返回的結果,若是GET請求假設在沒有Range頭域時被服務器成功成功而且條件爲真。但它不會影響304(沒有改變)響應的返回若是條件爲假。
某些情形下,除了使用Range頭域外,使用If-Range頭域(見14.27節)可能更合適。
若是支持範圍請求的代理接收了一個範圍請求,它會轉發(forward)此請求到入流(inbound)服務器,而且接收整個返回實體,但它只是返回給客戶的請求的範圍。代理將接收的整個響應存儲到它的緩存裏若是此響應知足緩存分配策略。
14.36 Referer
Referer請求頭域,爲了對服務器有用,容許客戶指定某資源的URI,客戶端今後資源得到的請求URI的地址(Referer頭域的Referer本應該寫成Referrer,出現了筆誤)。Referer請求頭域容許服務器產生返回到資源的URI連接的列表。它照樣容許服務器爲維護而跟蹤過期或寫錯的連接。Referer頭域不能被髮送若是請求URI從一個自己沒有URI的資源得到,例如用戶從鍵盤輸入。
得到請求URI的資源地址(URI)-爲了服務器的利益.Referer請求頭容許服務器生成關於到資源的反向鏈接(back-link)的列表,爲了興趣,記錄,優化的高速緩存等等.它也容許追蹤過期的或錯誤類型的鏈接(link)以便維護.若是請求URI是從一個沒有本身的URI的源得到的,如從使用者鍵盤的輸入,那麼必定不要發送Referer域.
Referer = "Referer" ":" ( absoluteURI | relativeURI )
例如:
Referer: http://www.w3.org/hypertext/DataSources/Overview.html
若是Referer頭域的域值是相對URI,那麼它將被解析爲相對於請求URI。URI不能包含一個片斷。見15.1.3關於安全的考慮。
14.37 Retry-After
Retry-After響應頭域能被用於一個503(服務不可得)響應,服務器用它來向請求端指明服務不可得的時長。此頭域可能被用於3xx(重定向)響應,服務器用它來(如web瀏覽器)指明用戶代理再次提交已重定向請求以前的最小等待時間。Retry-After頭域值多是HTTP-date或者也多是一個響應時間後的十進制整數秒。
Retry-After = 「Retry-After」 「:」 ( HTTP-date | delta-seconds )
下面是它的兩個例子
Retry-After: Fri,31 Dec 1999 23:59:59 GMT
Retry-After:120
在後一例子中,延遲時間是2分鐘。
14.38 Server
Server響應頭域包含了源服務器用於處理請求的軟件信息。 此域可包含多個產品標記(3.8節),以及鑑別服務器與其餘重要子產品的註釋。產品標記按它們的重要性來排列,並鑑別應用程序。
Server = 「Server」
例:
服務器:CERN/3.0 libwww/2.17
若響應是經過代理服務器轉發的,則代理程序不得修改服務器響應頭域。做爲替代,它應該包含一個Via頭域(在14.45節裏描述)。
注:揭示特定的軟件版本可能會使服務器易於受到那些針對已知安全漏洞的軟件的攻擊。 建議服務器實現者將此域做爲可設置項。
14.39 TE
TE請求頭域指明客戶端能夠接受哪些傳輸編碼(transfer-coding)的響應,和是否願意接收塊(chunked)傳輸編碼響應的尾部(trailer)(譯註:TE頭域和Accept-Encoding頭域與Content-Encoding頭域很類似,但TE應用於傳輸編碼(transfer coding),而Content-Encoding應用於內容編碼(content coding,見3.5節))。 TE請求頭域的值可能由包含關鍵字「trailers」 和/或用逗號分隔的擴展傳輸編碼名(擴展傳輸編碼名可能會攜帶可選的接受參數的列表)(在3.6節描述)組成。
TE = "TE" ":" #( t-codings )
t-codings = "trailers" | ( transfer-extension [ accept-params ] )
若是出現關鍵字「trailers」,那麼它指明客戶端願意接受(chunked)傳輸編碼響應的尾部(trailer)。 此關鍵字爲傳輸編碼(transfer-coding)值而保留,但它自己不表明一種傳輸編碼。
舉例:
TE: deflate
TE:
TE: trailers, deflate;q=0.5
TE請求頭域僅適用於當即鏈接。因此不管什麼時候,只要在HTTP/1.1消息中存在TE頭域,鏈接頭域(Connection header filed)(參見14.10節)中就必須指明。
經過TE頭域,服務器能利用下述規則來測試傳輸編碼(transfer-coding)是不是可被客戶端接受的:
塊(chunked)傳輸編碼老是能夠接受的(譯註:因此不須要在TE頭域裏指定塊(chunked)傳輸編碼,由於請求端老是能夠接收塊傳輸編碼)。若是在TE頭域裏出現關鍵字「trailers」,那麼客戶端指明它願意接受塊(chunked)傳輸編碼響應裏的尾部(trailer)。這意味着客戶端或者正在聲明全部的下游客戶端願意接收塊(chunked)傳輸編碼響應裏的尾部(trailer),或者聲明它願意表明下游接收端去嘗試緩存響應。
注意:HTTP/1.1並無定義任何方法去限制塊傳輸編碼響應的大小,這是爲了方便客戶端能緩存整個響應。
只要是出如今TE頭域裏的傳輸編碼都是可被請求端接受的,除非此傳輸編碼跟隨的qvalue值爲0(根據3.9節中定義,qvalue爲0代表是「不可接受的」(not acceptable)))
若是在TE頭域裏有指明多個傳輸編碼是可接受的,那麼傳輸編碼(transfer-coding)的qvalue值最大的是最容易被被接受的。塊傳輸編碼的qvalue值爲1。
若是TE頭域值是空的或者TE頭域沒有出如今消息裏,那麼服務器只能認爲塊(chunked)傳輸編碼的響應是請求端能夠接受的。沒有傳輸編碼的消息老是可接受的。
14.40 Trailer
Trailer經常使用頭域值指明瞭在以塊(chunked)傳輸編碼消息裏的尾部(trailer)裏用到的頭域。
Trailer = "Trailer" ":" 1#field-name
一個http/1.1消息會包含一個Trailer頭域,若是它利用了塊(chunked)傳輸編碼而且編碼裏的尾部(trailer)不爲空。這樣作是爲了使接收端知道塊(chunked)傳輸編碼響應消息尾部(trailer)有哪些頭域。
若是具備塊傳輸編碼的消息,沒有Trailer頭域存在,則此消息的尾部(trailer)將不能包括任何頭域。3.6.1節展現了塊傳輸編碼的尾部(trailer)的利用限制。
Trailer頭域中指示的消息頭域不能包括下面的頭域:
.Transfer-Encoding
.Content-Length
.Trailer
14.41 Transfer-Encoding
傳輸譯碼(Transfer-Encoding)經常使用頭域指示了消息主體(message body)的編碼轉換,這是爲了實如今接收端和發送端之間的安全數據傳輸。它不一樣於內容編碼(content-coding),傳輸代碼是消息的屬性,而不是實體(entity)的屬性。
Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
傳輸編碼(transfer-coding)在3.6節中被定義了。一個例子是:
Transfer-Encoding: chunked
若是一個實體應用了多種傳輸編碼,傳輸編碼(transfer-coding)必須以應用的順序列出。傳輸編碼(transfer-coding)可能會提供編碼參數(譯註:看傳輸編碼的定義,3.6節),這些編碼參數額外的信息可能會被其它實體頭域(entity-header)提供,但這並無在規範裏定義。
許多老的HTTP/1.1應用程序不能理解傳輸譯碼(Transfer-Encoding)頭域。
14.42 Upgrade
Upgrade經常使用頭域容許客戶端指定它支持什麼樣的附加傳輸協議,若是服務器會切換到Upgrade指定的協議若是它以爲合適的話。服務器必須利用Upgrade頭域於一個101(切換協議)響應裏,用來指明將哪一個協議被切換了。
Upgrade = 「Upgrade」 「:」 1#product
例如,
Upgrade: HTTP/2.0,SHTTP/1.3, IRC/6.9, RTA/x11
Upgrade頭域的目的是爲了提供一個從HTTP/1.1到其它不兼容協議的簡單遷移機制。這樣作是經過容許客戶端通知本身指望使用另外一種協議來實現的,例如更新版本的HTTP協議,即便當前請求仍然使用HTTP/1.1。使不兼容協議的遷移變得簡單,這隻須要客戶端去發起一個都被支持的協議的請求,而且向服務器指明本身想要使用更好的協議若是可行的話。
Upgrade頭域只能應用於切換應用程序層(application –layer)協議,應用程序層協議在傳輸層(transport-layer)鏈接之上。Upgrade頭域並不意味着協議必定要改變;服務器能夠接受而且能夠選擇。在協議改變後應用程序層(apllication-layer)通訊的能力和本質,徹底依賴於新協議的選擇,儘管在改變協議後的第一次動做必須是對初始HTTP請求(包含Upgrade頭域)的響應。
Upgrade頭域只能應用於當即鏈接(immediate connection)。所以,upgrade關鍵字必須被提供在Connection頭域裏(見14.10節),只要Upgrade頭域呈如今HTTP/1.1消息裏。
Upgrade頭域不能被用來指定切換到一個不一樣鏈接的協議。爲這個目的,使用301,302,303重定向響應更合適。
這個規範定義了本協議的名字爲「HTTP」,它在3.1節的HTTP版本規則中定義的超文本傳輸協議家族中被使用。任何一個標記均可被用來作協議名字,然而,只有當客戶端和服務器用在同一協議裏使用此名字纔有用。
14.43 User-Agent
User-Agent請求頭域包含關於發起請求的用戶代理的信息。這是爲了統計,跟蹤協議違反的狀況,和爲了識別用戶代理從而爲特定用戶代理自動定製響應。用戶代理應該包含User-Agent頭域在請求中。此頭域包含多個識別代理和子產品的產品標記(見3.8節)和解釋。一般,產品標記按重要程度的順序排列從而去指定應用程序。
User-Agent = "User-Agent" ":" 1*( product | comment )
例子:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
14.44 Vary
Vary頭域值指定了一些請求頭域,這些請求頭域用來決定當緩存中存在一個響應是保鮮時緩存是否被容許去利用此響應去回覆後續請求而不須要重驗證(revalidation)。對於一個不能被緩存或陳舊的響應,Vary頭域值用於告訴用戶代理選擇表現形式(reprentation)的標準。一個Vary頭域值是「*」意味着緩存不能從後續請求的請求頭域來決定合適表現形式的響應。見13.6節關於緩存如何利用Vary頭域。
Vary = "Vary" ":" ( "*" | 1#field-name )
一個HTTP/1.1的服務器應該包含一個Vary頭域於任何可緩存的受限於服務器驅動協商的響應裏。這樣作是容許緩存合適地解析關於那個資源的未來請求,並通知用戶代理那個資源導向地址的出現。一個服務器可能包含一個Vary頭域於一個不可緩存的受限於服務器驅動協商的響應裏,由於這樣作可能爲用戶代理提供有用的而且響應據此而變化的維度信息。
一個Vary頭域值由域名(filed-name)組成,響應的表現形式是基於Vary頭域裏列舉的請求頭域來選擇的。一個緩存可能會假設爲未來請求進行相同的選擇,若是Vary頭域例舉了相同的域名,但必須是此響應在此期間是保鮮的。
Vary頭域裏的域名並非侷限於本規範裏定義的標準請求頭域。域名是大小寫不敏感的。
Vary域值爲」*」意味着不受限於請求頭域的非特定參數在選擇響應表現形式中起做用 。」*」值不能被代理服務器產生;它可能只能被源服務器產生。
14.45 Via
Via經常使用頭域必須被網關和代理使用,用來指明用戶代理和服務器之間關於請求的中間協議和接收者,和源服務器和客戶端之間關於響應的中間協議和接收者。它和RFC822[9]裏的「Received」頭域類似,而且它用於跟蹤消息的轉發,避免請求循環,和指定沿着請求/響應鏈的全部發送者的協議能力。
Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
received-protocol = [ protocol-name "/" ] protocol-version
protocol-name = token
protocol-version = token
received-by = ( host [ ":" port ] ) | pseudonym
pseudonym = token
received-protocol指出沿着請求/響應鏈每一段的服務器或客戶端所接收消息的協議版本。protocol-version被追加於Via頭域值後面,當消息被轉發時。
只要協議是HTTP,那麼protocol-name是無關緊要的。received-by頭域一般是接收的轉發服務器的host(主機)和可選的port(端口)號,或接收的轉發客戶端的host(主機)和可選的port(端口)號。然而,若是真實host(主機)被看做是信息敏感的,那麼此主機可能會被別名代替。若是port(端口號)沒有被給定,那麼它可能被假設爲received-protocol的缺省port(端口)號。
Via頭域裏若是有多個域值,則每一個值分別表明一個已經轉發消息的代理或網關。每個接收者必須把它的信息追加到最後,因此最後的結果是按照轉發應用程序的順序來的。
comment(註釋)可能被用於Via頭域是爲了指定接收者代理或網關的軟件,這個比如User-Agent和Server頭域。然而,Via頭域裏全部的comment是可選的(譯註:無關緊要的),而且能夠被接收者在轉發消息以前移去。
例如,有一個請求消息來自於一個HTTP/1.0用戶代理,被髮送到代號爲「fred」的內部代理,此內部代理利用HTTP/1.1協議轉發此請求給一個站點爲nowhere.com的公共代理,而此公共代理爲了完成此請求經過把它轉發到站點爲www.ics.uci,edu的源服務器。被www.ics.uci.edu站點接收後的請求這時可能有下面的Via頭域:
Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
被用做通向網絡防火牆的入口的代理和網關在缺省狀況下不該該轉發host(主機)的名字和端口到防火牆區域裏。若是這些信息顯示地指定要被傳送,那麼就應該被傳送。若是此信息顯示地指定不能被傳送,那麼任何穿過防火牆而被接收的host(主機)應該用一個合適的別名替換。
爲了隱藏組織結構的內部結構須要,一個代理(proxy)可能會在一個Via頭域中把相同received-protocal值的項合成一個項。例如,
Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
將被摺疊成
Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
應用程序不該該合併多個項,除非他們都在相同組織的控制下而且host(主機)已經被別名代替了。應用程序不能合併不一樣received-protocaol值的項。
14.46 Warning
Warning經常使用頭域被用於攜帶額外關於消息的狀態或變換的信息而這些信息是不能在消息裏反應出來的。這些信息一般被用於去警告來自於緩存操做或來自於應用於消息實體主體轉換的關於語義透明性(semantic transparency)的缺乏。
Warning頭域被用於響應裏,這裏有以下語法:
Warning = "Warning" ":" 1#warning-value
warning-value = warn-code SP warn-agent SP warn-text
[SP warn-date]
warn-code = 3DIGIT
warn-agent = ( host [ ":" port ] ) | pseudonym
; the name or pseudonym of the server adding
; the Warning header, for use in debugging
warn-text = quoted-string
warn-date = <"> HTTP-date <">
一個響應可能攜帶多個Warning頭域。
warn-text必須使用對於接收響應的用戶來講儘量能理解的天然語言和字符集。找到用戶自能理解的天然語言和字符集,必須基於任何可能的知識,如緩存或用戶的位置,請求裏的Accept-Language頭域,響應裏的Content-Language頭域,等等。缺省語言是英語,缺省字符集是ISO-8859-1。
若是字符集不是ISO-8859-1,那麼它必須利用RFC2047裏描述的來在warn-text裏進行編碼。
Warning頭域能被應用於任何消息,然而,一些warn-codes是特定於緩存的,而且能被應用於響應消息。新的Warning頭域應該加在任何已存在Warning頭域的後面。緩存不能刪除任何它接收的消息裏的Warning頭域。然而,若是一個緩存要去成功驗證了一個緩存項,那麼它應該移除任何附加在那個緩存項之前的Warning頭域除了特定於此Warning code的Warning頭域。它而後必須添加任何接收的Warning頭域於驗證響應裏。換句話說,附加的必須是最近的相關於響應的Warning頭域。
當多個Warning頭域被附加於一個響應裏,那麼用戶代理應該通知用戶儘量多的警告,而且以它們呈如今響應裏的順序。若是用戶代理不能通知用戶全部的警告,那麼用戶代理應該按照下面的規則:
- 前面的響應裏的警告優於後面響應的警告
- 用戶偏心的字符集的警告優於其它字符集的警告,但這除了warn-codes和warn-agents一致的狀況。
產生多個Warning頭域的系統應該時刻記住利用用戶代理行爲來安排警告。
關於警告的緩存行爲的要求在13.1.2裏描述。
下面是當前定義的warn-codes,每個warn-code都有一個建議性的以英語表示的warn-text,和它的意思的描述。
110 Response is stale
不管什麼時候當返回響應是陳舊的時候,必須被包含。
111 Revalidation failed
若是一個緩存由於嘗試去重驗證響應失敗而返回一個陳舊的響應(因爲不能到達服務器),必須被包含。
112 Disconnected operation
若是緩存在一段時間被有意地斷開鏈接,應該被包含。
113 Heuristic expiration
若是緩存探索性地選擇了一個保鮮壽命大於24小時而且響應的年齡大於24小時時,必須被包含。
199 Miscellaneous warning
警告文本可能包含任意信息呈現給用戶。除了呈現給用戶警告,接收警告的系統不能採起任何自動行爲。
214 Transformation applied
若是一箇中間緩存或代理採用任何對響應的內容編碼(content-coding)(在Content-Encoding頭域裏指定)或媒體類型(media-type)(在Content-Type頭域裏指定)的改變變,或響應的實體主體(entity-body)的該變,那麼此響應碼必須被中間緩存或代理添加,除非此警告碼(warning code)已經在響應裏出現。
299 Miscellaneous persistent warning
警告文本應該包含任意呈現給用戶的任意信息。接收警告的系統不能採起任何自動行爲。
若是一個實如今一個消息裏發送多個版本是HTTP/1.0或更早的HTTP協議版本的Warning頭域,那麼發送者必須包含一個和響應日期(date)相等的warn-date到每個Warning頭域值中。
若是一個實現收到一條warning-value裏包含一個warn-date的消息,而且那個warn-date不一樣於響應裏的Date值,那麼warning-value必須在保存,轉發,或利用消息以前從消息裏刪除。(這回防止本地緩存去緩存Warning頭域的惡果。)若是全部warning-value由於這個緣由而被刪除,Warning頭域必須也要被刪除。
14.47 WWW-Authenticate
WWW-Authenticate響應頭域必須包含在401(沒有被受權)響應消息中。此域值至少應該包含一個callenge,此callenge指明受權方案(譯註:有的地方翻譯成模式)和適用於請求URI的參數。
WWW-Authenticate =「WWW-Authenticate」 「:」 1#challenge
HTTP訪問受權過程在「HTTP Authentication: Basic and Digest Access Authentication」[43]裏描述。用戶代理被建議特別當心去解析WWW-Authenticate頭域值,當此頭域值包含多個challenge,或若是多個WWW-Authenticate頭域被提供且challenge的內容能包含逗號分隔的受權參數的時候。
15.安全考慮 (Security Consideration)
這一部分是用來提醒程序開發人員,信息提供者,和用戶關於HTTP/1.1安全方面的限制。討論並不包含對披露問題的明確的解決辦法,然而,確對減小安全風險提供了一些建議。
15.1 我的信息 (Personal Information)
HTTP的客戶端常常要對大量的我的信息保密(例如用戶的名字,域,郵件地址,口令,密匙等。),而且應當很是當心地防止這些信息無心識地經過HTTP協議泄露到其餘的資源。咱們很是強烈地建議應該給用戶提供一個方便的界面來控制這種信息的傳播,而且設計者和實現者在這方面應該特別注意。歷史告訴咱們在這方面的錯誤常常引發嚴重的安全和/或者隱私問題,並致使對設計或實現者的公司產生很是不利的影響。
15.1.1服務器日誌信息的濫用 (Abuse of Server Log Information)
服務器是用來保存用來指定用戶讀模型或感興趣主題的請求的。這些信息一般顯然是需保密的,而且它的使用在某些國家被法律保護。利用HTTP協議提供數據的人們必須保證在這些數據被許可的狀況下分發。
15.1.2敏感信息的傳輸 (Transfer of Sensitive Inforamtion)
就像任何數據傳輸協議同樣,HTTP不能調整數據傳輸的內容,也沒有任何經驗方法去決定給定請求背景裏特定信息的敏感性。所以,應用程序應該儘量爲此信息提供者提供對此信息的控制。背景裏有四個頭域須要提出來,這四個頭域是:Server,Via,Referer 和From。
揭露服務器特定軟件版本可能會使服務器的機器更容易受到經過軟件安全漏洞來進行攻擊。實現者應該使Server頭域成爲可設置的選項。
用做穿過網絡防火牆入口的代理應該特別當心關於指定防火牆後的主機(host)頭域信息的傳輸。特別地,代理應該移除或用殺毒後的版本替換任何產生於防火牆以後的Via頭域。
Referer頭域容許學習的讀模型和反向連接牽引。雖然它很是有用,但也會被濫用若是用戶詳情沒有從包含在Referer頭域裏信息分離開來。即便當我的信息已經被移除了,那麼這個Referer頭域也可能指定私有的文檔URI,此文檔不適合做爲共有的。
From頭域裏的信息可能會和用戶的私有興趣或他們站點的安全策略相沖突,所以這些信息在用戶使此頭域內容無效、有效和改變的狀況下不能被傳輸。用戶必須能在用戶的喜好或應用程序的缺省設置範圍內設置此頭域的內容。
咱們建議,儘管不須要,給用戶提供一個方便的觸發器來使發送From和Referer頭域信息有效或失效。
User-Agent(14.4節)或Server(14.38節)頭域有時候能被用來去肯定一個特定的客戶端或服務器存在安全漏洞。不幸的是,一樣的信息常常被用於其它的有價值的目的由於HTTP如今沒有更好的機制。
15.1.3 URI中敏感信息的編碼(Encoding Sensitive Information in URI’s)
由於一個連接的源多是私有信息或者可能揭露其它私有信息資源,因此強烈建議用戶能選擇是否須要發送Referer頭域。例如,瀏覽器客戶端可能爲了開放/匿名方式會有一個觸發開關,此開關可能使Referer頭域和From頭域信息的發送有效/無效。
客戶端不該該包含一個Referer頭域在一個非安全HTTP請求裏,若是參考頁面在一個安全的協議上傳輸。
利用HTTP協議的服務做者不該該利用基於窗體GET提交敏感數據,由於這個能引發數據在請求URI裏被編碼。許多已存在的服務,代理,和用戶代理將記錄請求URI於某些對第三方可見的地方。服務器能利用基於窗體POST提交來取代基於窗體GET提交。
15.1.4鏈接到Accept頭域的隱私問題
Accept請求頭域能揭露用戶的信息給全部被訪問的服務器。Accept-Language頭域能揭露用戶的私有信息,由於能理解特定語言的人常常被認爲就是某個特定種族裏的成員。提供選擇設置Accept-Language頭域內容於每次請求裏的用戶代理被強烈鼓勵讓設置過程包含一個讓用戶知道隱私丟失的消息。
限制私有信息的方法多是在缺省狀況下讓用戶代理不發送Accept-Language頭域,而且讓用戶代理詢問用戶是否發送Accept-Language頭域給服務器若是用戶代理經過查看任何由服務器產生的Vary響應頭域時發現此次發送能提升服務的質量。
請求裏的用戶配置性的接受頭域若是這些接受頭域(accept header fileds)包含質量值,那麼他們應該被服務器用做相對信賴和長久的用戶標識符。這樣的用戶標識符將會容許內容提供者進行click-trail跟蹤以及容許合做內容提供者匹配跨服務器click-trail或者造成單個用戶窗體提交。注意對於許多並不在代理服務器後面的用戶,運行用戶代理的主機的網絡地址也將做爲長久用戶的標識符。在代理服務器被用做加強隱私的環境裏,用戶代理在提供給終端用戶接受(accept)頭域配置選項上應該是保守的。提供高度頭域配置能力的用戶代理應該警告用戶隱私可能的丟失。
15.2 基於文件和路徑名稱的攻擊
HTTP的源服務器的實現應該當心地限制HTTP請求返回的文檔給那些由管理員受權的人。若是HTTP服務器要把HTTP URIs翻譯成文件系統的調用,那麼服務器必須當心去對待提供給HTTP客戶端的文件傳輸。例如,UNIX,微軟Windows,和其餘操做系統都利用」..」去指示當前的父目錄。對於這一個系統,若是HTTP服務器容許訪問一個資源,但這些資源經過HTTP服務器不能訪問,那麼一個HTTP服務器必須不容許任何這樣的構造存在於請求URI。一樣的,用做服務器內部文件的引用的文件(如訪問控制文件,配置文件,腳本代碼)必須受到保護不讓不合適的獲取,由於他們可能包含敏感的信息。經驗告訴咱們一個在HTTP服務器實現裏的一個小小的錯誤會帶來安全風險。
15.3 DNS欺騙
使用HTTP的客戶端嚴重依賴於域名服務,所以這會致使基於IP和DNS名稱的不關聯的攻擊。客戶端須要當心關注IP地址/DNS名稱關聯的持久合法性。
特別地,HTTP客戶端爲了確認IP地址/DNS名稱關聯性,應該依賴於客戶端本身的的名稱解析器,而不是緩存之前主機(host)名稱查找(host name lookups)結果。許多平臺已經能本地的去緩存主機名稱查找(host name lookups)當在合適的時候,而且他們應該被配置成能這樣作。然而,只有當被名稱服務器報告的TTL(Time To Live)信息使被緩存的信息仍然有用時,緩存查找(lookups)纔是合適的。
若是HTTP客戶端爲了提升性能去緩存主機名稱查找(host name lookups)的結果,那麼他必須觀察被DNS報告的TTL信息。
若是HTTP客戶端不能看到這條規則,那麼他們就會被欺騙當之前訪問的IP地址改變時。由於網絡地址的改變變得很日常,因此這種形式的攻擊在不斷增長。看到這個規則能減小潛在的安全攻擊的可能性。
此要求照樣能提供客戶端負載平衡行爲由於重複的服務器能利用同一個DNS名稱,此要求能下降用戶在訪問利用策略(strategy)的站點中的體驗失敗。
15.4 Location頭域和欺騙
若是單個的服務器支持互不信任的多個組織,那麼它必須檢查自稱的某個組織控制下產生響應裏Location和Content-Location頭域值,以確認這些組織沒有企圖使它們沒有權限的資源無效。
15.5 Content-Disposition的問題
RFC 1806 [35],在HTTP中常用的Content-Disposition(見19.5.1節)頭域就源於此文檔,有許多很是認真的安全考慮在此文檔裏說明。Content-Disposition並非HTTP標準版本中的一部分,但自從它被普遍應用以來,咱們正在證實它對使用者的價值和風險。詳細資料見RFC 2183 [49](對RFC 1806的升級)。
15.6 受權證書和空閒客戶端
現有的HTTP客戶端和用戶代理一般會不肯定地保留受權信息。HTTP/1.1並無爲服務器提供一個方法讓服務器去指導客戶端丟棄這些緩存的證書(credentials)。這是一個重大缺陷,此缺陷須要擴展HTTP協議來解決。在某些狀況下,證書的緩存能干涉應用程序的安全模型,此狀況包含但不侷限於:
Ø 這樣的客戶端。此客戶端已經空閒時間超長而且服務器可能但願再次讓客戶端出示證書。
Ø 這樣的應用程序。此應用程序包括了一個會話中斷指令(例如在一頁上有"logout"或者"commit"的按鈕),依據此指令應用程序的服務器端「知道」沒有更多的理由爲客戶端保留證書。
這是做爲當前單獨研究的。有不少解決這個問題的社區,而且咱們鼓勵在屏幕保護程序,空閒超時,和其餘能減輕安全問題的方法裏利用密碼保護。特別地,能緩存證書的用戶代理被鼓勵去提供一個容易地訪問控制機制讓在用戶的控制下去丟棄緩存的證書。
15.7 代理和緩存 (Proxies and Caching)
本質上說,HTTP代理是中間人(men-in-the-middle),而且存在中間人攻擊(man-in-the-middle attacks)危險。代理運行在其上系統的折中能致使嚴重的安全和隱私問題。代理擁有對相關安全信息、用戶和組織的我的信息、和屬於用戶和內容提供者的專有信息的訪問權限。一個妥協的代理,或一個沒有考慮安全性和隱私性的代理可能會被用作進行攻擊的代理。
代理操做者應該保護代理運行其上的系統,正如他們保護任何包含或傳輸敏感信息的系統同樣。特別的,代理上收集的日誌信息常常包含較高的我的敏感信息,和/或關於組織的信息。日誌信息應該被當心的保護,而且要合適地開發利用。(見15.1.1)節。
代理的設計者應當考慮到設計和編碼斷定所涉及到的隱私和安全問題,以及他們提供給代理操做人員配置選項(尤爲是缺省配置)所牽涉到的隱私和安全問題。
代理的用戶須要知道他們本身不比運行代理的操做員更值得信賴;HTTP協議自身不能解決這個問題。
當合適的時候,對密碼學的正確應用,可能會保護普遍的安全和隱私攻擊。密碼學的討論不在本協議文檔的範圍內。
15.7.1關於代理的服務攻擊的拒絕
代理是存在的。代理很難被保護。關於此研究正在進行。
16 感謝(Acknowledgment)
這份規範大量使用了擴展BNF和David爲RFC 822 [9]定義的經常使用結構。一樣的,它繼續使用了不少Nathaniel Borenestein和Ned Freed爲MIME [7]提供的定義。咱們但願在此規範裏他們的結論有助於減小過去在HTTP和互聯網郵件消息格式關係上的混淆。
HTTP協議在這幾年已經有了至關的發展。它受益於大量積極的開發人員的社區--許多人已經經過www-talk郵件列表參與進來--而且一般就是那個社區對HTTP和萬維網的成功做了重大貢獻。 Marc Andreessen, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois Groff , Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob McCool, Lou Montulli, Dave Raggett, Tony Sanders, 和 Marc VanHeyningen由於他們在定義協議早期方面的貢獻應該獲得特別的讚譽。
這篇文檔從全部那些參加HTTP-WG的人員的註釋中得到了很大的益處。除了已經提到的那些人之外,下列人士對這個規範作出了貢獻:
Gary Adams Ross Patterson
Harald Tveit Alvestrand Albert Lunde
Keith Ball John C. Mallery
Brian Behlendorf Jean-Philippe Martin-Flatin
Paul Burchard Mitra
Maurizio Codogno David Morris
Mike Cowlishaw Gavin Nicol
Roman Czyborra Bill Perry
Michael A. Dolan Jeffrey Perry
David J. Fiander Scott Powers
Alan Freier Owen Rees
Marc Hedlund Luigi Rizzo
Greg Herlihy David Robinson
Koen Holtman Marc Salomon
Alex Hopmann Rich Salz
Bob Jernigan Allan M. Schiffman
Shel Kaphan Jim Seidman
Rohit Khare Chuck Shotton
John Klensin Eric W. Sink
Martijn Koster Simon E. Spero
Alexei Kosut Richard N. Taylor
David M. Kristol Robert S. Thau
Daniel LaLiberte Bill (BearHeart) Weinman
Ben Laurie Francois Yergeau
Paul J. Leach Mary Ellen Zurko
Daniel DuBois Josh Cohen
緩存設計的許多內容和介紹應歸於如下人士的建議和註釋:Shel Kaphan, Paul Leach, Koen Holtman, David Morris, 和 Larry Masinter。
大部分規範的範圍是基於Ari Luotonen和John Franks早期作的工做,以及從Steve Zilles另外加入的內容。
感謝Palo Alto的"cave men"。大家知道大家是誰。
Jim Gettys(這篇文檔如今的編者)特別但願感謝Roy Fielding,這篇文檔之前的編者,連同John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, 和Larry Masinter一塊兒感謝他們的幫助。還要特別感謝Jeff Mogul和Scott Lawrence對「MUST/MAY/ SHOULD」使用的檢查。
Apache組,Anselm Baird-Smith,Jigsaw的做者,和Henrik Frystyk在早期實現了RFC 2068,咱們但願感謝他們發現了許多這篇文檔正嘗試糾正的問題。
17 參考資料 (Reference)
[1] Alvestrand, H., "Tags for the Identification of Languages", RFC
1766, March 1995.
[2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey,
D. and B. Alberti, "The Internet Gopher Protocol (a distributed
document search and retrieval protocol)", RFC 1436, March 1993.
[3] Berners-Lee, T., "Universal Resource Identifiers in WWW", RFC
1630, June 1994.
[4] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource
Locators (URL)", RFC 1738, December 1994.
[5] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language -
2.0", RFC 1866, November 1995.
[6] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer
Protocol -- HTTP/1.0", RFC 1945, May 1996.
[7] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part One: Format of Internet Message Bodies",
RFC 2045, November 1996.
[8] Braden, R., "Requirements for Internet Hosts -- Communication
Layers", STD 3, RFC 1123, October 1989.
[9] Crocker, D., "Standard for The Format of ARPA Internet Text
Messages", STD 11, RFC 822, August 1982.
[10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R.,
Sui, J., and M. Grinbaum, "WAIS Interface Protocol Prototype
Functional Specification," (v1.5), Thinking Machines
Corporation, April 1990.
[11] Fielding, R., "Relative Uniform Resource Locators", RFC 1808,
June 1995.
[12] Horton, M. and R. Adams, "Standard for Interchange of USENET
Messages", RFC 1036, December 1987.
[13] Kantor, B. and P. Lapsley, "Network News Transfer Protocol", RFC
977, February 1986.
[14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
Three: Message Header Extensions for Non-ASCII Text", RFC 2047,
November 1996.
[15] Nebel, E. and L. Masinter, "Form-based File Upload in HTML", RFC
1867, November 1995.
[16] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821,
August 1982.
[17] Postel, J., "Media Type Registration Procedure", RFC 1590,
November 1996.
[18] Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC
959, October 1985.
[19] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, RFC 1700,
October 1994.
[20] Sollins, K. and L. Masinter, "Functional Requirements for
Uniform Resource Names", RFC 1737, December 1994.
[21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for
Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.
[22] ISO-8859. International Standard -- Information Processing --
8-bit Single-Byte Coded Graphic Character Sets --
Part 1: Latin alphabet No. 1, ISO-8859-1:1987.
Part 2: Latin alphabet No. 2, ISO-8859-2, 1987.
Part 3: Latin alphabet No. 3, ISO-8859-3, 1988.
Part 4: Latin alphabet No. 4, ISO-8859-4, 1988.
Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988.
Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987.
Part 7: Latin/Greek alphabet, ISO-8859-7, 1987.
Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988.
Part 9: Latin alphabet No. 5, ISO-8859-9, 1990.
[23] Meyers, J. and M. Rose, "The Content-MD5 Header Field", RFC
1864, October 1995.
[24] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC
1900, February 1996.
[25] Deutsch, P., "GZIP file format specification version 4.3", RFC
1952, May 1996.
[26] Venkata N. Padmanabhan, and Jeffrey C. Mogul. "Improving HTTP
Latency", Computer Networks and ISDN Systems, v. 28, pp. 25-35,
Dec. 1995. Slightly revised version of paper in Proc. 2nd
International WWW Conference '94: Mosaic and the Web, Oct. 1994,
which is available at
http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat
ency.html.
[27] Joe Touch, John Heidemann, and Katia Obraczka. "Analysis of HTTP
Performance", <URL: http://www.isi.edu/touch/pubs/http-perf96/>,
ISI Research Report ISI/RR-98-463, (original report dated Aug.
1996), USC/Information Sciences Institute, August 1998.
[28] Mills, D., "Network Time Protocol (Version 3) Specification,
Implementation and Analysis", RFC 1305, March 1992.
[29] Deutsch, P., "DEFLATE Compressed Data Format Specification
version 1.3", RFC 1951, May 1996.
[30] S. Spero, "Analysis of HTTP Performance Problems,"
http://sunsite.unc.edu/mdma-release/http-prob.html.
[31] Deutsch, P. and J. Gailly, "ZLIB Compressed Data Format
Specification version 3.3", RFC 1950, May 1996.
[32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP:
Digest Access Authentication", RFC 2069, January 1997.
[33] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC
2068, January 1997.
[34] Bradner, S., "Key words for use in RFCs to Indicate Requirement
Levels", BCP 14, RFC 2119, March 1997.
[35] Troost, R. and Dorner, S., "Communicating Presentation
Information in Internet Messages: The Content-Disposition
Header", RFC 1806, June 1995.
[36] Mogul, J., Fielding, R., Gettys, J. and H. Frystyk, "Use and
Interpretation of HTTP Version Numbers", RFC 2145, May 1997.
[jg639]
[37] Palme, J., "Common Internet Message Headers", RFC 2076, February
1997. [jg640]
[38] Yergeau, F., "UTF-8, a transformation format of Unicode and
ISO-10646", RFC 2279, January 1998. [jg641]
[39] Nielsen, H.F., Gettys, J., Baird-Smith, A., Prud'hommeaux, E.,
Lie, H., and C. Lilley. "Network Performance Effects of
HTTP/1.1, CSS1, and PNG," Proceedings of ACM SIGCOMM '97, Cannes
France, September 1997.[jg642]
[40] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part Two: Media Types", RFC 2046, November
1996. [jg643]
[41] Alvestrand, H., "IETF Policy on Character Sets and Languages",
BCP 18, RFC 2277, January 1998. [jg644]
[42] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource
Identifiers (URI): Generic Syntax and Semantics", RFC 2396,
August 1998. [jg645]
[43] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
Leach, P., Luotonen, A., Sink, E. and L. Stewart, "HTTP
Authentication: Basic and Digest Access Authentication", RFC
2617, June 1999. [jg646]
[44] Luotonen, A., "Tunneling TCP based protocols through Web proxy
servers," Work in Progress. [jg647]
[45] Palme, J. and A. Hopmann, "MIME E-mail Encapsulation of
Aggregate Documents, such as HTML (MHTML)", RFC 2110, March
1997.
[46] Bradner, S., "The Internet Standards Process -- Revision 3", BCP
9, RFC 2026, October 1996.
[47] Masinter, L., "Hyper Text Coffee Pot Control Protocol
(HTCPCP/1.0)", RFC 2324, 1 April 1998.
[48] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part Five: Conformance Criteria and Examples",
RFC 2049, November 1996.
[49] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation
Information in Internet Messages: The Content-Disposition Header
Field", RFC 2183, August 1997.
18 做者地址
Roy T. Fielding
Information and Computer Science
University of California, Irvine
Irvine, CA 92697-3425, USA
Fax: +1 (949) 824-1715
EMail: fielding@ics.uci.edu
James Gettys
World Wide Web Consortium
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA
Fax: +1 (617) 258 8682
EMail: jg@w3.org
Jeffrey C. Mogul
Western Research Laboratory
Compaq Computer Corporation
250 University Avenue
Palo Alto, California, 94305, USA
EMail: mogul@wrl.dec.com
Henrik Frystyk Nielsen
World Wide Web Consortium
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA
Fax: +1 (617) 258 8682
EMail: frystyk@w3.org
Larry Masinter
Xerox Corporation
3333 Coyote Hill Road
Palo Alto, CA 94034, USA
EMail: masinter@parc.xerox.com
Paul J. Leach
Microsoft Corporation
1 Microsoft Way
Redmond, WA 98052, USA
EMail: paulle@microsoft.com
Tim Berners-Lee
Director, World Wide Web Consortium
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA
Fax: +1 (617) 258 8682
EMail: timbl@w3.org
19 附錄
19.1 互聯網媒體類型message/http和application/http
這篇文檔除了定義HTTP/1.1協議外,還用做互聯網媒介類型"message/http"和"application/http"的規範。此類型用於封裝一個HTTP請求消息或響應消息,這假設此類型遵循MIME對 全部「消息」類型關於行長度和編的限制。application/http類型能夠用來封裝一個或者更多HTTP請求或響應信息(非混合的)的傳輸路徑(pipeline)。下列是在IANA[17]註冊的。
媒介類型名稱: message
媒介次類型名稱: http
必須參數: 無
可選參數: 版本,信息類型
版本:封裝信息的HTTP版本號(例如,"1.1")。若是不存在,版本能夠從消息的第一行肯定。
信息類型:信息類型--"請求"或者"響應"。若是不存在,類型能夠從報文的第一行肯定。
編碼考慮:只有"7bit","8bit",或者"二進制"是容許的。
安全考慮:無
媒介類型名稱: application
媒介次類型名稱: http
必須參數: 無
可選參數: 版本,信息類型
版本:封裝信息的HTTP版本號(例如,"1.1")。若是不存在,版本能夠從報文的第一行肯定。
信息類型:信息類型--"request"或者"response"。若是不存在,類型能夠從報文的第一行肯定。
編碼考慮:用這種類型封裝的HTTP信息是"二進制"的格式;當經過E-mail傳遞的時候一種合適的內容傳輸編碼是必須的。
安全考慮:無
19.2 互聯網媒體類型multipart/byteranges
當一個HTTP206(部份內容)響應信息包含多個範圍的內容(請求響應的內容有多個非重疊的範圍),這些是做爲一個多部分消息主體來被傳送的。這種用途的媒體類型被稱做"multipart/byteranges"。
multipart/byteranges媒體類型包括兩個或者更多的部分,每個都有本身Content-type和Content-Range頭域。必需的分界參數(boundary parameter)指定分界字符串,此分界字符串用來隔離每一部分。
媒介類型名稱: multipart
媒介次類型名稱: byteranges
必須參數: boundary
可選參數: 無
編碼考慮:只有"7bit","8bit",或者"二進制"是容許的。
安全考慮:無
例如:
HTTP/1.1 206 Partial Content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-type:multipart/byteranges;boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 500-999/8000
...第一部分...
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 7000-7999/8000
...第二部分
--THIS_STRING_SEPARATES--
注意:
在實體(entity)中,在第一個分界字符串以前能夠有多餘的CRLFs。
雖然RFC 2046 [40]容許分界字符串加引號,可是一些現有的實現會不正確的處理分界字符串
許多瀏覽器和服務器是按照字節範圍標準的早期草案關於使用multipart/x-byteranges媒體類型來進行編碼的的,這個草案不老是徹底和HTTP/1.1中描述的版本兼容。
19.3 寬鬆的應用程序 (Tolerent Applications)
雖然這篇文檔列出了HTTP/1.1消息所必須的元素,可是並非全部的程序在實現的時候都是正確的。所以咱們建議當誤差能夠明確解釋的時候,運算程序對這種誤差應該是寬容的。
客戶端應該寬鬆的解析Status-Line(狀態行);服務器也應該寬鬆的解析Request-Line(請求行)。特別的,他們應該能夠接受頭域之間任何數量的SP或HT字符,即便協議規定只有一個SP。
消息頭域的行終結符是CRLF。然而,當解析這樣的頭域時,咱們建議應用程序能識別單一LF做爲行終結符並能忽略CR。
實體主體(entity-body)的字符集應該被標記爲應用於實體主體字符編碼的最小公分母,而且指望不對實體進行標記要優於對實體標記爲US-ASCII或ISO-8859-1。見3.7.1和3.4.1。
對關於日期分析和編碼的要求的額外規則以及其它對日期編碼的潛在問題包含:
Ø HTTP/1.1客戶端和緩存應該假定一個彷佛是50多年之後的RFC-850日期其實是過去的(這有助於解決"2000年"問題)。
Ø 一個HTTP/1.1的實現能夠內部地表示一個比正確日期值更早的已解析後的Expires日期,可是必定不要(MUST NOT)內部地表示一個比正確日期值更遲的已解析過的Expires日期。
Ø 全部過時日期相關的計算必須用GMT時間。本地時區必定不能(MUST NOT)影響年齡或過時時間的計算。
Ø 若是一個HTTP頭域不正確的攜帶了一個非GMT時間區的日期值,那麼必須利用最保守的可能轉換把此日期值轉換成GMT時間值。
19.4 HTTP實體和RFC 2045實體之間的區別
HTTP/1.1使用了許多Internet Mail(RFC 822 [9])和Multipurpose Internet Mail Extensions(MIME [7])裏定義的結構,去容許實體以多種表現形式和擴展機制去傳輸。然而,RFC2045討論郵件,而且HTTP有許多不一樣於RFC2045裏描述的特徵。這些不一樣被當心地挑選出來優化二進制鏈接的性能,爲了容許使用新的媒體類型有更大的靈活性,爲了使時間比較變得容易,和爲了認可一些早期HTTP服務器和客戶端的實效。
本附錄描述了HTTP協議不一樣於RFC 2045的特殊區域。在嚴格的MIME環境中的代理和網關應該意識到這些不一樣而且在必要的時候要提供合適地轉換。從MIME環境到HTTP的代理服務器和網關也須要意識到這些不一樣由於一些轉換多是須要的。
19.4.1 MIME版本(MIME-Version)
HTTP不是一個遵照MIME的協議。然而HTTP/1.1消息能夠(MAY)包含一個單獨的MIME-Version經常使用頭域用來指出什麼樣的MIME協議版本被用於去構造消息。利用MIME-Version頭域指明徹底遵循MIME協議的消息(在RFC2045[7])。代理/網關要保證徹底遵照MIME協議當把HTTP消息輸出到嚴格MIME環境的時候。
MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
在HTTP/1.1用的缺省值是MIME1.0版本。然而,HTTP/1.1消息的解析和語義是由本文檔而不是MIME規範定義的。
19.4.2轉換到規範化形式 (Conversion to Canoical Form)
RFC 2045 [7]須要一個Internet mail實體在被傳輸以前要被轉換成一個規範化的形式,這在RFC2049[48]裏第四章裏描述的。這篇文檔的3.7.1節描述了當用HTTP協議傳輸時容許使用的」text」子媒體類型的形式。RFC2046要求以類型爲「text」的內容要用CRLF表示爲換行符,以及在換行符外禁止使用CR或LF。
RFC 2046須要像在"text"類型的內容裏同樣,用CRLF表示行間隔符並禁止在行間隔符序列之外使用CR或者LF。HTTP容許CRLF,單個CR,和單個LF來表示一個換行符在一個文本內容消息中。
在可能的地方,從HTTP到嚴格MIME環境的代理或網關應該(SHOULD)把RFC2049裏描述的text媒體類型裏全部換行符轉換成RFC2049裏CRLF的規範形式。然而,注意這可能在Content-Encoding出現的時候,以及HTTP容許利用一些沒有利用13和10表明CR和LF的字符集時候都會變得複雜。
實現者應該注意轉換將會破壞任何應用於源內容(original content)的密碼校驗和,除非源內容已是規範化形式。所以,對任何在HTTP中使用校驗和的內容被建議要表示爲規範化形式。
19.4.3日期格式的轉換 (Conversion of Date Formate)
爲了簡化日期比較的過程,HTTP/1.1使用了一個限制的日期格式(3.3.1節)。其它協議的代理和網關應該保證任何消息裏出現的Date頭域應該遵循HTTP/1.1規定的格式,若是有必要須要重寫此日期。
19.4.4 Content-Encoding頭域介紹 (Introduction of Content-Encoding)
RFC 2045不包含任何等價於HTTP/1.1裏Content-Encoding頭域的概念。由於這個頭域做爲媒體類型(media type)的修飾,從HTTP協議到MIME遵照的協議的代理和網關在轉發消息以前必須既能改變Content-Type頭域的值,也能解碼實體主體(entity-body).。(一些爲Internet mail類型的Content-Type的實驗性的應用已經使用了一個媒體類型參數「; conversions=<content-coding>」去執行等價於Content-Encoding的功能。然而,此參數並非RFC2045的部分)
19.4.5沒有Content-Transfer-Encoding頭域
HTTP不使用RFC 2045裏的Content-Transfer-Encoding(CTE)頭域。從使用MIME協議到HTTP的代理和網關在把響應消息發送給HTTP客戶端以前必須刪除任何非等價(non-identity,譯註:identity編碼,表示沒有進行任何編碼)CTE("quoted-printable"或"base64")編碼。
從HTTP到MIME協議遵循的代理和網關要確保消息在那個協議安全傳輸上是用正確的格式和正確的編碼,「安全傳輸」是經過使用的協議的限制而被定義的。這樣一個代理或網關應該用合適的Content-Transfer-Encoding頭域來標記數據若是這樣作將提升安全傳輸的可能性。
19.4.6 Transfer-Encoding頭域的介紹
HTTP/1.1介紹了Transfer-Encoding頭域(14.41節)。代理/網關在轉發經由MIME協議的消息以前必須移除任何傳輸編碼。
一個解碼"chunked"傳輸代碼(3.6節)的程序能夠用代碼表示以下:
length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
19.4.7 MHTML和行長度限制
和MHTML實現共享代碼的HTTP實現須要瞭解MIME行長度限制。由於HTTP沒有這個限制,HTTP並不摺疊長行。用HTTP傳輸的MHTML消息遵照全部MHTML的規定,包括行長度的限制和摺疊,規範化等,由於HTTP傳輸全部消息主體(見3.7.2)而且不解析消息的內容和消息中包含任何MIME頭域。
19.5 其它特徵
RFC 1945和RFC 2068裏一些協議元素被一些已經存在的HTTP實現使用,可是這些協議元素對於大多數HTTP/1.1應用程序既不兼容也不正確。實現者被建議去了解這些特徵,可是不能依賴於它們的出現或不依賴於與其它HTTP/1.1應用程序的互操做性。這些特徵中的一些特徵描述了實驗性的特徵,以及還有一些特徵描述了沒有在基本HTTP/1.1規範裏被描述的實驗性部署特徵。
一些其它頭域,如Content-Dispositon和Title頭域,他們來自於SMTP和MIME協議,他們一樣常常被實現(見2076[37]).
19.5.1 Content-Disposition
Content-Disposition響應頭域被建議做爲一個這樣的用途,那就是若是用戶請求要使內容被保存爲一個文件,那麼此頭域被源服務器使用去建議的一個缺省的文件名。此用途來自於RFC1806[35]關於對Content-Disposition的定義。
content-disposition = "Content-Disposition" ":"
disposition-type *( ";" disposition-parm )
disposition-type = "attachment" | disp-extension-token
disposition-parm = filename-parm | disp-extension-parm
filename-parm = "filename" "=" quoted-string
disp-extension-token = token
disp-extension-parm = token "=" ( token | quoted-string )
一個例子是:
Content-Disposition: attachment; filename="fname.ext"
接收用戶的代理不該該(SHOULD NOT)關注任何在filename-parm參數中出現的文件路徑信息,這個參數被認爲在此次僅僅是應用於HTTP實現。文件名應該(SHOULD)只被看成一個終端組件。
若是此頭域用於一個Content-Type爲application/octet-stream響應裏,那麼含義就是用戶代理不該該展示響應,可是它應該直接進入一個‘保存響應爲…’對話框。
見15.5節關於Content-Disposition的的安全問題。
19.6 和之前版本的兼容
要求和之前的版本的兼容超出了協議規範的範圍。然而HTTP/1.1有意設計成很容易支持之前的版本。必須值得注意的是,在寫這份規範的時候,咱們但願商業的HTTP/1.1服務器去:
--接受HTTP/0.9,1.0和1.1請求的請求行(Request-Line)格式;
--理解HTTP/0.9,1.0或1.1格式中的任何有效請求;
--恰當地用客戶端使用的主要版原本響應。
而且咱們但願HTTP/1.1的客戶端:
--接受HTTP/1.0和1.1響應的狀態行(Status-Line)格式;
--懂得HTTP/0.9,1.0或1.1的格式的任何有效的響應。
對大多數HTTP/1.0的實現,每個鏈接要在請求以前被客戶端創建,而且在發送響應以後要被服務器關閉。一些實現了在RFC 2068 [33]的19.7.1節描述的持久鏈接的Keep-Alive版本。
19.6.1對HTTP/1.0的改變
這一部分總結HTTP/1.0和HTTP/1.1之間主要的區別。
19.6.1.1 對多主機web服務器和保留IP地址簡化的改變
客戶端和服務器必須支持Host請求頭域,而且若是Host請求頭域在HTTP/1.1請求裏缺乏,那麼服務器應該報告一個錯誤,而且服務器能接受一個絕對URIs(5.1.2節),對於這個要求是在此規範裏最重要的改變。上面的改變將容許互聯網,一旦舊的客戶端再也不經常使用時,去支持一個IP地址的多個web站點,這大大簡化了大型運算的web服務器,在那裏分配多個IP地址給一個主機(host)會產生很嚴重的問題。此互聯網照樣能恢復這樣一個IP地址,此IP地址做爲特殊目的被分配給被用於根級HTTPURLs的域名。給定web的增加速度,服務器的部署數量部,那麼全部HTTP實現(包括對已存HTTP/1.0應用程序)應該正確地知足下面這些需求:
--客戶端和服務器都必須(MUST)支持Host請求頭域。
--發送HTTP/1.1請求的客戶端必須(MUST)發送Host頭域。
--若是HTTP/1.1請求不包括Host請求頭域,服務器就必須(MUST)報告錯誤400(Bad Request)。
--服務器必須(MUST)接受絕對URIs(absolute URIs)。
19.6.2和HTTP/1.0持續鏈接的兼容
一些客戶端和服務器可能但願和一些對之前持續鏈接實現的HTTP/1.0客戶端和服務器兼容。HTTP/1.0持久鏈接須要顯示地協商,由於它們不是缺省的行爲。持久鏈接的HTTP/1.0實驗性的實現有錯誤,而且HTTP/1.1裏的新的功能被設計成去矯正這些問題。此問題是一些已經存在的1.0客戶端可能會發送Keep-Alive頭域給不理解鏈接的代理服務器,而後代理服務器會把此Keep-Alive轉發給下一個入流(inbound)服務器。因此HTTP/1.0客戶端必須禁止利用Keep-Alive當和代理會話的時候。
然而,和代理進行會話最重要是利用持久鏈接,因此那個禁止很顯然不能被接受。所以,咱們須要一些其它的機制去指明須要一個持久鏈接,而且它必須能安全的使用甚至當和忽略鏈接的老代理。持久鏈接缺省是爲HTTP/1.1消息的;爲了聲明非持久鏈接(見14.10節),咱們介紹一個新的關鍵字(Connection:close)。
持久鏈接的源HTTP/1.0的形式(the Connection: Keep-Alive and Keep-Alive 頭域)在RFC2068裏說明
19.6.3對RFC 2068的改變
這篇規範已經被仔細的審查來糾正關鍵字的用法和消除它們的歧義;RFC 2068在遵照RFC 2119 [34] 制定的協定方面有不少問題。
澄清哪一個錯誤代碼將會使入流服務器失靈(例如DNS失靈)。(10.5.5節)
CREATE有一個特色當一個資源第一次被建立的時候必須須要一個Etag。(10.2.2節)
Content-Base頭域今後規範裏刪除了:它沒法普遍的實現,而且在沒有健壯的擴展機制的狀況下,沒有簡單的,安全的方式去介紹它。而且,它以一種類似的而不是相同的方式在MHTML[45]裏被使用。
略…..
20 索引 (Index)
21 所有版權聲明
本篇文章來源於 中國協議分析網|www.cnpaf.net 原文連接:http://www.cnpaf.net/Class/HTTP/200811/23277.html