超文字傳輸協議-HTTP/1.1(修訂版)
超文字傳輸協議-HTTP/1.1(修訂版)
說明
本文件規定了網際網路社群的標準組協議,並需要討論和建議以便更加完善。請參考
“網際網路官方協議標準”(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應用程式的激增,這就迫切需要一個新的版本,以便能使兩個通訊程式能夠確定彼此的真實能力。
此規範定義的協議叫做“HTTP/1.1”,.這個協議與HTTP/1.0相比,此規範更為嚴格,以確保各個協議的特徵得到可靠實現。
實際的資訊系統除了簡單的獲取資訊之外,還要求更多的功能,包括查詢(search),終端更新(front-end update)和註解(annotation)。HTTP為請求提供可擴充方法集和訊息頭集[47]。HTTP是建立在統一資源識別符號(URI)[3]的約束上的,作為一個地址(URL)[4]或名稱(URN)[20],以指定被一個方法使用的資源。訊息以一種類似於網際網路郵件[9]訊息格式來傳輸的,網際網路訊息格式定義於多目的網際網路郵件擴充套件(MIME)[7]裡。
HTTP也是用於使用者代理(user agents)和其它網際網路系統的代理/閘道器之間通訊的通訊協議,這些網際網路系統可能由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)儲存其副本,為的是能響應後續請求。確定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協議是一種請求/響應型的協議。 客戶端給伺服器傳送請求的格式是一個請求方法(request method),URI,協議版本號,然後緊接著一個包含請求修飾符(modifiers),客戶端資訊,和可能的訊息主體的類MIME(MIME-like)訊息。伺服器對請求端傳送響應的格式是以一個狀態行(status line),其後跟隨一個包含伺服器資訊、實體元資訊和可能的實體主體內容的類MIME(MIME-like)的訊息。其中狀態行(status line)包含訊息的協議版本號和一個成功或錯誤碼。HTTP和MIME之間的關係如附錄19.4節所闡述。
大部分的HTTP通訊是由使用者代理(user agent)發起的,由應用於一個源伺服器資源的請求構成。最簡單的情形,這可以通過使用者代理(UA)和源伺服器(O)之間的單一連線(v)來實現。
請求鏈(Request chain)-------------------------------------- ----------à
使用者代理(UA)----------------單一連線(v)--------------源伺服器(O)
<----------------------------------------------------------響應鏈(response chain)
有可能在請求/響應鏈中出現一個或多箇中間者(intermediares),這是比較複雜的情形。常見的中間者(intermediares)有三種:代理(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的伺服器,與此同時C正在處理A的請求。
通訊中任何非隧道成員都可能會採用一個內部快取(internal cache)來處理請求。如果沿著鏈的成員有請求已快取的響應,請求/響應鏈就會大大縮短。下圖闡明瞭一個最終請求響應鏈,假定B擁有一個來自於O(通過C)的以前請求響應的快取副本,並且此請求的響應並未被UA或A快取。
請求鏈(request chain)---------->
UA-----v----------A-----v-----B-----C----O
<---------響應鏈 (response chain)
並不是所有的響應都能有效地快取,一些請求可能含有修飾符(modifiers),這些修飾符對快取動作有特殊的要求。HTTP對快取行為(behavior)和可快取響應(cacheable responses)的定義在第13章定義。
實際上,目前全球資訊網上有多種被實踐和部署的快取和代理的體系結構和配置。這些系統包括節省頻寬的快取代理(proxy cache)層次(hierarchies)系統,可以廣播(broadcast)或多播(multicast)快取資料的系統,通過CD-ROM釋出快取資料子集的機構,等等。HTTP系統(http system)會被應用於寬頻連線的企業區域網中的協作,並且可以被用於PDAs進行低耗無線斷續連線訪問。HTTP1.1的宗旨是為了支援各種各樣的已經部署的配置,同時引進一種協議結構,讓它滿足可以建立高可靠性的web應用程式,即使不能達到這種要求,也至少可以可靠的定位故障。
HTTP通訊通常發生在TCP/IP連線上。預設埠是TCP 80,不過其它埠也可以使用。但並不排除HTTP協議會在其它協議之上被實現。HTTP僅僅期望的是一個可靠的傳輸(譯註:HTTP一般建立在傳輸層協議之上);所以任何提供這種保證的協議都可以被使用;協議傳輸資料單元(transport data unit)與HTTP/1.1請求和響應的訊息結構之間的映象已經超出了本規範的範圍。
大部分HTTP/1.0的實現都是對每個請求/響應交換(exchange)產生一個新的連線。而HTTP/1.1中,一個連線可以用於一個或更多請求/響應交換,雖然連線可能會因為各種原因中斷(見第8.1節)。
2 符號習慣和一般語法
2.1 擴充的BNF(擴充的 巴科斯-諾爾正規化)
本文件規定的所有機制都用兩種方法描述:散文體(prose)和類似於RFC 822的擴充Backus-Naur Form(BNF)。要理解本規範,使用者需熟悉符號表示法。擴充BNF結構如下:
名字(name)=定義(definition)
名字(name)就是代表規則的名字,規則名裡不能包含“<”和“>”,通過等號把規則名和規則定義(definiation)分離開。空格只有在採用延續行縮排來指定跨度多於一行的規則定義的時候才有意義。某些基本規則(basic rules)使用大寫字母包含在規則定義裡, 如SP,LWS,HT,CRLF,DIGIT,ALPHA,等等。尖括號可以包含在規則定義裡,只要它們的存在有利於區分規則名的使用。
“字面文字”(“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”。
*規則
前面的字元“”表示重複。完整的形式是“
[規則]
方括號裡是任選元素;“[foo bar]”相當於“*1(foo bar)”。
N 規則
特殊的重複:“
規則
類似於“*”,結構“#”是用來定義一系列元素的。完整的形式是
(LWS element (LWS ","LWS element))
就可以表示為
1#element
無論在哪裡使用這個結構,空元素都是允許的,但是不計入元素出現的次數。換句話說 ,
“(element ), , (element) ”是允許的,但是僅僅視為兩個元素。因此,在至少需要一個元素的地方,必須存在至少一個非空元素。預設值是0和無窮大,這樣,“#element”允許任意零個或多個元素;“1# element”需要至少一個;“1#2element”允許一個或兩個元素。
註釋(comment)
用分號引導註釋。
隱含的*LWS
本規範所描述的語法是基於字(word-based)的。除非特別註明,線性空白(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”的域裡。在其他域裡,圓括號被視作域值的一部分。
comment (註釋)= "(" *(ctext | quoted-pair | comment )” )"
ctext = <除"(" 和 ")"以外的任意TEXT >
如果一個TEXT若被包含在雙引號裡,則當作一個字。
quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
qdtext = <any TEXT except <">>
斜劃線(""")可以被作為單字元的引用機制,但是必須要在quoted-string和comment構造之內。
quoted-pair = """ CHAR
3 協議引數
3.1 HTTP版本
HTTP使用一個“
HTTP訊息的版本在HTTP-Version域被指明,HTTP-Version域在訊息的第一行中。
HTTP-Version = "HTTP" "/" 1DIGIT "." 1DIGIT
注意major和minor數字必須被看成兩個獨立整數,每個整數都可以遞增,並且可以增大到大於一位數的整數,如HTTP/2.4比HTTP/2.13低,而HTTP/2.4又比HTTP/12.3低。前導0必須被接收者忽略並且不能被髮送者傳送。
一個應用程式如果傳送或響應訊息裡的包含HTTP-Version為“HTTP/1.1”的訊息,那麼此應用程式必須至少條件遵循此協議規範。最少條件遵循此規範的應用程式應該把“HTTP/1.1”包含在他們的訊息的HTTP-Version裡,並且對任何不相容HTTP/1.0的訊息也必須這麼做。關於何時傳送特定的HTTP-Version值的細節,參見RFC2145[36]。
應用程式的HTTP版本是應用程式最少條件遵循的最高HTTP版本。
當代理或閘道器應用程式轉發(forwarding)訊息的協議版本不同於代理或閘道器應用程式本身協議版本的時候,代理(proxy)和閘道器(gateway)應用程式就要小心。因為訊息裡協議版本說明了傳送者處理協議的能力,所以一個代理/閘道器千萬不要傳送一個高於該代理/閘道器應用程式協議版本的訊息。如果代理或閘道器接收了一個更高版本的訊息,它必須要麼使協議的版本降低,要麼以一個錯誤響應,或者要麼切換到隧道行為(tunnel behavior)。
自從RFC 2068[33]釋出後,由於存在與HTTP/1.0代理(proxy)的互操作問題,所以快取代理(caching proxies)必須能提升請求的版本到他們能支援的程度,但閘道器(gateway)可以這麼做也可以不這麼做,而隧道(tunnels)卻不能這麼做。代理(Proxy)/閘道器(gateway)的響應(Response)必須和請求(request)的主版本(major version)號保持一致。
注意:HTTP版本間的轉換可能會對訊息頭域(header fields)在版本里有或沒有而進行改變。
3.2 通用資源識別符號(URI)
URIs有許多名字已為人所知:WWW地址,通用文件識別符號,通用資源識別符號[3],以及後來的統一資源定位器(URL)[4]和統一資源名稱(URN)[20]。就HTTP而言,通用資源識別符號(URI)只是簡單的格式化字串---通過名稱,位置,或其它特徵---識別一個資源。
3.2.1一般語法
根據使用的背景,HTTP裡的URIs可以表示成絕對(absoulute)形式或相對形式(相對URI基於根URI[11])。兩種形式的區別是根據這樣的事實:絕對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,並且應該能夠處理無限長度的URIs,這種無效長度的URL可能會在客戶端以基於GET方式的請求時產生。如果伺服器不能處理太長的URI的時候,伺服器應該返回414狀態碼(此狀態碼代表Request-URI太長)。
注:伺服器在依賴大於255位元組的URI時應謹慎,因為一些舊的客戶或代理實現可能不支援這些長度。
3.2.2 HTTP URL
在HTTP協議裡,http模式(http scheme)被用於定位網路資源(resourse)的位置。本節定義了http URLs這種特定模式(scheme)的語法和語義。
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
如果埠為空或未給出,就假定為80。它的語義即:已識別的資源存放於正在監聽tcp連線的那個埠的伺服器上,並且請求資源的的Request-UR為絕對路徑(5.1.2節)。無論什麼可能的時候,URL裡使用IP地址都是應該避免的(參看RFC 1900 [24])。如果絕對地址(abs_path)沒有出現在URL裡,那麼應該給出"/"。如果代理(proxy)收到一個主機(host)名,但是這個主機名不是全稱域名(fully quanlified domain name),則代理應該把它的域名加到主機名上。如果代理(proxy)接收了一個全稱域名,代理不能改變主機(host)名稱。
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-date的地方。
注:日期值的接收者被鼓勵能可靠地接收來自於非HTTP應用程式傳送的的日期值,例如有時可以通過代理(proxy)/閘道器(gateway)向SMTP或NNTP獲取或提交訊息。
所有的HTTP日期/時間都必須以格林威治時間(GMT)表示。對HTTP而言,GMT完全等同於UTC(世界協調時間)。前兩種日期/時間格式裡包含“GMT”,它是時區的三個字面的簡寫,並且當讀到一個asctime格式時必須先被假定是GMT時間。HTTP日期(HTTP-date)區分大小寫,不能在此語法中除SP之外包含一個多餘的LWS。
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對日期/時間格式的要求僅僅應用在協議流的使用。客戶和伺服器不必把這種格式應用於使用者呈現(user presentation),請求記錄日誌,等等。.
3.3.2 Delta Seconds(秒間隔)
一些HTTP頭域(header field)允許時間值以秒為單位,以十進位制整數表示,此值代表訊息接收後的時間。
delta-seconds = 1*DIGIT
3.4 字符集 (Character Sets)
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頭域裡包含一個字符集引數,即使字符集是ISO-8859-1的也應該指明,這樣就不會讓接收者產生混淆。
不幸的是,一些舊的HTTP/1.0客戶端不能處理在Content-Type頭域裡明確指定的字符集引數。HTTP/1.1接收端必須要認真對待發送者提供的字符集;並且當用戶代理(user agent,譯註:如瀏覽器)開始呈現一個文件時,雖然使用者代理可以猜測文件的字符集,但如果content-type頭域裡提供了字符集,並且使用者代理也支援這種字符集的顯示,不管使用者代理是否願意,它必須要利用這種字符集。參見3.7.1節。
3.5 內容編碼(Content Codings)
內容編碼(content coding)的值表示一種曾經或能被應用於一個實體的編碼轉換(encoding transformation)。內容編碼主要用於文件的壓縮或其它有效的變換,但這種變換必須不能丟失文件的媒體型別的特性,並且不能丟失文件的資訊(譯註:就像有失真壓縮和無失真壓縮,前者不會丟失資訊,後者會丟失資訊)。實體經常被編碼後儲存,然後傳送出去,並且在接收端被解碼。
content-coding = token
所有內容編碼(content-coding)的值是不區分大小寫的。HTTP/1.1在接受譯碼 (Accept-Encoding,14.3節)和內容譯碼(Content-Encoding)(14.11節)頭域裡使用內容編碼(content-coding)的值。儘管該值描述了內容編碼,更重要的是它指出了一種解碼機制,利用這種機制對實體的編碼進行解碼。
網路分配數字權威( (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 ,譯註: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
所有傳輸編碼的值是大小寫不敏感。傳輸編碼的值在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,MIME [7])的值相似,它被定義能夠實現在7位傳輸服務上保證二進位制資料的安全傳輸。不過,傳輸編碼與內容傳輸譯碼(Content-Transfer-Encoding)對純8位傳輸協議有不同的側重點。在HTTP中,訊息主體存在不安全的特性是因為有時候很難確定訊息主體的長度(7.2.2節)和在共享的傳輸上加密資料。
網路分配數字權威(IANA)擔任註冊傳輸編碼的值標記(token)的角色。起初,註冊包含如下標記:"塊"(3.6.1節),"身份"(3.6.2節),"gzip"(3.5節),"壓縮"(3.5節),和"縮小"(3.5節).
新的傳輸編碼的值標記應該註冊,這同新的內容編碼的值標記也需要註冊一樣。.
如果接收端接收到一個經過傳輸編碼編碼過的實體主體(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,在14.40節闡述)來指明哪些頭域被包含在塊傳輸編碼的尾部(trailer) (見14.40節)
如果伺服器要使用塊傳輸編碼進行響應,除非以下至少一條為真時它才能包含尾部(trailer):
a)如果此響應的對應請求包括一個TE頭域,並且利用 “trailers”指明瞭塊傳輸編碼響應的尾部是可以接受的(TE頭域在14.39節中描述;或者
b)如果是源伺服器進行響應,響應裡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)以一種 屬性/值(attribute/value)形式(如3.6節定義)跟隨 型別/子型別(type/subtype)。
型別(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訊息控制結構(如頭域和多邊界體(multipart boundaries))裡,一個純粹的CR或LF都不能代替CRLF的作用。
如果一個實體主體(entity-body)用內容編碼(content-coding)進行編碼,原始資料在被編碼前必須是一種以上定義的媒體型別格式。.
"charset"引數(parameter)被應用於一些媒體型別,來定義資料的字符集(見3.4節)。當傳送端沒有指明charset引數(parameter)時,“text”型別的子媒體型別(subtype)被接收端接收後會被認為是預設的ISO-8859-1字符集。非“ISO-8859-1”字符集和它的子類(subsets)的資料必須被指示恰當的字符集。3.4.1節描述了相容性問題。
3.7.2多部分型別(Multipart type)
MIME提供了一系列“多部分”(multipart)型別---在單個訊息主體內包裝一個或多個實體。所有的多部分型別共享一個公共的語法(這在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使用者代理一樣或者相似的行為,這依賴於接收何種多部分型別。一個多部分型別訊息的每一個體部分(body-part)裡的MIME頭域對於HTTP除了MIME語意並沒有太大意義。
通常, 一個HTTP使用者代理應該遵循與一個MIME使用者代理相同或相似的行為。如果一個應用程式收到一個不能識別的多部分子型別,這個應用程式必須將它視為"multipart/mixed"。
注:"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-Encoding)指明的傳輸編碼(transfer-coding)應用於實體主體(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節)出現,並且它的域值是非”“dentity”傳輸編碼值,那麼傳輸長度(transfer-length)被“塊”(chunked)傳輸編碼定義,除非訊息因為通過關閉連線而結束。
3。如果出現Content-Length頭域(屬於實體頭域)(見14.13節),那麼它的十進位制值(以位元組表示)即代表實體主體長度(entity-length,譯註:實體長度其實就是實體主體的長度,以後把entity-length翻譯成實體主體的長度)又代表傳輸長度(transfer-length)。Content-Length頭域不能包含在訊息中,如果實體主體長度(entity-length)和傳輸長度(transfer-length)兩者不相等(也就是說,出現Transfer-Encodind頭域)。如果一個訊息即存在傳輸譯碼(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使用者代理(user agents)當接收了一個無效的長度時必須能通知使用者。
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和協議版本(HTTP-Version),最後以CRLF結束。元素是以SP字元分隔。除了最後的CRLF,CR或LF是不被允許的。
Request-Line =Method SP Request-URL SP HTTP-Version CRLF
5.1.1方法 (Method)
方法標記(token)指明瞭在被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 * HTTP/1.1
當向代理(proxy)提交請求時,絕對URI(absoluteRUI)格式是不可缺少的。代理(proxy)可能會被要求再次轉發請求或者從一個有效的快取(cache)裡構造響應去響應請求。注意:代理可能轉發請求給另一個代理或直接給被absoluteURI指定的源伺服器。為了避免迴圈請求,代理(proxy)必須能識別所有的伺服器名字,包括任何別名,本地的變化值,數字IP地址。一個請求行(Request-Line)的例子如下:
GET http://www.w3.org/pub/www/TheProject.html HTTP/1.1
為了未來HTTP版本的所有請求能遷移到absoluteURI地址,所有基於HTTP/1.1的伺服器必須接受絕對absoluteURI形式的請求,即使HTTP/1.1客戶端只為代理產生絕對absoluteURI請求。
authority格式只被用於CONNECT方法(9.9節).
Request-URI大多數情況是被用於指定一個源伺服器或閘道器(gateway)上的資源。這種情況下,URI的絕對路徑(abs_path,見3.2.1節)作為Request-URI被傳輸,並且URI網路位置(authority)必須在Host頭域裡指出。例如:客戶希望直接從源伺服器獲取資源,這種情況下,它可能會建立一個TCP連線,此連線是特定於主機“www.w3.org”的80埠的,這時會發送下面行:
GET /pub/WWW/TheProject.html HTTP/1.1
Host:www.w3.org
接下來是請求的其他部分。注意絕對路徑(absolute path)不能是空的;如果在原始URI裡沒有出現絕對路徑,必須給出"/"(伺服器的根)。
Request-URI是以3.2.1節裡指定的格式傳輸。如果Request-URI用"%HEX HEX"[42]編碼,源伺服器為了解析請求必須能對它進行解碼。伺服器接收到一個無效的Request-URI時必須以一個合適的狀態碼響應。
透明代理(proxy)不能重寫接收到的Request-URI裡的“abs_path”部分,當它轉發此請求到下一個內向伺服器(inbound server,見1.3術語)時,但除了上面說的把一個空的abs_path用一個”/”代替之外。
注:不重寫的規則是為了防止代理(proxy)改變請求的原意,因為存在源伺服器利用非保留(non-reserved)的URI字元為相反的目的 。實現者應該知道某些低於HTTP/1.1版本的代理(proxy)會重寫Request-URI。
5.2請求資源的識別 (The Resource Identified by a Request)
請求資源的精確定位是由請求裡的Request-URI和Host頭域決定的。
如果源伺服器不允許資源根據請求的不同主機來區分時,那麼它可以會忽略Host頭域的值,當它決定通過HTTP/1.1請求來識別資源的時候。(在HTTP/1.1裡關於對Host的支援在19.6.1.1節描述了其他的要求)。
一個源伺服器如果必須基於請求主機來區分資源(這是因為存在虛擬主機(virtual hosts)和虛擬主機名(vanity host names)),那麼,對HTTP/1.1請求,它必須遵循下面的規則去決定請求的資源:
1. 如果Request-URI是絕對地址(absoluteURI),那麼主機(host)是Request-URI的一部分。任何出現在請求裡Host頭域的值應當被忽略。
2. 假如Request-URI不是絕對地址(absoluteURI),並且請求包括一個Host頭域,則主機(host)由該Host頭域的值決定.
3. 假如由規則1或規則2定義的主機(host)對伺服器來說是一個無效的主機(host),則應當以一個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),由協議版本以及數字狀態碼和相關的文字短語組成,各部分間用空格符隔開,除了最後的CRLF序列,中間不允許有CR或LF。
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
6.1.1狀態碼與原因短語 (Status Code and Reason Phrase)
Status-Code元素是一個試圖理解和滿足請求的三位數字整數碼,這些碼的完整定義在第十章。原因短語(Reason-Phrase)是為了給出關於狀態碼的簡單的文字描述。狀態碼用於控制,而原因短語(Reason-Phrase)是讓使用者便於閱讀。客戶端不需要檢查和顯示原因短語。
狀態碼的第一位數字定義響應類別。後兩位數字沒有任何分類角色。第一位數字有五種值:
-1xx :報告的 -請求被接收到,繼續處理
-2xx :成功 - 被成功地接收(received),理解(understood),接受(accepted)的動作 。
-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]。 HTTP/1.1(RFC2068)實現的實踐過程和度量展現了一個滿意的結果。對其他方法也有了初步探究,如T/TCP [27]。
HTTP持久連線有著諸多的優點:
--- 通過建立與關閉較少的TCP連線,不僅節省了路由器與主機(客戶端,伺服器,代理,閘道器,隧道或快取)的CPU時間,還節省了主機用於TCP協議控制塊(TCP protocol control blocks)的記憶體。
--- HTTP請求和響應能在連線上進行管線請求方式。 管線請求方式能允許客戶端執行多次請求而不用等待每一個請求的響應(譯註:即客戶端可以傳送請求而不用等待以前的請求的響應到來後再發請求),並且此時只有一個TCP連線被使用,從而提高了效率,減少了時間。
--- 網路阻塞會被減少,這是由於減少了因TCP連線產生的包的數量並且也由於允許TCP有充分的時間去決定網路阻塞的狀態。
--- 因為無須在建立TCP連線時的握手上耗費時間,而使後續請求的等待時間減少。
---HTTP改進的越來越優雅,因為報告錯誤不需要關閉tcp連線的代價。將來的HTTP版本客戶端可以樂觀的嘗試利用一個新特性,但是如果和老伺服器通訊時錯誤被報告,那麼就要用舊的語義進行重新嘗試。
HTTP實現應該實現持久連線。
8.1.2總體操作
HTTP/1.1 與早期HTTP 版本的一個顯著區別在於持久連線是HTTP/1.1的預設方式。也就是說,除非另有指定,客戶端總應當假定伺服器會保持持久連線,即便在收到伺服器的出錯響應時也應如此。
持久連線提供了一種可以由客戶端或伺服器通知終止TCP連線的機制。利用Connection頭域(14。10節)可以產生終止連線訊號。一旦出現了終止連線的訊號,客戶端便不可再向此連線提出任何新請求。
8.1.2.1 協商(Negotiation)
除非請求裡Connection頭域中包含“close”連線標記(connection-token),HTTP/1.1伺服器總可以認為HTTP/1.1 客戶端想要維持持久連線(persistent connection)。如果伺服器想在發出響應後立即關閉連線,它應當傳送一個含“close”的Connection頭域。
一個HTTP/1.1客戶端可能期望連線一直保持開著,但這必須是基於伺服器響應裡是否包含一個Connection頭域並且此頭域裡是否包含“close”。如果客戶端不想再繼續維持連線來發送更多請求,那麼它應傳送一個值為“close”的Connection頭域。
如果客戶端或伺服器中的任一方在Connection頭域裡包含“close”,那麼那個請求就成為這個連線的最後一個請求。
客戶端和伺服器不應認為持久連線是低於1.1的HTTP版本所擁有的,除非它被顯式地指明。19.6.2節指出了跟HTTP/1.1客戶端相容的更多資訊。
8.1.2.2 管線(pilelining)
支援持久連線(persistent conncetion)的客戶端可以以管線的方式傳送請求(即無須等待響應而傳送多個請求)。伺服器必須按接收請求的順序傳送響應。
假定以持久連線方式進行連線,並且假定在連線建立後進行管線方式請求的客戶端應該準備去重新嘗試連線如果首次管線請求方式嘗試失敗。如果客戶端重新去嘗試連線,那麼,只有在客戶端知道連線是持久連線之後,客戶端才能進行管線傳送請求。如果伺服器在響應所有對應的請求之前關閉了連線,客戶端必須準備去重新發送請求。
客戶端不應該利用非等冪的方法或者非等冪的方法序列(見9.1.2節)進行管線方式的請求。否則一個過早的傳輸層連線的終止可能會導致不確定的結果。希望傳送非等冪方法請求的客戶端只有接收了上次它發出請求的響應後才能再次傳送請求給伺服器。
8.1.3代理 (Proxy Servers)
代理是非常重要的,因為代理正確地實現了Connection頭域的屬性,這在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節),可以用長度為零的塊和空尾部(trailer)來提前標記報文結束。若訊息主體之前有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(繼續)狀態碼時。因此,當一個客戶端傳送Expect請求頭域給一個源伺服器(可能通過代理),此伺服器也沒有以100(繼續)狀態碼響應,那麼客戶端不應該在傳送請求訊息的主體前無限等待。
HTTP/1.1源伺服器的要求:
--- 當接收一個包含值為“100-contitue”的Expect請求頭域的請求時,源伺服器必須或者以100(繼續)狀態碼響應從而繼續從輸入流裡接收資料,或者以一個最終的狀態碼響應。源伺服器不能在傳送100(繼續)狀態碼響應之前接收請求主體。如果伺服器以一個終結狀態碼響應後,它可能會關閉傳輸層連線或者它也可能會繼續接收或遺棄剩餘的請求。但是既然它返回了一個終結狀態碼的響應,它就不能再去執行那個請求的方法(如: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(繼續)響應的源伺服器必須最終能傳送一個終結狀態響應,,除非源伺服器過早切斷了傳輸層連線。
--- 若源伺服器接收到不含值為“100-contitue”的Expect請求頭域的請求,但該請求含有請求訊息主體,而伺服器在從傳輸層連線上接收整個請求訊息主體前返回一個終結狀態響應,那麼此源伺服器不能關閉傳輸層連線直到它接收了整個請求或者直到客戶端關閉了此連線。否則客戶端可能不會信任接收此響應訊息。然而,這一要求不應該被解釋為防止伺服器免受拒絕服務攻擊,或者防止伺服器被客戶端攻擊。
對HTTP/1.1代理的要求:
--- 若代理接到一個請求,此請求包含值為“100-continue”的Expect請求頭域,並且代理可能不能確定下一站伺服器是否遵循HTTP/1.1或更高版協議,那麼它必須轉發此請求時包含此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常用方法的定義如下。雖然方法可以被展開,但新加的方法不能被認為與擴充套件客戶端和伺服器共享同樣的語義。
Host請求頭域(見14.23節)必須能在所有的HTTP/1.1請求裡出現。
9.1 安全和等冪(Idempotent)方法
9.1.1安全方法(Safe Methods)
實現者應當知道軟體是代表使用者在網際網路上進行互動,並且應該小心地允許使用者知道任何它們可能採取的動作(action),這些動作可能給他們自己或他人帶來無法預料的結果。
GET和HEAD方法只是執行沒有影響的動作那就是獲取資源。這些方法應該被考慮是“安全”的。可以讓使用者代理呼叫的其它方法,如: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涉及到一個數據生成過程,那麼這個過程生成的資料應該被作為實體在響應中返回而不是過程的源文字,除非源文字恰好是過程的輸出。
如果請求訊息包含 If-Modified-Since,,If-Unmodified-Since,If-Match,If-None-Match或者 If-Range頭域,GET的語義將變成“條件(conditionall) GET”。一個條件GET方法會請求滿足條件頭域的實體。條件GET方法的目的是為了減少不必要的網路使用,這通過允許利用快取裡仍然保鮮的實體而不用多次請求或傳輸客戶端已經擁有的實體來實現的。.
如果請求方法包含一個Range頭域,那麼GET方法就變成“部分Get”(partial 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(見其他)響應能被使用者代理利用去獲得可快取的響應。
POST 請求必須遵循8.2節裡指明的訊息傳送的要求。
參見15.1.3節關於安全性的考慮.
9.6 PUT
PUT方法請求伺服器去把請求裡的實體儲存在請求URI(Request-URI)標識下。如果請求URI(Request-URI)指定的的資源已經在源伺服器上存在,那麼此請求裡的實體應該被當作是源伺服器關於此URI所指定資源實體的最新修改版本。如果請求URI(Request-URI)指定的資源不存在,並且此URI被使用者代理定義為一個新資源,那麼源伺服器就應該根據請求裡的實體建立一個此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意指什麼,並且伺服器不能把此請求應用於其它資源(resource)。如果伺服器期望請求被應用於一個不同的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”的頭域。此方法的響應不能被快取。
9.9 CONNECT(連線)
HTTP1.1協議規範保留了CONNECT方法,此方法是為了能用於能動態切換到隧道的代理((如 SSL tunneling [44]).)。
10.狀態碼定義
每一個狀態碼在下面定義,包括此狀態碼依賴於方法的描述和響應裡需要的任何元資訊的描述。
10.1 通知的 1xx
這類狀態程式碼指明瞭一個臨時性的響應,包含一個Status-Line和可選的頭域,並且被一個空行結束(譯註:空行就是CRLF)。這類狀態碼響應沒有必須的頭域。因為HTTP/1.0沒有定義任何1xx狀態碼,所以伺服器不能傳送一個1xx響應給一個HTTP/1.1客戶端,除了實驗性的目的。
客戶端必須能在一個常規響應之前接受一個或多個1xx狀態,即使客戶端不期望100(繼續)狀態響應。不被客戶端期望的1xx狀態響應可能會被使用者代理忽略。
代理必須能轉發1xx響應,除非代理和它的客戶端的連線關閉了,或者除非代理自己響應請求併產生1xx響應。(例如:如果代理添加了“Expect:100-continue”頭域當轉發請求時,那麼它不必轉發相應的100(繼續)狀態響應。)
10.1.1 100 繼續 (Continue)
100狀態響應告訴客戶端應該繼續請求。100響應是個中間響應,它被用於通知客戶端請求的初始部分已經被接收了並且此請求還沒有被伺服器丟棄。客戶端應該繼續傳送請求的剩餘部分,或者,如果此請求已經完成了客戶端會忽略此100響應。伺服器在接收請求後必須傳送一個終結響應。見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)
此狀態碼響應指明響應裡實體頭域元資訊不能從源伺服器獲而是從本地的或第三方響應副本里收集的。這些元資訊可能是源伺服器版本的子集或超集。如,包含一個存在本地的資源註釋資訊就可以產生一個源伺服器能理解的元資訊的超集。利用此響應狀態碼不是必須但是比200(Ok)響應卻更加合適。
10.2.5 204 無內容 (No Content)
伺服器已經滿足了請求但並沒有返回一個實體而是返回更新的元資訊。此響應可能包含新的或更新的元資訊以實體頭域的形式,這些元資訊應該相關於請求變數。
利用此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)資訊(見13章)被提供以便使用者(或使用者代理)能選擇一個更適的表現形式並重定向它的請求到那個表現形式的位置。
除非是HEAD請求,否則300狀態響應應該包含一個實體,此實體包含一個資源特性和位置列表,從這個列表裡使用者或使用者代理能選擇最合適的資源的表現形式。實體格式被Content-Type頭域裡的媒體型別指定。使用者代理選擇最合適的表現形式的行為可能會被自動執行,這依賴於實體格式和自己的能力。然而,此規範並沒有定義自動執行行為的標準。
如果伺服器能確定更好的表現形式,它應該為此表現形式在Location頭域裡包含一個特定的URI來指明此表現形式的位置;使用者代理可能會利用此Location頭域自動重定向。300狀態響應是可快取的除非被特別指明。
10.3.2 301 永久移動 (Moved Permanently)
請求資源被賦於一個新的永久的URI,並且任何將來對此資源的引用都會利用此301狀態響應返回的URI。具有連結編輯能力的客戶端應該能自動把請求URI的引用轉到到伺服器返回的新的引用下。此響應是能快取的除非另外宣告。
新的永久URI應該在響應中被Location頭域給定。除非請求方法是HEAD,否則此響應應該包含一個超文字提示和一個指向新URI的超文字連結。
如果客戶端接收了一個來自非GET或HEAD請求方法的301響應,那麼使用者代理不能自動重定向請求除非它能被使用者確認,因為這可能會改變請求提交的條件。
注意:當客戶端在接收了301狀態碼響應後,會重定向POST請求,一些已經存在的HTTP/1.0使用者代理會錯誤的把此請求變成一個GET請求。
10.3.3 302 發現(Found)
請求的資源暫時地存放在一個不同的URI下。因為重定向的地址可能有時會被改變,客戶端應該繼續為將來的請求利用請求URI(Request-URI)。302響應是隻有在Cache-Control或Expires頭域指明的情況下才能被快取。
臨時的URI應該在Location頭域裡指定。除非請求方法是HEAD,否則此響應應該包含一個超文字提示和一個指向新URI的超文字連結。
如果客戶端接收了一個來自非GET或HEAD請求方法的302響應,那麼使用者代理不能自動重定向請求除非它能被使用者確認,因為這可能會改變請求提交的條件。
注意:RFC1945和RFC2068指定客戶端不能在重定向請求的時候改變請求方法。然而,大多數使用者代理實現會把302響應看成是303響應,從而根據Location頭域值的URI執行GET請求,不管原始的請求方法是什麼。303和307狀態響應的目的是為使伺服器明白客戶端期望哪種型別的重定向。
10.3.4 303 見其他(See Other)
請求的響應被放在一個不同的URI下,並且應該用GET方法獲得那個資源。此方法的存在主要是讓POST呼叫指令碼的輸出能使使用者代理重定向到一個選擇的資源。新的URI並不是原始請求資源的代替引用。303響應不能被快取,但是再次重定向請求的響應應該被快取。
不同的URI應該在Location頭域裡指定。除非請求方法是HEAD,除非請求方法是HEAD,否則此響應應該包含一個超文字提示和一個指向新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響應裡出現的話。
-
Expire,Cache-Control,和/或者Vary頭域,如果這些頭域值與以前同一變數響應中的不一致。
如果條件GET請求使用強快取驗證(見13.3.3節)時,那麼響應不應包含其它實體頭域。當條件GET使用弱快取驗證時,那麼響應必須不能包含其它實體頭域;這能防止快取的實體主體與更新的頭域之間的不一致性。
如果一個304響應指示一個沒有被快取的實體,那麼此快取必須不用理會此響應,並且以無條件請求重試請求。
如果快取利用一個接收到的304響應去更新一個快取項,那麼快取必須用此響應響應裡任何最新的域值更新快取項。
10.3.6 305 使用代理 (Use 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頭域裡給定。否則此響應應該包含一個超文字提示和一個指向新URI的超文字連結,因為許多HTTP/1.1以前的使用者代理不能理解307狀態響應。因此,此提示應該包含使用者在新的URI上重試原始請求的必需資訊。
如果307狀態響應.對應的請求的方法不是GET或HEAD,那麼使用者代理不能自動重定向此請求除非它能被使用者確認,因為因為這可能會改變請求提交的條件。
10.4 客戶端錯誤 4xx
狀態碼4xx類的目的是為了指明客戶端出現錯誤的情況。除了當響應一個HEAD請求,伺服器應該包含一個實體,此實體包含一個此錯誤請求的解釋。此狀態碼對所有請求方法都是適合的。使用者代理應該展示任何響應裡包含的實體給使用者。
如果客戶端傳送資料,利用TCP的伺服器實現應該小心地確保客戶端確認包含了響應的包(packets)的接收,在伺服器關閉此輸入連線前。如果在關閉連線後,客戶端繼續傳送資料給伺服器,那麼伺服器的TCP棧將傳送一個重置包給客戶端,這能擦除客戶端非確認的輸入緩衝(input buffers)在這些緩衝被HTTP應用程式讀和解析之前。
10.4.1 400 壞請求(Bad Request)
請求不能被伺服器理解,由於錯誤的語法。客戶端不應該在沒有改變請求的情況下重試請求。
10.4.2 401 未授權的 (Unauthorized)
伺服器需要對請求進行使用者認證。響應必須包含一個WWW-Authenticate頭域(見14.47),此頭域包含一個適用於請求資源的授權的激勵(challenge)。客戶端會以一個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伺服器被准許根據請求裡的接受頭域會返回不可接受的響應。在一些情況下,這可能更傾向於傳送一個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請求的時候。例如,如果版本被使用並且被PUT的實體包含資源的改變,而這些改變會和以前的(第三方的)請求的相沖突,那麼伺服器應該使用409響應去指明它不能完成此請求。在這種情況下,此響應的實體可能包含這兩個版本的差異點,響應的實體格式以Content-Type頭域指定。
10.4.11 410 不存在(gone)
請求資源在源伺服器上不再可得並且也沒有轉發地址可用。此條件被認為是永久的。具有連結編輯能力的客戶端應該在使用者確認後刪除請求URI的引用。如果伺服器不知道或不容易去確定條件是否是永久的,那麼此404(沒有發現)狀態響應將被代替利用。響應是可快取的,除非另外申明。
410響應主要的目的是為了web維護任務,這通過告訴接收者資源已經不可得了並且告訴接收者伺服器擁有者已經把那個資源的遠端連線給移除了。對有時間限制的,推銷性的服務,和對不再繼續工作在伺服器站點人員的資源,這個事件(410響應)是非常普遍的。它不需要把所有長久不可得的資源標記為“gone”或者保持任意長時間—這需要伺服器擁有者自己的判斷
10.4.12 411 長度必需 (Length Required)
伺服器拒絕接受請求裡沒有包含Content-Length頭域的請求。客戶端可以重試此請求如果它添加了一個有效的Content-Length頭域,此頭域值指定了請求訊息裡訊息主體的長度。
10.4.13 412 先決條件失敗 (Precondition Failed)
在一個或多個請求頭域裡指定的先決條件當在伺服器上測試為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 期望失敗(Expectation Failed)
Expect請求頭域裡指定的希望不能被伺服器滿足,或者,如果伺服器是代理,那麼能確定請求不能被下一站(next-hop)伺服器滿足。
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)
此響應說明:作為閘道器或代理的伺服器從上游(upstream)伺服器接收了一個無效的響應。
10.5.4 503 服務不能獲得(Service Unavailable)
由於伺服器暫時地過載或維護,伺服器不能處理請求。這就是說這是暫時條件,此條件將會在一些延時後被減輕。延遲的長度可以在Retry-After頭域裡指定。如果沒有Retry-After被給,那麼客戶端應該處理此響應就像它處理500響應一樣。
注意:503狀態碼的存在並不是意指伺服器當產生過載時必須利用它。一些伺服器可能希望拒絕此連線。
10.5.5 504 閘道器超時(Gateway Timeout)
作為閘道器或代理的伺服器在不能及時地接收一個從URI指定的上游(upstream)伺服器(例如:HTTP,FTP,LDAP伺服器)或者其他的輔助性伺服器(例如:DNS伺服器)的響應。
注意:當DNS查詢超時時,一些部署的代理將會返回400或500響應。
10.5.6 505 HTTP版本不支援 (HTTP version Not Supported)
伺服器不能支援,或拒絕支援此HTTP協議版本訊息。505響應指明伺服器不能或不願意完成這樣的請求,這在3.1中描述了。此響應應該包含一個實體,此實體描述了為什麼此協議版本不被支援和其他能被伺服器支援的協議版本。
11.訪問認證(Access Authentication)
HTTP提供一些可選的激勵響應(challenge-response)認證(authentication)機制,這些機制能被用於伺服器去激勵客戶端請求,使客戶端提供認證資訊。常用訪問認證框架,還有“basic”和“digest”認證規範,都在“HTTP Authentication:basic and Digest Access Authentication”[43]規範裡指定。HTTP/1.1規範採用了“激勵(chanllenge)”和“證書(credentials)”的定義。
12.內容協商 (Content Negotiation)
大多數響應包含一個實體,此實體包含人類使用者能理解的資訊。通常,希望響應能提供給使用者相應請求的“最可得”(best available)的實體。對伺服器和快取來說,不幸的是,並不是所有的使用者都對這個“最可得”的實體有相同的喜好,並且並不是所有的使用者代理(如web瀏覽器)都能一致的呈現這些實體。所以,HTTP提供了幾個“內容協商”的機制 — 當有多個可得的表現形式的時候,對給定響應去選擇最好的表現形式的過程。
注意:沒有稱做“格式協商”(譯註:“格式”指的是“媒體型別”)的,這是因為選擇的表現形式可能會有相同的媒體型別,但卻根據其它能力(capabilities),例如一種不同的語言。
任何包含一個實體主體的響應應該由受協商來決定,包括錯誤響應。
在HTTP中,有兩種型別的內容協商:伺服器驅動協商和代理驅動協商。這兩種型別的協商具有正交性,因此能被單獨使用或聯合使用。一個聯合使用的協商會被叫做透明協商,這發生在當快取利用源伺服器提供的代理驅動協商資訊為後續請求提供伺服器驅動協商的時候。
12.1 伺服器驅動協商(Server-driven Negotiation)
如果響應的最好的表現形式的選擇是通過伺服器上的演算法來實現,那麼這種方式的協商稱做伺服器驅動協商。選擇是基於響應可得的表現形式(根據不同的維度,響應會不同;例如,語言,內容編碼,等等)和請求訊息裡特定的頭域或附屬於請求的其他資訊(如:網路客戶端的地址)。
伺服器驅動協商是有優點的,當從可行的表現形式裡進行選擇的演算法對使用者代理來說描述是比較難的(譯註:代理驅動協商),或者當伺服器期望通過第一個響應傳送“最好的猜測”(“best guess”)給客戶端時(如果“最好的猜測”對使用者是合適的,能避免後續請求的迴路延遲)的時候。為了改善伺服器的猜測,使用者代理應該包含請求頭域(Accept,Accept-Language,Accept-Encoding,等等),這些頭域能描述它對響應的喜好。
服務驅動協商有如下缺點:
-
對伺服器來說不可能確切地決定什麼對使用者來說是最好的,因為那需要對使用者代理和響應目的的全面理解(如:使用者到底想把響應展示到螢幕還是列印到紙上?)。
-
使使用者代理在而每一個請求裡描述它的能力即不高效(假定只有少量的響應卻擁有多個表現形式)也潛在地侵犯使用者的隱私。
-
使源伺服器的實現變得複雜,並且使為請求產生響應的演算法實現變得複雜。
-
可能會限制公有快取(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(不接受的)狀態響應來進行代理驅動協商,當伺服器不能或不願意利用伺服器驅動協商來提供一個不同響應(a varying response)的是時候。
12.3 透明協商(Transparent Negotiation)
透明協商是伺服器驅動協商和代理驅動協商的結合體。當一個快取接收到伺服器的響應,並且響應裡提供了一系列可得的表現形式(就像在代理驅動協商裡的響應一樣)並且快取能理解維度的差異,那麼此快取變得有能力代表源伺服器為那個資源的後續請求去執行伺服器驅動協商。
透明協商的優點在於它能分發源伺服器的協商工作並且能移除代理驅動協商的第二次請求的延遲,因為快取能正確的猜測到合適的響應並返回給請求端。
此規範沒有定義透明協商的機制,雖然它也沒有避免任何這樣的機制作為擴充套件被用於HTTP/1.1。
13 HTTP中的快取
HTTP通常應用於能通過採用快取技術提高效能的分散式資訊系統。HTTP/1.1協議包括的許多使快取儘可能的工作的元素。因為這些元素與協議的其他方面有著千絲萬縷的聯絡,而且他們相互作用、影響,因此有必要分別從方法(methods),頭(headers),響應狀態碼來介紹快取的基本設計。
如果快取不能改善效能,他將一無用處。HTTP/1.1中快取可以在許多情況下排除傳送請求和傳送完整響應。前者減少了網路迴路的數量;我們利用一個“過期(expiration)”機制來為此目的(見13.2節)。後者減少了網路應用的頻寬;我們用“驗證(validation)”機制來為此目的(見13.3)。
對行為,可行性,和關閉的操作的要求需要我們能放鬆了語義透明性。HTTP/1.1協議允許伺服器,快取,和客戶端在必要的時候能顯式地降低透明性。然而,因為不透明的操作能混淆非專業的使用者,同時可能和某個伺服器應用程式不相容(例如訂購商品),因此協議透明性在下面情況下才能被放鬆:
-- 當被客戶端或源伺服器放鬆時,只能被一個顯式的協議層(protocol-level)請求放鬆
-- 當被快取或被客戶端放鬆時,只能在出現一個對終端使用者的顯式的警告時才能被放鬆
因此,HTTP/1.1協議提供這些重要的元素:
1.提供了完全語義透明性(full semantic transparency)的特性當被通訊所有方需要時
-
允許源伺服器或使用者代理顯式地請求和控制非透明性操作的協議特性
-
允許快取給響應繫結警告資訊(通過Warning頭域來實現)的協議特性,當這些響應沒有保持語義透明的請求近似性(requested approximation)時
一個基本的原則是客戶端必須能夠發現任何語義透明性的潛在放鬆規則。
注意:伺服器,快取,或者客戶端的實現者可能會面對設計上的決策,它並沒有明確地在此規範裡討論。如果一個決策影響了語義透明性,那麼實現者將會在維持語義透明性上犯錯,除非一個仔細且完整的分析能向我們展示打破透明性帶來的好處。
13.1.1快取正確性(Cache Correctness)
一個正確的快取必須能用快取裡最新的(up-to-date)響應來響應請求(見13.2.5,13.2.6,和13.12),已快取的響應必須滿足下面的條件:
1.已快取的響應已被檢測應與通過源伺服器重驗證後返回的響應等價。
2.已快取的響應是足夠保鮮(fresh)的(見13.2節)。預設的情況下,這意味著此響應必須滿足客戶端,源伺服器,和快取(見14.9節)的最少嚴格(least restrictive freshness)保鮮要求;如果源伺服器指定了保鮮要求,那麼它是源伺服器自己的保鮮要求。
如果一個已快取的響應,由於客戶端和源伺服器的最多嚴格(most restrictive freshness)保鮮要求,而不是足夠保鮮的,那麼在仔細考慮的情況下,快取也許仍然會根據一個合適的警告頭域(見13.15和14.46)返回此已快取的響應,除非這個響應不被允許(例如:通過”no-store” cache-directive ,或者通過一個”no-cache” cache-request-directive;見14.9節)。
3.已快取的響應是一個合適的304(沒有被改變),305(代理重定向),或 錯誤(4xx或者5xx)響應訊息。
如果快取不能同源伺服器通訊,如果已快取的響應能正確的服務於請求,那麼一個正確的快取應該用它快取的響應去響應請求;如果不能伺服器於此請求,那麼快取必須能返回一個錯誤或一個警告指示通訊失敗。
如果快取從伺服器端接收到一個響應(或者是一個完整的響應,或者一個304(沒有改變)的響應),此響應應該是伺服器正常情況下發送到請求的客戶端的響應,並且此響應並不再新鮮,那麼此快取應該把此響應轉發給請求客戶端而不需要新增一個新的Warning頭域(而不需要移去已經存在的Warning頭域)。快取並不是簡單的因為傳輸中響應變得陳舊而去嘗試重驗證響應;這可能會導致一個無限的迴圈。使用者代理接收一個陳舊的但沒有Warning頭域的響應,它應該提示使用者一個警告資訊。
13.1.2警告資訊(Warnings)
無論何時,快取返回一個響應,此響應既不是第一手的(first-hand)也不是足夠保鮮(在13.1.1節的條件2),那麼快取必須利用一個Warning常用頭域來警告產生的影響。Warning頭域和當前定義的警告在14.46節裡描述。這些警告允許客戶端去採取合適的動作。
Warning頭域可能被用於快取相關的和其他的目的。使用Warning頭域而不是錯誤狀態碼,區別於是否是真正的錯誤。
警告被賦予三位數字警告碼(warn-codes)。第一個數字指明:在一個成功的重驗證之後,警告是否必須或不必從快取項裡刪除。
1xx 警告描述了響應的保鮮或重驗證狀態,並且這些狀態必須在一個成功重驗證之後刪除。1xx警告碼(warn-codes)可能是由快取產生的,當驗證一個快取項時。此警告碼不能被客戶端產生。
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頭域允許客戶端或伺服器在請求或響應裡傳輸多個指令。這些指令常常覆蓋預設的快取演算法。作為一個常用規則,如果頭域值中存在一個明顯的衝突,那麼最多嚴格解釋(most restrictive interpretation)的頭域值會被應用(也就是說,能保留語義透明性的值)。然而,一些情況下,cache-control指令被顯式地用來削弱語義透明性的近似性(例如,”max-stale” 或者 “public”)。
Cache-control指令在14.9節被描述。
13.1.4顯式使用者代理警告(Explicit User Agent Warnings)
很多使用者代理允許使用者覆蓋基本快取機制。例如,使用者代理可能允許使用者指定快取實體(即使實體明顯是陳舊的)永遠不要被驗證。或者,使用者代理可能習慣於給任何請求加上“Cache-Control:max-stale=3600”。使用者代理不應該預設的執行非透明行為或導致非正常且無效率的快取行為,但是可以通過一個顯式的使用者動作,代理可能會被顯式地設定去這樣做。
如果使用者已覆蓋基本快取機制,那麼使用者代理無論何時遇到不能滿足伺服器透明性要求(server’s transparency requirements)的資訊被展現時,使用者代理應該顯式地給使用者以指示(特別是,如果被展現實體被認為是陳舊的)。因為協議通常允許使用者代理去判定響應是否是陳舊,所以此指示只需要實際發生時才被展現。此指示不必是對話方塊;它應該是一個圖示(例如,一個正在腐爛的魚)或者一些其他的指示器。
如果使用者以某種方式已覆蓋快取機制,同時這種方式可能非正常地降低了快取效率,那麼使用者代理應該繼續指示此狀態給使用者(例如,通過一個圖片顯示)以便使用者能謹慎地消費額外資源或忍受額外延遲。
13.1.5規則和警告的例外情況(Exceptions to the Rules and Warnings)
在某些情況下,快取的操作者可以選擇去設定返回陳舊的響應,即使此響應沒有被客戶端請求。這個決定不應該被輕易決定,但是為了實用性或效能方面的要求可能會這樣做,特別是當快取和源伺服器連線不好時。無能何時當快取會返回一個陳舊的響應時,快取必須給此響應做個標記(利用Warning頭域),這樣能使客戶端軟體能提醒使用者可能會存在潛在的問題。
同樣可以允許使用者代理去採取步驟獲得第一手的或保鮮的響應。由於這個原因,如果客戶端顯式地請求第一手的或保鮮的響應,快取就不應該返回一個陳舊的響應,除非由於技術或策略方面的原因而不能遵守。
13.1.6由客戶控制的行為(Client-controlled Behavior)
當源伺服器(退一步講,可以是通過在響應裡新增年齡的中間快取)是過期資訊的主要來源時,在某些情況下,客戶端可能需要控制快取決定是否返回一個已快取的響應而不需要通過伺服器驗證它。客戶端通過利用一些Cache-Control頭域的指示命令(directives)來達到此目的。
客戶端的請求可能會指定自己願意接受一沒有經過驗證響應的最大年齡(age);指定0值會強迫快取重驗證所有的響應。客戶端同樣也會指定在響應過期之前的最小保持時間。這兩個選項會增強對快取行為的限制,因此不能進一步地放鬆快取語義透明的近似性(approximation of semantic transparency)。
客戶端同樣可能會指定它願意接受(accept)到達的陳舊響應。這放鬆了對快取的限制,同時這可能違反了源伺服器對語義透明性的限制,但是這可以支援離線操作(disconnected operation),或者高可用性(high availability)當連線不好時。
13.2 過期模型 (Expiration Model)
13.2.1伺服器指定過期(Server-Specified Expiratiion)
HTTP快取會工作的很好,這是因為快取能完全地避免客戶端對源伺服器的請求。避免請求的主要機制是使伺服器通過提供一個將來的顯式過期時間(explicit expiration time)以指示響應可以滿足後續的請求。也就是說,快取能返回一個保鮮(fresh)的響應而不需要和源伺服器接觸。
伺服器可以給響應賦一個將來的顯式過期時間(explicit expiration time),並確信在過期時間之前實體不會改變。這通常能保持語義透明性,只要伺服器對過期時間仔細斟酌。
過期機制只能應用於從快取構建響應,而不能應用於立即轉發給客戶端的第一手(first-hand,見1.3節術語)響應。
如果源伺服器希望強制語義透明的快取去驗證每個請求,它給顯式過期時間(explicit expiration time)設為過去。這就是說響應總是陳舊的,所以當快取利用此響應去服務於後續請求時,快取應該驗證此響應。見14.9.4節,有更嚴格的方式來進行重驗證。
如果源伺服器希望強迫任何HTTP/1.1快取(不管此快取是怎樣設定的)去驗證每一個請求,源伺服器應該利用“must-revalidate”快取控制指令(見14.9節)。
伺服器指定顯式過期時間是通過利用Expires頭域或Cache-Control頭域裡的max-age快取控制指令。
過期時間不能被用於強制客戶代理去重新整理顯示或過載資源;過期的語義只能應用於快取機制,並且當對資源的發起新請求時,此機制只需檢測此資源的過期狀態。見13.13節,關於快取和歷史機制的差異。
13.2.2啟發式過期
因為源伺服器不能總是提供一個顯式過期時間(explicit expiration time),HTTP快取通常會賦予一個啟發式過期時間(heuristic expiration time),它採用一種演算法,此演算法利用其它頭域的值(例如Last-Modified時間)去估計一個合理的過期時間。HTTP/1.1規範沒有提供特定的演算法,但是卻加強了演算法結果最壞情況的限制。因為啟發式過期時間可能會損壞語義透明性,他們應該被謹慎地使用,並且我們鼓勵源伺服器儘可能提供顯式過期時間(explicit expiration times)。
13.2.3年齡(Age)計算
為了瞭解快取項(譯註:快取項是用來響應請求的,它包含已快取的響應實體)是否是保鮮的(fresh),快取需要知道其年齡是否已超過保鮮壽命(freshness lifetime)。我們在13.2.4節中討論如何計算保鮮壽命,本節討論如何計算響應或快取項的年齡。
在討論中,我們利用術語“now”來表示“執行計算主機上時鐘的當前值”。使用HTTP協議的主機,特別是運行於源伺服器和快取的主機,應該使用NTP[28] 或其他類似協議來同步其時鐘到全球(globally)精確時間標準上。
HTTP1.1協議要求源伺服器儘可能在每個響應裡附加一個Date頭域,並且賦予響應產生的時間(見14.18節)。我們利用術語“date_value”去表示Date頭域的值,這是一種適合於運算操作的表示方法。
當從快取裡獲取響應訊息時,HTTP/1.1利用Age響應頭域來表達響應訊息的估計年齡。Age響應頭域值是快取對響應自從被源伺服器產生或重驗證到現在的時間估計值。
實際上,年齡的值是響應從源伺服器途徑每一個快取的逗留時間的總和,再加上響應在網路路徑上傳輸的時間。
我們用“age_value”來表示Age頭域的值,這是一種適於算術操作的表示方法。
一個響應的年齡(age)可以通過兩種完全獨立的途徑來計算::
1.now - date_value,如果本地時鐘與源伺服器時鐘同步的相當好。若結果為負,則取零。
2.age_value,如果途徑響應路徑(response path)的所有快取均遵循HTTP1.1協議。
如果我們有兩種不同的方法計算響應的年齡,我們可以合併二者如下:
corrected_received_age = max(now – date_value,age_value)
並且只要我們有近似同步時鐘或全HTTP/1.1(all-HTTP/1.1)路徑,就能得到一個可信賴的(保守的)結果。
由於網路附加延時,會在伺服器產生響應與下一個快取或客戶端接收響應之間產生時間延遲。如果不經修訂,這一延遲會帶來不正常的低年齡。
由於導致產生年齡值的請求是早於年齡值的產生,我們能校正網路附加延遲通過記錄請求產生的時間。然後,當一個年齡值被接收後,它必須被解釋成相對於請求產生的時間,而不是相對響應接收的時間。不管有多少延遲,此演算法會導致保守的結果。所以,我們計算:
corrected_initial_age = corrected_received_age + (now - request_time)
這裡“request_time”是請求的傳送時間。
當快取收到響應時,年齡計算的演算法總結如下:
/*
* age_value
* is the value of Age: header received by the cache with this response.
* date_value
* is the value of the origin server's Date: header
* request_time
* is the (local) time when the cache made the request
* that resulted in this cached response
* response_time
* is the (local) time when the cache received the response
* now
* is the current (local) time
*/
apparent_age = max(0, response_time - date_value); //快取收到響應時響應的年齡
corrected_received_age = max(apparent_age, age_value);
response_delay = response_time - request_time;
corrected_initial_age = corrected_received_age + response_delay;
resident_time = now - response_time; //即收到響應到現在的時間間隔
current_age = corrected_initial_age + resident_time;
快取項(cache entry)的current_age是快取項從被源伺服器最後驗證到現在的時間間隔(以秒記)再加上corrected_initial_age。當從快取項裡產生一條響應時,快取必須在響應裡包含一個Age頭域,它的值應該等於此快取項的current_age值。
Age頭域出現在響應裡說明響應不是第一手的(first-hand)(譯註:第一手的說明,響應是直接來自於源伺服器到達接收端的,而不是來自於快取裡儲存的副本)。然而相反的情況並不成立,因為響應裡缺少Age頭域並不能說明響應是第一手的(fisrt-hand),除非所有請求路徑上的快取都遵循HTTP/1.1協議(也就是說,以前HTTP版本快取沒有定義Age頭域)。
13.2.4過期計算(Expiration Calculations)
為了確定一條響應是保鮮的(fresh)還是陳舊的(stale),我們需要將其保鮮壽命(freshness lifetime)和年齡(age)進行比較。年齡的計算見13.2.3節,本節講解怎樣計算保鮮壽命,以及判定一個響應是否已經過期。在下面的討論中,數值可以用任何適於算術操作的形式表示。
我們用術語“expires_value”來表明Expires頭域的值。我們用術語“max_age_value”來表示Cache-Control頭域裡“max-age”控制指令的值(見14.9.3節)。
max-age指令優於Expires頭域執行,所以如果max-age出現在響應裡,那麼定義如下:
freshness_lifetime = max_age_value
否則,若Expires頭域出現在響應裡,定義如下:
freshness_lifetime = expires_value - date_value
注意上述運算不受時鐘誤差影響,因為所有資訊均來自源伺服器。
如果Expires, Cache-Control:max-age, 或 Cache-Control:s-maxage (見 14.9.3) 均未在響應中出現,且響應沒有包含對快取的其他控制,那麼快取可以用啟發式演算法計算保鮮壽命(freshness lifetime)。快取必須對年齡大於24小時的響應附加113警告,如果此響應不帶這種警告。
同樣,如果響應有最後修改時間(Last-Modified time),啟發式過期值應不大於從那個時間開始到現在這段時間間隔的某個分數。典型設定為間隔的10% 。
計算響應是否過期非常簡單:
response_is_fresh = (freshness_lifetime > current_age)
13.2.5澄清過期值(Disambiguation Expiration Values)
由於過期值容易被任意設定,有可能兩個快取包含同一資源的不同保鮮值(fresh values)。
如果客戶端執行獲取請求接收到一個非第一手的響應,此請求響應在客戶端快取裡仍然是保鮮的,並且快取項裡的Date頭域的值比新響應的Date頭域值要新,那麼客戶端應該忽略此新響應。如果這樣的話,它可以以“Cache-Control:max-age=0”指令(見14.9節)重試請求,從而去強制和源伺服器重驗證。
如果一個快取對同一個表現形式(representation)擁有兩個保鮮響應卻有不同的驗證器,那麼快取必須利用Date頭域值最近的響應。這種情況可能發生由於快取會快取來自其它快取的響應,或者由於客戶端已要求過載或重驗證一個顯然保鮮的快取項的。
13.2.6澄清多個響應(Disambiguating Multiple Response)
因為客戶端可能收到經多個路徑而來的響應,所以某些響應會經過一些快取集,某些響應會經過其它快取集,客戶端收到響應的順序可能與源伺服器傳送響應的順序不同。我們希望客戶端利用最新的響應,即使舊響應仍然是保鮮的。
實體標籤(entity tag)和過期值(expiration value)都不能決定響應的順序,因為可能會出現晚一點的響應故意攜帶過早的過期時間(expiration time)。日期值的精度被規定只有一秒。
當客戶端嘗試重驗證一個快取項的時,並且接收到的響應裡Date頭域晚於已存在的快取項,那麼客戶端應該無條件的重試請求,並且包含
Cache-Control: max-age=0
去強制任何中間快取通過源伺服器來驗證(validate)它們的快取副本,或者
Cache-Control: no-cache
去強制任何中間快取去從源伺服器獲得一個新的副本。
13.3 驗證模型(Validation Model)
當快取擁有一箇舊快取項並且想利用它來作為客戶端請求的響應時,快取必須首先通過源伺服器(或者可能通過一個有保鮮響應的中間快取)對其進行驗證看是否此快取項可用。我們稱做“驗證(validating)”此快取項。我們可以不必花代價來重傳完整響應(full response),並且在快取項無效時可以不必產生額外的迴路,因此HTTP1.1協議支援使用條件方法(conditional methods)。.
協議支援條件方法(conditional methods)的關鍵特徵是圍繞“快取驗證器(cache validator)”展開的。當源伺服器產生一個完整響應(full response)時,它同時會附加一些驗證器給響應,這些驗證器和快取項一起儲存。當客戶端(使用者代理或快取)對有快取項的資源執行條件請求時,客戶端在請求裡包含一個相關的驗證器(validator)。
伺服器(有可能是源伺服器或快取伺服器)核對請求裡的驗證器和當前此實體本地驗證器是否匹配,如果匹配(見13.3.3),則返回一個特定狀態碼(通常為304(沒有改變))的響應並不包含實體主體(entity body)。如果不匹配,伺服器就返回完整響應(包含實體主體)。這樣,如果驗證器匹配,我們就避免了傳輸完整響應(full response);同時,如果驗證器不匹配,也避免了額外的迴路。
在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)
由於源伺服器和快取會比較兩個驗證器來確定他們是否代表相同的實體,所以通常希望實體發生任何變化時驗證器也相應變化,這樣的驗證器為強驗證器。.
然而,可能存在這樣的請求,伺服器傾向於僅在實體發生重要的語義變化時才改變驗證器,而在實體的某些方面不發生重大改變時就不改變驗證器。在資源變化時驗證器未必變化的驗證器稱為弱驗證器.。
實體標籤通常是強驗證器,但協議提供一種機制來使實體標籤變成弱驗證器。可以認為強驗證器在實體的每一位元組變化時而變化,而弱驗證器僅在實體的語義變化時才變化。換言之,我們能認為強驗證器是特定實體的標識,而弱驗證器是同一類語義等價實體的標識。
注: 強驗證器的例子:一個整數他會隨著每次實體發生變化而遞增。一個實體的修改時間,如果以秒為精度,能被看作為弱驗證器,因為在一秒內資源可能改變兩次。對弱驗證器的支援是可選擇的。然而,弱驗證器允許更有效地快取等價物件。
.
客戶端產生請求並把驗證器包含在一個驗證頭域(validating header fiield)裡時或伺服器比較兩個驗證器的時候均用到驗證器。強驗證器可在任何情況下使用,而弱驗證器僅在不依賴於嚴格相等時才可用。當客戶端產生條件GET請求來請求一個完整實體時,任何型別的驗證器都可以使用。然而,子範圍(sub-range)請求時只能使用強驗證器,否則客戶端可能會得到一個不一致的實體。
客戶端可以在發出簡單(非子範圍)GET請求裡既可以利用弱驗證器也可以利用強驗證器。客戶端不能利用弱驗證器在其它的請求形式裡。
HTTP1.1協議定義驗證的唯一功能就是比較。有兩種驗證器比較方法,這依賴於比較的背景是否允許利用弱驗證器。
.
-
強比較方法:如果相等,兩驗證器必須完全一致,並且兩個驗證器都是強驗證器。.
-
弱比較方法:如果相等,兩驗證器必須完全一致,但它們中的任何一個或全部被標明“弱”(“weak”)的不會影響結果。
實體標籤是強驗證器除非它被顯式地標記為弱(weak)的。3.11節給出了實體標籤的語法。
最後修改時間(Last-Modifed頭域的值)被用作請求的驗證器時預設為弱驗證器,除非滿足下列規則才判定它是強驗證器:.
-
此驗證器正在被源伺服器用來和當前實體驗證器進行比較,並且
-
源伺服器知道相關的實體不會在當前驗證器涵蓋的秒內改變兩次,
或者
-
此驗證器即將被客戶端用於If-Modified-Since 或者 If-Unmodified-Since頭域裡,因為客戶端有一個關於實體的快取項,並且
-
快取項包含一個日期值(Date value),日期值給出了源伺服器傳送源響應的時間,並且
-
Last-Modifed頭域值至少提前於日期值(Date value)60秒。
或者
-
此驗證器正在被中間快取通過與其快取項裡儲存的驗證器相比較 ,並且
-
快取項包含日期值(Date value),它指明瞭源伺服器傳送源響應(original response)的時間,並且
-
Last-Modifed頭域值至少提前於日期值(Date value)60秒。
此種方法依賴於以下事實,如果兩個不同響應被源伺服器在同一秒內被髮出,但這兩個響應都有相同的最後修改時間(Last-Modified time),那麼其中至少有一個響應的日期值和最後修改時間的值(Last-Modifed的值)相等。60秒的限制能保證Date和Last-Modifed的值在不同時鐘或在響應準備期間的不同時刻產生。一個實現可能會利用大於60秒的值,如果它認為60秒太短。
如果客戶端希望執行子範圍(sub-range)請求來請求一個只有最後修改(Last-Modifed)時間但沒有晦澀(opaque)驗證器時,它可能會認為只有最後修改(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.0和HTTP/1.1快取能合適地進行響應。
HTTP/1.1源伺服器,當接收到一個條件請求並同時包含Last-Modifed日期(例如,在If-Modified-Since,或If-Unmodified-Since頭域裡)和一個或多個實體標籤(例如在If-Match,If-None-Match,或If-Range頭域裡)作為快取驗證器時,源伺服器不能返回一個304狀態響應(沒有改變)除非這樣作能與請求裡所有的條件頭域一致。
HTTP/1.1快取,當接收到一個條件請求並且此請求裡同時包含Last-Modified日期和一個或多個實體標籤作為快取驗證器時,它不能返回一個本地已快取的響應給客戶端,除非已快取的響應與請求裡所有條件頭域一致。
注意:這些原理背後的規則是HTTP/1.1伺服器和客戶端應在請求和響應裡儘可能傳輸非冗餘的資訊。接收這些資訊的HTTP/1.1系統將會對這些接收到的驗證器作最保守的假設。
HTTP/1.0客戶端和快取會忽略實體標籤。通常,Last-Modified值會被這些系統接收和利用,以提供透明性和高效快取行為,因此HTTP/1.1源伺服器這時應提供Last-Modified值。在一下很少的情況,一個Last-Modified值作為驗證器被HTTP/1.0系統使用時會帶來嚴重的後果,這時HTTP/1.1伺服器不應提供一個Last-Modified值。
13.3.5非驗證條件(Non-validating Conditionls)
實體標籤背後的原則是隻有服務作者才知道資源的語義從而去選擇一個合適的快取驗證機制,並且任何比位元組相等(byte-equality)比較方法複雜的驗證器比較方法都會帶來風險。所以,任何其他的頭域的比較(除了Last-Modified,為了相容HTTP/1.0)從來不會被用於驗證一個快取項。
13.4 響應的可快取性(Response Cacheability)
除非被快取控制(見14.9節)指令明確地限制,快取系統可以將一成功響應作為快取項,可以返回快取項裡的響應副本而不需要驗證它如果此副本是保鮮的,並且也可以在驗證成功後返回它。如果響應既沒有快取驗證器也沒有顯式過期時間,我們認為它不能被快取,但是某些快取可能會違反這個約定(例如,當處於離線時)。客戶端能經常發現這種來自於快取的響應,只需通過把Date頭域值同當前時間作比較。
注意:某些HTTP1.0快取可能違反這一假設而沒有提示任何警告。
然而,在一些情況下,快取不適合儲存實體,或使快取的實體服務於後續請求。這可能因為服務的作者認為絕對的語義透明性是有必要的,或著出於安全和隱私考慮。某些快取控制指令因此被提供是為了讓伺服器能指示某些資源實體,或部分實體,不能被快取。
注意在14.8節裡描述了防止一個共享快取(shared cache)去儲存和返回一個以前包含Authorization頭域請求的響應。
除非快取控制指令防止響應被快取,一個接收的響應如果它的狀態碼是200,203,206,300,301或410,那麼此響應應該被快取儲存而且可用於後續的請求,但這必須受過期機制決定。然而,如果快取不支援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頭域。
其它hop-by-hop頭域必須在Connection頭域(14.10節)裡列出,並將被引進於HTTP/1.1(或後來的版本)裡。
13.5.2不可更改的頭域 (Non-modifiable Headers)
HTTP1.1的某些特徵,如數字認證(Digest Authentication),是基於某些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)。
如果任何要求不能滿足,快取必須利用最接近現在(most recent)的部分響應(基於任何響應的Date頭域值,並且會利用輸入響應如果這些Date頭域值相等或丟失了),而且必須丟棄其它的部分資訊。
13.6 快取已協商響應(Caching Negotiated Responses)
使用伺服器驅動內容協商(12.1節),會在響應裡新增Vary頭域,並改變快取利用響應去服務後續請求的條件和過程。見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頭域匹配同一請求URI已存快取項的Content-Location頭域,並且它的實體標籤不同於已存快取項的實體標籤,而且它的Date頭域值比已存快取項更接近當前,那麼已經存在的快取項不能被返回去響應將來的請求並且將會從快取裡刪除。
13.7 共享和非共享快取 (Shared and Non-Shared Caches)
出於安全和保密考慮,有必要區分共享和非共享快取。非共享快取是僅供一個使用者訪問,此情況下,訪問性(accessibility)應由適當的安全機制控制。所有其它快取均被認為是共享的。此協議的其它部分對共享快取的操作新增限制以防止隱私丟失或訪問控制的失敗。
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方法不應有導致錯誤的行為的副作用(side effects)如果這些響應來自於快取。他們可以仍然有副作用,但快取在決定快取時不必考慮這些副作用。快取總是被期望去觀察一源伺服器對快取的顯式限制(explicit restrictions)。
我們注意到此規則的一個例外:有些應用程式習慣於在在GETs和HEADs方法裡使用查詢URLs(在rel_path_part裡包含一個“?”)從而執行帶來很大的副作用的操作,快取不能把此URIs的響應看作一個保鮮的,除非伺服器提供一個顯式過期時間(explicit expiration time)。這就意味著,對這樣的URIs的,來自HTTP/1.0伺服器的響應不應被快取儲存。見9.1.1節相關的資訊。
13.10 在更新或刪除後的無效性
在源伺服器上,某些方法對某資源執行的影響,可能會引起一個或多個已存快取項的非透明的無效。也就是說,雖然他們可能會繼續是保鮮的,但是他們不能準確的反應出源伺服器對那個資源的新請求的響應。
HTTP協議無法保證所有此類快取項均被標明無效。例如,引起源伺服器上資源變化的請求可能不會穿過存有一個快取項的代理。然而,卻有一些規則幫助減少可能的錯誤行為。
在此節裡,短語“使實體無效(invalidata an entity)”意味著快取要麼可以刪除它儲存的所有的實體的例項,要麼可以把這些實體例項標記為“無效”並在它們可作為後續請求的響應之前進行重驗證。
一些HTTP方法必須讓快取去使一個實體無效(invalidate an entity) 。這些實體要麼被請求URI指定,要麼在Location或在Content-Location頭域裡被指定(如果出現的話)。這些方法是:
-
PUT
-
DELETE
-
POST
為了防止伺服器攻擊拒絕,一個基於Location或Content-Location頭域裡的URI的無效處理必須只有在URI的host部分和請求URI裡的host部分相同時才被執行。
一個快取如果不能理解請求裡的方法,那麼它應該使請求URI指定的任何實體無效。
13.11 強制寫通過( Write-Through Mandatory)
所有可能對源伺服器資源進行修改的方法都要寫通過(written through)給源伺服器。這通常包括所有除了GET和HEAD的方法。快取在將此種請求轉發給伺服器並獲得相應響應前不能對請求客戶端做出響應。 但這個不能阻礙代理快取在伺服器已傳送最終響應(final replay)之前傳送100(繼續)響應。
相反的情況(通常叫“寫回”或“拷貝回”快取)在HTTP1.1中是不允許的,這是由於保持一致的更新是非常困難的,並且在寫回之前也會存在伺服器,快取和網路故障的問題。
13.12 快取替換 (Cache Replacement)
如果一個新可快取(見14.9.2, 13.2.5, 13.2.6 和 13.8)響應從一資源被快取接收,並且同一資源的已存響應已經被快取儲存,那麼快取應該利用新響應去響應當前請求。快取可能會把這一新響應放進儲存裡,並且可以,如果它滿足所有其它要求,利用此響應來響應任何將來的請求。如果快取想把此新響應加進快取儲存,13.5.3的規則必須應用。
說明:一個新響應如果其Date頭域值比已存已快取的響應的Date頭域值要舊,那麼它是不可快取的。
13.13 歷史列表 (History Lists)
使用者代理經常使用歷史機制(history mechanisms),如“後退”按鈕和歷史列表,來重新展示一個會話的先前實體。
歷史機制和快取機制是不同的。特別是歷史機制不應嘗試給資源當前狀態展示一語義透明檢視。其歷史機制只是為了展示資源獲取當時使用者看到的東西。
預設情況,過期時間(expiration time)沒有應用於歷史機制(history mechanisms)。如果實體仍然在儲存裡,歷史機制應該對其顯示即使其實體已經過期了,除非使用者專門地設定代理去重新整理已過期的歷史文件。
這不能防止歷史機制告訴使用者某檢視可能過期。
注意:如果歷史機制沒必要地阻止了使用者檢視陳舊資源,那麼這會強制服務作者避免利用HTTP過期控制和快取控制當他們想利用時。服務作者可以認為使用者不被呈現錯誤訊息或警告訊息是非常重要的,當他們利用導向按鈕(如回退按鈕)去看以前獲得的資源時。即使有時這些資源本不應被快取儲存,或應很快過期,使用者介面的考慮可能會強制服務作者去尋求其它防止快取的方法(例如,“一次性”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頭域值發現它不能傳送客戶端可接受的響應,那麼伺服器應傳送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, /
擁有下面的優先順序:
1)text/html; level=1
2)text/html
3)text/*
4)/
一個媒體型別的喜愛程度質量因子是和一個給定的媒體型別聯絡在一起的,它是由查詢能最高優先匹配那個媒體型別的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 = "Accept-Charset" ":"
1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
字符集值在3.4節裡描述。每一個字符集可能被給於一個相聯絡的質量值用來表示使用者對那個字符集的喜愛程度。預設值是q=1.例如:
Accept-Charset:: iso-8859-5, unicode-1-1;q=0.8
如果特殊值“”出現在Accept-Charset頭域裡,那麼將匹配任何Accept-Charset頭域裡沒有的字符集(包含ISO-8859-1)。如果Accept-Charset頭域裡沒有出現“”出現,那麼所有沒有在Accept-Charset頭域裡顯式宣告的字符集的質量值都為0,但是有個例外,那就是如果ISO-8859-1沒有被顯式宣告,那麼它的質量值為1。
如果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頭域,並利用下面的規則來決定:
1.如果一個內容編碼(content-coding)在Accept-Encoding頭域裡出現,那麼它是可以接受的(acceptable),除非它的qvalue為0。(這在3.9節裡定義,一個qvalue為0說明是“不可接受的”)
2.如果“*”出現在Accept-Encoding頭域裡,那麼它匹配任何沒有出現在Accept-Encoding頭域裡的可得內容編碼。
3.如果多個內容編碼是可接受的,那麼qvalue為最高的且非0的內容編碼是最喜歡的。
4.“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匹配一個語言標籤如果它能精確和語言標籤相等,或者它能精確匹配標籤字首,標籤字首是語言標籤裡字元“-”之前的部分。特殊的“*”字元出現在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響應頭域允許伺服器向客戶指明伺服器對範圍請求的接受度。
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)指定的資源所支援的方法。此頭域的目的是嚴格地讓接收端知道資源所適合的方法。在405(方法不被允許)響應中必須出現Allow頭域。
Allow = "Allow" ":" #Method
使用示例:
Allow: GET, HEAD, PUT
這一頭域不能阻止客戶端使用其他方法。但在Allow頭域域中給出的方法應被執行。Allow頭域裡指定的方法是每次請求時被源伺服器定義的方法。
Allow頭域裡可以和一PUT請求一起使用,而為了說明新的或改變的資源支援這些方法。伺服器不需要去支援這些方法,伺服器應包含一個Allow頭域在響應裡並且給出實際支援的方法。
代理(proxy)不能改變Allow頭域即使它沒有理解此頭域裡指定的所有方法,因為使用者代理可能和源伺服器通訊有其他的意圖。
14.8 Authorization (授權)
使用者代理往往希望通過伺服器給自己授權,使用者代理這樣做是通過在請求裡包含一個Authorization請求頭域,但是通常在接收了一個401響應後就沒有必要再讓伺服器給自己授權了。Authorization頭域由包含使用者代理對請求資源域的授權資訊的證書(credentials)組成。
Authorization = "Authorization" ":" credentials
HTTP訪問授權在“HTTP Authenticatiion:Basic and Digest Access Authentication”[43]中描述。如果一個請求被授權並且一個域(realm)被指定,那麼這個證書應對此域裡所有的其他請求是有效的(假設在此授權模式本身不需要其它例如根據激發值或利用同步時鐘而變化的證書)。
當一個共享快取(shared cache)(見13.7節)接收一個請求,並且此請求包含一個Authorization頭域時,那麼快取不能返回此請求相應的響應來響應任何其它的請求,除非下面指定的例外之一發生:
1.如果此響應包含“s-maxage”快取控制指令,那麼此快取可以利用此響應來響應後續請求。但是(如果指定的最大年齡過期了)代理快取必須首先通過源伺服器來重驗證此響應,同時利用新請求裡的Authorization請求頭域去讓源伺服器給新請求授權。(這是s-maxage定義的行為)。如果響應包含“s-maxage=0”,那麼代理在重利用此響應之前必須總是重驗證它。
2.如果此響應包含“must-revalidate”快取控制指令,那麼快取可以利用此響應來響應後續請求。但是如果此響應是陳舊的,那麼所有快取必須首先通過源伺服器重驗證那個響應,同時利用新請求裡的Authorization請求頭域去讓源伺服器去給此新請求授權。
3.如果此響應包含“public”快取控制指令,那麼此響應可以用來響應任何後續的請求。
14.9 Cache-Control
Cache-Control常用頭域被用於指定必須在請求/響應鏈上的被所有快取機制遵守指令。這些指令指定了防止快取去幹涉請求或響應的行為。這些指令經常覆蓋預設的快取演算法。快取指令是單方向的,因為請求中指令的存在並不意味著同樣的指令必須在響應中出現。
請注意HTTP/1.0快取可能沒有實現Cache-Control,並且也沒有實現Pragma: no-cache(參見14.32節)。
快取指令必須被代理或閘道器通過,不管這些指令對應用程式有多重要,因為這些指令可能對請求/響應鏈上的所有接收者都適用。不可能為一個特定快取去指定一個快取指令。
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
指明響應訊息的部分或所有部分是為一個使用者準備的並且不得被共享快取儲存。可以使源伺服器可以宣告響應的特定部分來針對某一使用者並且對其他使用者的請求是無效的。一個私有(非共享)快取可以快取此響應。
注:詞語“私有”的使用僅用來控制響應在何處可被快取,並且不能保證訊息內容的隱私。
no-cache
如果no-cache快取控制指令沒有指定一個field-name,那麼一個快取不能利用此響應在沒有通過源伺服器對它進行成功重驗證的情況下去滿足後續的請求。這允許源伺服器去防止響應被快取儲存,即使此快取已被設定可以返回陳舊響應給客戶端。
如果no-cache快取控制指令指定一個或多個field-name,那麼快取可以利用此響應去滿足後續的請求,但這要受限於對快取的其它限制。然而,指定的filed-name必須不能在後續請求的響應裡被髮送如果此響應沒有在源伺服器那裡得到成功重驗證。這允許源伺服器能防止快取去重利用響應裡的某些頭域,但仍然允許快取能儲存響應剩餘部分。
注意:大多數HTTP/1.0快取將不能識別或遵循這個指令。
14.9.2什麼能被快取儲存
no-store
no-store快取控制指令的目的在於防止不經意地釋放或保留敏感資訊(比如存放在備份磁帶的資訊)。 no-store快取控制指令應用於整個訊息,並且可以在響應裡或在請求裡被髮送。如果在請求裡被髮送,快取不能儲存此請求或此請求響應的任何部分。如果在響應裡被髮送,快取不能儲存此響應或儲存此響應請求的任何部分。此快取控制指令能應用於非共享快取和共享快取。“不能儲存”在這個背景裡的意思是指快取不能有意地把資訊儲存在非易失性儲存裡,而且必須盡力去刪除易失性儲存上的資訊當它轉發完畢後。
即使當此指令在一個響應裡時,使用者也可能會顯式地在快取系統之外儲存這個響應(例如,利用一個“另存為”對話方塊)的地方。歷史緩衝(History buffers)(見13.13節)可能儲存這個響應作為它們正常操作的一個部分。
此指令的目的是為了滿足某些使用者宣告的要求,還有就是為那些比較在意通過訪問快取資料結構而發生資訊洩漏的作者提供方便。在一些情況下,利用此快取控制指令可能會增強隱私,但是我們注意到它並不是在任何情況下都是可信任的或都能充分地保護隱私的。特別是,惡意的或被損壞的快取可能不能識別到或遵循此指令,並且網路通訊也容易隨時受到竊聽。
14.9.3對基本過期機制的改進
實體的過期時間可由源伺服器利用“Expires”頭域(參見14.21節)指定。 或者,也可以在響應裡利用max-age快取控制指令指定。當max-age快取控制指令出現在一個已快取的響應裡時,如果此響應的當前年齡(current age,譯註:見13.2.3節關於current age的定義)大於為那個資源的一個新請求時max-age裡給定的年齡值(以秒),那麼這個已快取的響應是陳舊的(stale)。對在一個響應裡應用max-age快取控制指令意味著此響應是可快取的(也就是說“公有的”)除非出現其它更具限制性的快取控制指令於響應裡。
若響應同時含有Expires頭域和max-age快取控制指令,那麼max-age快取控制指令應該覆蓋Expires頭域,即使Expires頭域更具限制性。此規則允許源伺服器可以為一給定響應來為一HTTP/1.1(或更遲)快取提供一個比一HTTP/1.0快取更長的過期時間(expiration time)。這個規則可能會很有用,如果某個HTTP/1.0快取不恰當地計算了年齡(ages)或過期時間(expiration times),可能由於不同步的時鐘。
許多HTTP/1.0快取實現可能會把響應裡小於或等於該響應裡Date頭域值的Expires頭域值看成與“no-cache”快取控制響應指令等效。如果一個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-stale沒有賦值,則客戶端願接受任意年齡的陳舊響應。
由於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)”。
利用快取控制請求指令,客戶端能指定下面三種動作:
End-to-end reload (End-to-end重新載入)
請求包含“no-cache”快取控制指令,或,為了相容HTTP/1.0客戶端,“Pragma: no-cache”快取控制指令。頭域名不能被包含在請求的no-cache快取控制指令裡。伺服器不能利用一個快取副本來響應這樣一個請求。
Specific end-to-end revalidation(指定的end-to-end重驗證)
請求包含一個“max-age=0”快取控制指令,它強制每個途徑源伺服器的快取必須通過下一快取或伺服器來重驗證它所擁有的快取項(如果有的話)。此初始請求包含一帶有客戶端當前驗證器的快取驗證條件。
Unspecified end-to-end revalidation(未指定的end-to-end重驗證)
請求包含一個“max-age=0”快取控制指令,它強制每個途徑源伺服器的快取必須通過下一快取或伺服器來重驗證它所擁有的快取項(如果有的話)。此初始請求沒有包含一快取驗證條件;沿著路徑上的第一個擁有此資源快取項的快取(如果有的話)在請求裡包含一帶有其快取當前驗證器的快取驗證條件。
max-age
當一箇中間快取被一個max-age=0的快取控制指令強迫去重驗證它所擁有的快取項,並且客戶端已經在請求裡包含了其本身擁有的驗證器,此驗證器可能不同於當前快取項裡儲存的驗證器。在這種情況下,快取應該在不影響語義透明性的情況下利用任一驗證器去執行請求。
然而,驗證器的選擇可能會影響效能。最好的辦法對中間快取來說,就是當執行請求時利用它自己的驗證器。如果伺服器以304(沒有改變)回覆,那麼此快取能返回一個它自己現在已經驗證了的副本給客戶端同時以一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快取控制指令出現在已被快取接收的響應裡時,那麼此快取不能利用此快取項,如果在它變得陳舊並且沒有通過源伺服器對它進行重驗證的情況下,去響應一個後續的請求。(也就是說,快取必須每次進行end-to-end重驗證,如果單獨地基於源伺服器的Expire或max-age值,已快取的響應是陳舊的話)
must-revalidate快取控制指令可以為某些協議特性提供可信賴性操作。在所有情況下,一個HTTP/1.1快取必須遵循must-revalidate快取控制指令;特別地,如果此快取不能直接和源伺服器通訊,那麼它必須產生一個504(閘道器超時)響應。
伺服器應傳送must-revalidate快取控制指令,如果並且只有在伺服器對實體的驗證請求失敗而導致不正確的操作時,例如一個不動聲息的未執行的金融事務。接收端不能採取任何違反此快取控制指令的自動的行為,並且不能自動地提供一個被驗證無效的實體副本如果此副本通過源伺服器重驗證失敗。
儘管這不被推薦,使用者代理(user agent)如果在糟糕的網路連線限制下,可能會違反此快取控制指令,但是,如果這樣的話,它必須顯式地警告使用者這是一個未驗證的響應。警告必須在每次未驗證的訪問時被提供,而且使用者代理應需要使用者顯式地確認資訊。
proxy-revalidate
proxy-revalidate快取控制指令和must-revalidate快取控制指令具有相同的語義,但它不能應用於非共享(non-shared)的使用者代理快取。它能被用於一已被授權請求的響應,去允許使用者快取能儲存或者過後能返回此響應而不需要去重驗證它(因為它已經被那個使用者授權了一次),但是服務於多個使用者的代理仍然需要每次去重驗證它(為了保證每個使用者已被授權)。注意這樣的授權響應同樣需要public快取控制指令,這是為了允許響應能完全被快取。
14.9.5 No-Transform快取控制指令
no-ransform
中間快取(代理)的實現者們已發現轉換某個實體主體的媒體型別轉是很有用的。一個非透明代理可能,例如,會在不同影象格式之間進行轉換,這是為了節約空間或在低速的連線上減少通訊流量。
然而,當這些轉換應用於某些應用的實體主體時,會引發嚴重操作問題。比如,醫學圖象應用程式,科學資料分析應用程式和利用end-to-end認證的應用程式都必須保證接收到的實體主體與原實體主體每一bit都是一致的。
所以,如果訊息包括了no-ransform快取控制指令, 那麼中間快取或代理不能改變13.5.2節中列出的受限於no-transform快取控制指令的頭域。這意味著快取或代理不能改變由這些頭域指定的實體主體的任何方面(aspect),包括實體主體本身的值。
14.9.6快取控制擴充套件(Cache control Extendions)
Cache-Control頭域能被擴充套件,可通過一個或多個cache-extension標記,每個標記可以被賦於一個值。資訊擴充套件(這些擴充套件無須快取行為的改變)可以不經改變其它快取控制指令的語義而被新增。行為擴充套件是通過現有快取控制指令的基本行為的修飾來實現的。 新快取控制指令與標準快取控制指令兩者都被提供,這樣,不理解新快取控制指令的應用程式會預設地採用標準快取控制指令規定的行為,而那些能理解新指令的應用程式會將其看做是修改了標準快取控制指令的要求。這樣,快取控制指令的擴充套件可以在無須改變基本協議的情況下就能夠實現。
擴充套件機制依賴於一HTTP快取,此快取遵從所有本地HTTP版本快取定義的快取控制指令,遵從一定的擴充套件,並且會忽略所有它不能理解的快取控制指令。
例如,考慮一個假設的名為“community”的新快取響應控制指令,此指令被看成是對private快取控制指令的修飾。我們定義此新快取控制指令以表明:除共享快取,任何被communit值命名的社群成員共享的快取也可快取此響應。例如,如果一個源伺服器希望允許UCI社群裡的成員在他們共享快取裡可以使用一私有響應,那麼此源伺服器應該包含:
Cache-Control: private, commuity="UCI"
一個見到此頭域的快取將會正確執行,即使此快取不能理解這個community快取擴充套件,因為快取同樣能看到並且能理解private快取控制指令所以這樣能導致預設的安全行為。
不能識別的快取控制指令必須被忽略;我們認為不能被HTTP/1.1快取識別的任一快取控制指令會和標準快取控制指令(或者響應的預設快取能力)聯合在一起這樣快取行為會保持最小正確性即使快取不理解此擴充套件。
14.10 Connection
Connection常用頭域允許傳送者指定某些專屬於某特定連線的選項,並且Connection頭域不能被代理(proxy)在以後的連線中傳送。
Connection頭域遵循如下語法:
Connection = “Connection” “:” 1#(connection-token)
connection-token = token
HTTP/1.1代理必須在轉發訊息之前解析Connection頭域並且,為此頭域中每一個connection-token,從訊息中刪除任何與connection-token裡同名頭域。 連線選項是由Connection頭域中出現connection-token而指明的,而不是由任何相應的附加頭域,因為附加頭域可以不被髮送如果對應的那個連線沒有引數。
Connection頭域裡列出的訊息頭域不得包含end-to-end頭域,例如Cache-Control頭域。
HTTP/1.1定義了“close”連線選項,這是為了讓傳送者指明在完成響應後連線將被關閉。
例如
Connection:close
無論是出現在請求或響應的頭域裡都表明:在完成現有請求/響應後連線不應被視是“持續的(persistent)”(參見8.1節)。
不支援持久連線的HTTP/1.1應用程式必須在每一訊息中都加上“close”連線選項。
接收到含有Connection頭域的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節)並且列出非dentity的內容編碼。
若實體的內容編碼(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頭域裡可以為內容(content)列出多種語言。例如,同時用毛裡土語和英語呈現“Treaty of Waitangi”就可以用下面表示:
Content-Language: mi,en
然而,有多種語言呈現於實體中並不代表此實體一定是為多個國家語言的使用者準備的。比如《初學拉丁文》之類的語言啟蒙教程,顯然是針對英語使用者的。這裡,合適的Content-Language頭域裡應只包括“en”。
Content-Language可應用於任意媒體型別(media type) -- 它不限於文字式的文件。
14.13 Content-Length
Content-Length實體頭域用於指明發送給接收者實體主體(entity-bidy)的大小(以十進位制的位元組數表示),或是在使用HEAD方法時,指明實體主體本應在GET方法時傳送實體主體的大小。
Content-Length = “Content-Length” “:” 1*DIGIT
示例:
Content-Length: 3495
除非被4.4節裡規定的規則禁止,否則應用程式應該利用此頭域指明訊息主體(message-body)的傳輸長度。
任何大於或等於0的Content-Length均為有效值。如果一個Content-Length沒有在訊息裡給定,4.4節描述瞭如何判斷訊息主體的長度。
請注意Content-Length頭域的含義與MIME中的關於此頭域的定義有很大的區別,MIME中,它在content-type型別為“message/external-body”的訊息裡是可選的。在HTTP中,在訊息被傳輸之前,如果訊息的長度能被確定,那麼訊息裡應該包含Content-Length頭域,除非不被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(original requested URI)的替代物;它只能是陳述了請求時相應於特定實體的資源位置。將來的請求也許會用Content-Location裡的URI作為請求URI,如果請求期望指定那個特定實體源。
如果一個實體含有一個Content-Location頭域,並且此頭域裡的URI不同於獲得此實體的URI,那麼快取不能認為此實體能被用於去響應基於那個Content-Location裡URI的後續請求。然而,Content-Location能被用於區分同一請求資源的多個實體,這在13.6節裡描述了。
若Content-Location擁有的是相對URI(relative URI),則此相對URI(relative URI)是相對於請求URI來解析的(Request-URI)。
PUT或POST請求中含有Content-Location頭域是沒有定義的;伺服器可自由忽略它。
14.15 Content-MD5
Content-MD5實體頭域,正如RFC1864[23]裡定義的一樣,提供實體主體(entity-body)的MD5摘要(digest),為的是提供end-to-end訊息完整性檢測(MIC)。(注:一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)的位元組的,就像一條命令:如果沒有傳輸編碼被應用,它們將會被髮送。
HTTP 將RFC 1864拓寬到允許對MIME複合媒體型別(如multipart/*,message/rfc822)計算摘要,但這並不改變如前所述的摘要計算方法。
有一些關於這個的後果。複合媒體型別(composite types)的實體主體可能包含許多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更多地使用二進位制內容型別,所以這種情況要注意用於計算摘要的位元組順序是由那個型別所定義的傳輸位元組順序(transmission byte order)。最後,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,它應把請求裡無效的Range頭域視為不存在。(正常情況下,這意味著返回一個包含完整實體的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賦予一值,此值在伺服器的配置時間之時或之前將被視為過去。(這允許響應提前過期而不需要為每個資源儲存單獨的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值,那麼它必須以合適的錯誤狀態碼響應。如果伺服器不能滿足任何expectation值,伺服器必須以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]
From頭域可以被用於記錄日誌和作為識別無效或不期望請求的來源。他不應該被用作訪問保護的不可靠方法。這個頭域的解釋是:此請求是代表所指定人執行,此人應該承擔這個方法執行的責任。特別的,機器人代理(robot agents)應該包含這個頭域,這樣此人應該對執行此機器人代理程式負責,並且應該能被聯絡上如果在接收端出現問題的話。
此頭域裡的網路email地址是可以和發出請求的網路主機(host)不同。例如,當一個請求被通過一代理(proxy)時,源作者的地址應被使用。
客戶端在沒有使用者的允許時是不應發出From頭域的,因為它可能和使用者的個人隱私或他們站點的安全策略(security policy)相沖突。強烈建議在任何一請求之前,使用者能取消,授權,和修改這個頭域的值。
14.23 Host
Host請求頭域指明瞭請求資源的網路主機和埠號,這可以從使用者或相關資源給定的源URI獲得(通常是一個HTTP URL,在3.2.2節描述)。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頭域的時候,一些伺服器使用精確的日期比較方法,而不是小於(less-than)比較方法,來決定是否傳送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)(利用了If-Unmodified-Since和If-Match頭域兩者或其中之一)請求裡利用Range請求頭域。然而,如果由於實體被改變而使條件失敗,那麼客戶端可能會發出第二次請求從而去獲得整個當前實體主體(entity-body)。
If-Range頭域允許客戶端使第二次請求短路(short-circuit)。說的通俗一點,這意味著:如果實體沒有改變,傳送我想要的部分;如果實體改變了,那就把整個新實體發過來。
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節)提供一種機制去限制轉發請求的代理或閘道器的數量。當客戶端嘗試去跟蹤一個好像陷入失敗或陷入迴圈的請求鏈時,這是非常有幫助的。
Max-Forwards = “Max – Forwards” “:” 1*DIGIT
Max-Forwards值是十進位制的整數,它指定了請求訊息可以剩餘轉發的次數。
對於一個TRACE或OPTIONS請求,如果包含一個Max-Forwards頭域,那麼接收此請求的代理或閘道器必須能在轉發(forwarding)此請求之前檢查和更新Max-Forwards頭域值。如果接收的值為0,那麼接收者不能轉發此請求;而是,它必須作為最後的接收者響應。如果接收的Max-Forwards值比0大,那麼此轉發的訊息必須包含一個更新了的Max-Forwards頭域,更新的值是在接收時的值上減去1。
對本規範定義的所有其它方法以及任何沒有明確作為方法定義部分的擴充套件方法的請求裡,Max-Forwards頭域可能會被忽略。
14.32 Pragma
Pragma常用頭域被用於包含特定執行指令,這些指令可能被應用於請求/響應鏈中任何接收者。從協議的觀點來看,pragma指令指定的行為是可選的;然而,一些系統可能要求行為必須滿足指令的要求。
Pragma = “Pragma” “:” 1#pragma-directive
pragma-directive =”no-cache” | extension-pragma
extension-pragma =token [ “=” ( token | quoted-string) ]
當no-cache指令出現在請求訊息中,應用程式應該轉發(forward)此請求到源伺服器,即使它擁有此請求響應的快取副本。pragma指令和no-cache快取控制指令(見14.9)有相同的語義,並且它是為同HTTP/1.0向後相容而被定義。當一個no-cache請求傳送給一個不遵循HTTP/1.1的伺服器時,客戶端應該既包含pragma指令也包含no-cache快取控制指令。
pragma指令必須能穿過代理和閘道器應用程式,不管對於那些應用程式有沒有意義。因為這些指令可能對請求/響應鏈上的所有接受者有用。不可能為一個特定的接收者定義一個pragma;然而,任何對接收者不相關的pragma指令都應該被接收者忽略。
HTTP/1.1快取應該把“Pragma:no-cache”當作好像客戶端傳送了“cache-control:no-cache”。在HTTP中不會有新的pragma指令會被定義。
14.33 Proxy-Authenticate
Proxy-Authenticate響應頭域必須被包含在407響應(代理授權)裡。此頭域值由一個challenge和parameters組成,challenge指明瞭授權模式,而parameters應用於請求URI的代理。
Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
關於HTTP訪問授權過程的描述在“HTTP Authentication:Basic and Digest Access Authentication”[43]中介紹了。不像WWW-Authenticate頭域,Proxy-Authenticate頭域只能應用於當前連線,並且不應該傳遞給下游(downstrem)客戶端。然而,一箇中間代理可能需要從請求下游客戶端而獲得它自己的證書(credentials),這在一些情況下就好像代理正在轉發Proxy-Authenticate頭域一樣。
14.34 Proxy-Authorization
Proxy-Authorization請求頭域允許客戶端讓一代理能給客戶端自己(或客戶端的使用者)授權。Proxy-Authorization頭域值由包含使用者代理(為代理和/或請求資源域)的授權資訊的證書組成。
Proxy-Authorization = “Proxy-Authorization” “:” credentials
HTTP訪問授權過程在“HTTP Authentication: Basic and Digest Access Authentication”[43]中描述。不像Authorization頭域,Proxy-Authorization頭域只能應用於下一個期望利用Proxy-Authenticate頭域授權的外向(outbound)代理。。
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頭域,並且指定的範圍或多個範圍對實體來說是適合的:
-
如果在無條件GET請求裡出現Range頭域,那麼這將會改變沒有Range頭域時的GET請求返回的結果。換句話說,返回的狀態碼不是200(ok)而是206(部分響應)。
-
如果在條件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請求頭域允許伺服器為了個人興趣,記錄日誌,優化快取等來產生回退連結列表。它照樣允許伺服器為維護而跟蹤過時或寫錯的連結。Referer頭域不能被髮送如果請求URI從一個沒有自身URI的資源獲得,例如使用者從鍵盤輸入。
Referer = "Referer" ":" ( absoluteURI | relativeURI )
例如:
Referer: http://www.w3.org/hypertext/DataSources/Overview.html
如果Referer頭域的域值是相對URI,那麼它將被解析為相對於請求URI。URI不能包含一個片段(fragment)。見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
若響應是通過代理轉發的,則代理程式不得修改Server響應頭域。作為替代,它應該包含一個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)是否是可被客戶端接受的:
1.塊(chunked)傳輸編碼總是可以接受的。如果在TE頭域裡出現關鍵字“trailers”,那麼客戶端指明它願意代表自己或任意下游(downstream)客戶端去接受塊(chunked)傳輸編碼響應裡的尾部(trailer)。這意味著,如果“trailers”給定,客戶端正在宣告所有下游(downstream)客戶端願意接收塊(chunked)傳輸編碼響應裡的尾部(trailer),或宣告它願意代表下游接收端去嘗試快取響應。
注意:HTTP/1.1並沒有定義任何方法去限制塊傳輸編碼響應的大小,這是為了方便客戶端能快取整個響應。
2.只要是出現在TE頭域裡的傳輸編碼都是可被請求端接受的,除非此傳輸編碼跟隨的qvalue值為0(根據3.9節中定義,qvalue為0表明是“不可接受的”(not acceptable)))
3.如果在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頭域於一個101(切換協議)響應裡,用來指明哪個協議被切換了。
Upgrade = “Upgrade” “:” 1#product
例如,
Upgrade: HTTP/2.0,SHTTP/1.3, IRC/6.9, RTA/x11
Upgrade頭域的目的是為了提供一個從HTTP/1.1到其它不相容協議的簡單遷移機制。這通過允許客戶端告訴伺服器客戶端期望利用另一種協議,例如主版本號更高的最新HTTP協議,即使當前請求仍然使用HTTP/1.1。這能降低不相容協議之間遷移的難度,只需要客戶端以一個更普遍被支援協議發起一個請求,同時告訴伺服器客戶端想利用“更好的”協議如果可以的話(“更好的”由伺服器決定,可能根據方法和/或請求資源的性質決定)。
Upgrade頭域只能應用於應用程式層(application –layer)協議之間的切換,應用程式層協議在傳輸層(transport-layer)連線之上。Upgrade頭域並不意味著協議一定要改變;並且伺服器接受和使用是可選的。在協議改變後應用程式層(apllication-layer)的通訊能力和性質,完全依賴於新協議的選擇,儘管在改變協議後的第一個動作必須是對初始HTTP請求(包含Upgrade頭域)的響應。
Upgrade頭域只能應用於立即連線(immediate connection)。因此,upgrade關鍵字必須被提供在Connection頭域裡(見14.10節),只要Upgrade頭域呈現在HTTP/1.1訊息裡。
Upgrade頭域不能被用來指定切換到一個不同連線的協議。為這個目的,使用301,302,303重定向響應更合適。
這個規範定義了本協議的名字為“HTTP”,它在3.1節的HTTP版本規則中定義的超文字傳輸協議家族中被使用。任何一個標記都可被用來做協議名字,然而,只有當客戶端和伺服器認為這個名字對應同一協議才有用。
14.43 User-Agent
User-Agent請求頭域包含關於發起請求的使用者代理的資訊。這是為了統計,跟蹤協議違反的情況,和為了識別使用者代理從而為特定使用者代理自動定製響應。使用者代理應該包含User-Agent頭域在請求中。此頭域包含多個識別代理和子產品的產品標記(見3.8節)和解釋。通常,為了識別應用程式,產品標記按重要性排列。
User-Agent = "User-Agent" ":" 1*( product | comment )
例子:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
14.44 Vary
Vary響應頭域值指定了一些請求頭域,全部去決定某快取是否被允許去利用此響應(並且此響應仍然保鮮)去回覆後續請求而不需要重驗證(revalidation)。對於不可快取或已陳舊的響應,Vary頭域值用於告訴使用者代理(user agent)選擇表現形式(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常用頭域必須被閘道器(gateways)和代理(proxies)使用,用來指明在使用者代理和伺服器之間關於請求的中間協議和接收者,和在源伺服器和客戶端之間關於響應的中間協議和接收者。它和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 codes)的Warning頭域。然後,它必須新增這個驗證響應裡的任何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指明授權模式(schemes)和適用於請求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頭域成為可設定的選項。
用作穿過網路防火牆入口的代理應該特別小心防火牆後可以辨別主機資訊的頭域資訊被傳輸。特別是,代理應移除在防火牆之後產生的任何Via頭域。
Referer頭域允許被學習的讀模式和反向連結的跟蹤。雖然它非常有用,但也會被濫用如果使用者細節沒有從包含在Referer頭域裡資訊裡分離開來。即使當個人資訊已經被移除了,Referer頭域也可能指定私有文件的URI(不能被公開)。
From頭域裡的資訊可能會和使用者的私有興趣或他們站點的安全策略相沖突,因此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 fields),特別是如果這些接受頭域(accept header fileds)包含質量值,那麼應該被伺服器用作相對信賴和長久的使用者識別符號(user identifiers)。這樣的使用者識別符號將會允許內容提供者進行點選跟蹤以及允許合作內容提供者匹配跨伺服器點選跟蹤或者形成單個使用者窗體提交。注意對於許多並不在代理後面的使用者,執行使用者代理的主機的網路地址也將作為長久使用者的識別符號。在代理被用作增強隱私的環境裡,使用者代理應保守地提供接受(accept)頭域配置選項給終端使用者上。作為一種高度隱私的方式,使用者代理可能在接力的(relayed)的請求裡的過濾接受頭域。提供高度可配置性的使用者代理應警告使用者會有隱私的洩漏。
15.2 基於檔案和路徑名稱的攻擊
HTTP的源伺服器的實現應該限制HTTP請求返回的文件應是伺服器管理員有意圖的文件。如果HTTP伺服器要把HTTP URIs翻譯成檔案系統的呼叫,那麼伺服器必須小心去對待提供給HTTP客戶端的檔案傳輸。例如,UNIX,微軟Windows,和其他作業系統都利用“..”去指示當前的父目錄。對於這樣一個系統,一HTTP伺服器不允許任何這樣的構造(construct)在請求URI裡,如果這個構造能在通過HTTP伺服器訪問之外能訪問這個資源。同樣的,用作對伺服器內部引用的檔案(如訪問控制檔案,配置檔案,指令碼程式碼)必須受到保護而不讓其被不合適的獲取,因為他們可能包含敏感的資訊。經驗告訴我們一個在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地址改變時,他們就會被欺騙。因為網路地址的改變變得很平常,所以這種形式的攻擊在不斷增加。看到這個規則能減少潛在的安全攻擊的可能性。
此要求同樣能改進客戶端負載均衡(load-balancing)行為,因為重複的伺服器能利用同一個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協議來解決。在某些情形下,快取證書會干涉應用程式的安全模型,這些情形包含但不侷限於:
Ø 這樣的客戶端。此客戶端空閒已到達一定時間,伺服器可能希望再次使客戶端讓使用者出示證書。
Ø 這樣的應用程式。此應用程式包括了一個會話中斷指令(例如在一頁上有“退出”或者“提交”的按鈕),根據此指令,伺服器端“知道”不需要更多理為客戶端保留證書。
這是作為當前獨立研究的。有很多解決這個問題的社群,並且我們鼓勵在螢幕保護程式、空閒超時、和其他能減輕安全問題的方法裡利用密碼保護。特別是,能快取證書的使用者代理被鼓勵去提供一個容易的訪問控制機制,讓在使用者控制下丟棄快取的證書。
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,我們希望感謝他們發現了許多這篇文件正嘗試糾正的問題。
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
當一個HTTP 206(部分內容)響應資訊包含多個範圍的內容(請求響應的內容有多個非重疊的範圍),這些是作為一個多部分訊息主體來被傳送的。這種用途的媒體型別被稱作"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--
注意:
1)在實體(entity)中,在第一個分界字串之前可以有多餘的CRLFs。
2)雖然RFC 2046 [40]允許分界字串加引號,但是一些現有的實現會不正確的處理分界字串
3)許多瀏覽器和伺服器是按照位元組範圍標準的早期草案關於使用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訊息可以包含一個單獨的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]要求一網際網路郵件實體在被傳輸之前要被轉換成一個規範化的形式,這在RFC2049[48]裡第四章裡描述的。本文件的3.7.1節描述了當用HTTP協議傳輸時允許使用的“text”子媒體型別的形式。RFC2046要求型別為“text”的內容要用CRLF表示為換行符,以及在換行符外禁止使用CR或LF。
RFC 2046需要像在“text”型別的內容裡一樣,用CRLF表示行間隔符並禁止在行間隔符序列以外使用CR或者LF。HTTP允許CRLF,單個CR,和單個LF來表示一個換行符在一個文字內容訊息中。
在可能的地方,從HTTP到MIME嚴格環境的代理或閘道器應該把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).。(一些為網際網路郵件型別的Content-Type的實驗性應用有使用一個媒體型別引數“; conversions=
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節),這些要求是此規範裡最重要的改變。
舊的HTTP/1.0客戶端會認為IP地址和伺服器是一對一關係;沒有其它機制去區分IP地址和目標伺服器。上面的改變將允許網際網路,一旦舊客戶端不再普遍使用時,可以去支援一個IP地址對應多個web站點的情況,這大大簡化了大型的web執行伺服器,在那上面上分配多個IP地址給一個主機(host)會產生嚴重問題。網際網路照樣能恢復這樣一個IP地址,此IP地址作為特殊目的被分配給被用於根級(root-level)HTTP URLs的域名。給定web的增長速度和伺服器的部署數量,那麼所有HTTP實現(包括對已存HTTP/1.0應用程式)應該正確地滿足下面這些需求:
--客戶端和伺服器都必須支援Host請求頭域。
--傳送HTTP/1.1請求的客戶端必須傳送Host頭域。
--如果HTTP/1.1請求不包括Host請求頭域,伺服器必須報告錯誤400(Bad Request)。
--伺服器必須接受絕對URIs(absolute URIs)。
19.6.2和HTTP/1.0持久連線的相容
一些客戶端和伺服器可能希望和一些以前持久連線實現的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的形式(Connection: Keep-Alive 和 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 全部版權宣告
略…..