本文檔規定了互聯網社區的標準組協議,並須要討論和建議以便更加完善。請參考
「互聯網官方協議標準」(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」。
*規則
前面的字符「*」表示重複。完整的形式是「<n>*<m>元素」,表示元素至少出現<n>次,至多出現<m>次。默認值是0和無窮大,因此"*(元素)"容許任何數值,包括零;"1*元素"至少出現一次;"1*2element"容許出現一次或兩次。
[規則]
方括號裏是任選元素;「[foo bar]」至關於「*1(foo bar)」。
N 規則
特殊的重複:「<n>(元素)」與「<n>*<n>(元素)」等價;就是說,(元素)正好出現<n>次。這樣2DIGIT是一個兩位數字,3ALPHA是一個由三個字符組成的字符串。
#規則
相似於「*」,結構「#」是用來定義一系列元素的。完整的形式是<n>#<m>元素,表示至少<n>個元素,至多<m>個元素,元素之間被一個或多個逗號(「,」)以及可選的線性空白(LWS)隔開了。這就使得表示列表這樣的形式變得很是容易;像
(*LWS element *(*LWS ","*LWS element))
就能夠表示爲
1#element
不管在哪裏使用這個結構,空元素都是容許的,可是不計入元素出現的次數。換句話說 ,
「(element ), , (element) 」是容許的,可是僅僅視爲兩個元素。所以,在至少須要一個元素的地方,必須存在至少一個非空元素。默認值是0和無窮大,這樣,「#element」容許任意零個或多個元素;「1# element」須要至少一個;「1#2element」容許一個或兩個元素。
註釋(comment)
用分號引導註釋。
隱含的*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使用一個「<major>.<minor>」數字模式來指明協議的版本號。爲了進一步的理解HTTP通訊,協議的版本號指示了發送端指明消息的格式和能力,而不只僅是經過雙方通訊而得到的通訊特性。當消息元素的增長不會影響通訊行爲或擴展了域值時,協議版本是不須要修改的。當協議會由於添加一些特徵而作了修改時,<minor>數字就會遞增。這些修改不會影響一般的消息解析算法,但它會給消息添加額外的語意(semantic)而且會暗示發送者具備額外的能力。協議的消息格式發生變化時,<major>數字就會增長。
HTTP消息的版本在HTTP-Version域被指明,HTTP-Version域在消息的第一行中。
HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
注意major和minor數字必須被當作兩個獨立整數,每一個整數均可以遞增,而且能夠增大到大於一位數的整數,如HTTP/2.4比HTTP/2.13低,而HTTP/2.4又比HTTP/12.3低。前導0必須被接收者忽略而且不能被髮送者發送。
一個應用程序若是發送或響應消息裏的包含HTTP-Version爲「HTTP/1.1」的消息,那麼此應用程序必須至少條件遵循此協議規範。最少條件遵循此規範的應用程序應該把「HTTP/1.1」包含在他們的消息的HTTP-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中描述了。此響應應該包含一個實體,此實體描述了爲何此協議版本不被支持和其餘能被服務器支持的協議版本html