超文本傳輸協議HTTP/1.1

文章來源:

http://www.blogjava.net/sunchaojin/archive/2007/08/09/http.html

說明

   本文檔規定了互聯網社區的標準組協議,並需要討論和建議以便更加完善。請參考

“互聯網官方協議標準”(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(讀者:改爲HTTP/1.0)客戶端,除了實驗性的目的。

客戶端必須能準備去接受一個或多個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 = max0, 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 AuthenticatiionBasic 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緩存控制指令的目的在於防止無意的泄露或保留了敏感信息(比如存放在備份磁帶的信息)。緩 存控制指令應用於整個消息,並且可以在響應裏或在請求裏被髮送。如果在請求裏被髮送,一個緩存不能保存此請求或此請求響應的任何部分。如果在響應裏被髮 送,一個緩存不能保存此響應或引起此響應請求的任何部分。此緩存控制指令能應用於非共享緩存和共享緩存。“不能保存”在這個上下文裏(context,譯註:也可以叫背景)的意思是指緩存不能有意的把信息保存在非易失性存儲裏,而且必須盡力去刪除易失性存儲上的信息當它轉發完畢後。 no-store

即使當此指令在一個響應裏時,用戶也可能會顯示地在緩存系統之外保存這個響應(例如,利用一個“另存爲”對話框)的地方。歷史緩存(譯註:見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: [email protected]

頭域可以被用於記錄日誌和作爲識別無效或多餘請求的資源。他不應該用作不安全形式 的訪問保護。這個頭域的解釋是:請求是代表所指定的人執行的,此人應該承擔這個方法執行的責任。特別的,機器人代理程序應該包含這個頭域,這樣此人應該對 運行此機器人代理程序負責,並且應該能被聯繫上如果在接收端出現問題的話。

此頭域裏的網絡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 AuthenticationBasic 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.0SHTTP/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: [email protected]

   James Gettys

   World Wide Web Consortium

   MIT Laboratory for Computer Science

   545 Technology Square

   Cambridge, MA 02139, USA

   Fax: +1 (617) 258 8682

   EMail: [email protected]

   Jeffrey C. Mogul

   Western Research Laboratory

   Compaq Computer Corporation

   250 University Avenue

   Palo Alto, California, 94305, USA

   EMail: [email protected]

   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: [email protected]

   Larry Masinter

   Xerox Corporation

   3333 Coyote Hill Road

   Palo Alto, CA 94034, USA

   EMail: [email protected]

   Paul J. Leach

   Microsoft Corporation

   1 Microsoft Way

   Redmond, WA 98052, USA

   EMail: [email protected]

   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: [email protected]

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 全部版權聲明

 …..

發佈了16 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章