本內容摘抄自《RESTful WebServices》 中文譯本附錄C '常見的HTTP報頭'。
原文做者:Leonard Ricbardson & Sam Ruby
翻譯:徐涵、李紅軍、胡偉html
客戶端經過Accept報頭告訴服務器,它但願服務器採用什麼表示格式返回,有的客戶端也許指望JSON,有的也許指望xml。
對於web瀏覽器而言,把這一信息放在HTTP報頭裏是個不錯的主意,可是對於web服務客戶端而言,不該將此做爲惟一的解決方案。web
客戶端經過該報頭告訴服務器,它但願服務器爲表示採用什麼字符集。例若有些指望UTF-8。算法
客戶端經過該報頭告訴服務器,能夠經過compress或gzip這些衆所周知的壓縮算法對響應體進行壓縮,從而節省寬帶。它和字符集編碼無關。瀏覽器
客戶端能夠經過該報頭告訴服務器,它但願爲表示採用哪一種人類語言。緩存
服務器發送這個報頭,代表它支持部分HTTP GET(partial HTTP GET)。客戶端能夠先發送一個HEAD請求,以便獲取服務器返回的Accept-Ranges報頭,而後再發送包含Range報頭的GET請求,以獲取資源的部分表示。安全
假如響應主體不是服務器剛剛生成的,那麼能夠經過該報頭代表它在服務器上存在多久了。這個報頭一般由HTTP緩存來設置,以便讓客戶端知道它獲得的表示多是一箇舊的副本。服務器
用於響應OPTIONS請求,以告訴客戶端一個特定資源支持哪些HTTP方法。cookie
這個請求報頭包含認證證書,例如一個按特定認證方案進行編碼的用戶名和密碼。服務器收到包含Authorization報頭的請求後,將先解碼其中的證書,而後肯定是否執行該請求。
理論上人們只須要Authorization這一個認證報頭就夠了(Proxy-Authorization是一個例外,由於它在一個不一樣的層次上工做),由於它是可擴展的。可是在實踐中,仍有自定義認證報頭的狀況,好比說基於Authorization報頭的X-WSSE。HTTP基本認證和HTTP摘要認證是最多見的認證方案,不過只要客戶端和服務器雙方均能理解,採用任何方案均可以。編碼
此報頭用於給客戶端和服務器之間的緩存(包括客戶端和服務器自身的緩存)下達指示。它明確指出緩存的規則,以及什麼時候清除緩存。
例如:
Cache-Control:max-age=36000 緩存3600秒
Cache-Control:no-cache 禁用緩存
Cache-Control:private 只能被客戶單緩存不能被代理緩存加密
大多數HTTP響應是從服務器到客戶端的通訊。介於服務器與服務端之間的媒介(好比代理)可以查看響應,但它不以此爲主要目的。不過服務器能夠額外附加一些面向代理的特殊報頭,並且一個代理能夠附加一些面向下一個代理的特殊報頭。它們把這些特殊報頭的名稱寫在Connection報頭裏。這些特殊報頭是針對兩個機器間的TCP鏈接的,而不是針對服務器與客戶端間的HTTP鏈接的,代理應該在把響應轉發出去以前,先把其中的特殊報頭以及Connection報頭自己去掉。固然,若是它須要,能夠再附加一些新的特殊報頭和一個Connection報頭。若是你正在編寫客戶端,並且不許備使用代理,那麼你可能遇到的惟一一個Connection報頭的值是「close」。它的意思是,服務器將在處理好本次請求以後,把TCP鏈接關閉。
該報頭與Accept-Encoding請求報頭相對。表示服務器實際採用的是什麼壓縮算法。
該報頭與Accep-Language請求報頭相對。表示響應主體所採用的天然語言,它可能會列出多個語言。
此響應報頭給出實體主體的大小(以字節爲單位)。它有兩個重要用途:
一、客戶端能夠讀取這個報頭,併爲讀取主體實體作好準備。
二、客戶端能夠經過作一次HEAD請求來獲知實體主體的大小,而沒必要真實的請求實體主體。
它可能回影響到客戶端做出「是獲取整個表示,仍是部分表示,抑或不獲取表示」的決定。
此響應報頭把所請求資源的規範URI告訴客戶端。跟Location報頭不一樣的,Content-Location報頭徹底是信息性的,它並不要求客戶端使用新的URI。
當服務爲同一個資源的不一樣表示分配了不一樣的URIs時,該報頭會比較有用。好比說,假如客戶端想獲得一個資源的」與特定表示無關「的通用版本,那麼服務器就能夠把該通用版本的URI在Content-Location報頭中給出。因此,當你請求具備特定格式與語言的/releases/104.html.en時,服務器會在響應裏把Content-Location報頭的值設爲/releases/104。
這是實體主體的加密校驗和。客戶端能夠用它來檢查實體主體有沒有在傳送過程當中被損壞。因爲攻擊者能夠同時篡改實體主體和Content-MD5報頭,因此這個報頭不是用於安全性目的,而只是用做錯誤檢測的。
當客戶端用Range請求報頭作部分GET請求時,服務器經過此響應報頭告訴客戶端它正在獲取哪部分表示。
毫無疑問,這是最爲著名的響應報頭。這個響應報頭告訴客戶端實體主體是什麼媒體類型。
做爲請求報頭,它表示客戶端發送請求的時間。做爲響應報頭,它表示服務器完成請求的時間。做爲響應報頭時,Date報頭被緩存所使用。
ETag的值是一個不透明的字符串,它用於指示一個表示的特定版本。若表示發生改變,ETag也應隨之改變。應儘可能爲GET請求的響應提供此報頭。客戶端未來進行條件GET時,須要用到ETag報頭的值,客戶端在作條件GET請求時,把ETag報頭的值放在If-None-Match請求報頭裏,服務器能夠經過If-None-Match請求報頭的值判斷客戶端保存的表示是否是最新的,若是是最新的,服務器就沒必要重複發送表示,以節省時間和寬帶。
條件GET請求主要是靠Last-Modified響應報頭及與之相對的If-Modified-Since請求報頭實現的。ETag的主要目的是提供雙重保險。由於假如一個表示在一秒鐘內改變兩次的話,靠Last-Modified-Since是反映不出這個變化的,但ETag能夠。
這個報頭用於LBYL請求。若服務器返回響應代碼100,那麼客戶端能夠繼續發送真正的請求。若服務器返回響應代碼417,那麼客戶端應該放棄發送真正的請求。
這個報頭告訴客戶端(或介於服務器與客戶端之間的代理),能夠在一段時間內對響應(整個響應,而不只僅是實體主體)進行緩存。條件HTTP GET須要作一次HTTP鏈接,
並花費必定的時間與資源。而Expires使客戶端能夠根本不用發送任何HTTP請求--至少在一段時間內。
這個報頭跟電子郵件裏的From字段的做用相似。它給出請求發送者的一個Email地址。因爲隱私緣由,這個報頭在human web上根本不被採用,而在「客戶端不在人類用戶直接控制下「的程序上就更不用說了。你也許能夠將它做爲User-Agent的一個擴展。
此報頭包含URI的域名部分。好比url爲:http://www.example.com/page.html,則URI路徑是:/page.html, Host報頭的值是:「www.example.com「或者」www.example.com:80「。
從客戶端角度來看,可能沒法理解爲何須要提供這樣一個報頭。因爲HTTP 1.1服務器能夠在一個IP地址上支持任意個域名,因此這個報頭是必需的。
這一特性叫作「基於域名的虛擬主機」,它使得擁有多個域名的人沒必要爲每一個域名單獨購買獨立的計算機與網卡。問題是,HTTP客戶端是向IP地址(而不是域名)發送請求的。因此若是沒有Host報頭,服務器就沒法得知客戶端請求的目標是哪一個虛擬主機。
咱們能夠用其餘報頭來間接描述這個報頭。它跟If-Unmodified-Since同樣,用於給除GET之外的HTTP動做設置條件。指示If-Unmodified-Since以時間爲值,而If-Match以ETag爲值。
簡而言之:If-Match跟If-None-Match與ETag的關係,就如同If-Unmodified-Since跟If-Modified-Since與Last-Modified的關係同樣。
這個請求報頭是支持條件HTTP GET的關鍵。客戶端把經過一次對同一URI的請求獲得的Last-Modified的響應報頭的值,放在本次請求的If-Modified-Since報頭裏。服務器能夠根據比較If-Modified-Since的值與資源的最後更新日期,判斷來自客戶端上次請求以來資源有沒有發生過改變。若資源已發生改變。也就是說條件If-Modified-Since成立,那麼服務器將把新的實體主體返回客戶端。若資源沒有發生改變,也就是說條件If-Modified-Since不成立,那麼服務器將返回響應代碼304且不發送實體主體。
因爲Last-Modified只能精確到1秒,全部有時僅靠If-Modified-Since會出現錯誤的結果。這就是爲何引入ETag與If-None-Match的緣由。
這個報頭也用於支持條件HTTP GET。客戶端把經過前一次對同一URI請求獲得的ETag響應報頭的值,放在本次請求的If-None-Match報頭裏。若ETag自上次請求以來發生變化,
則條件If-None-Match成立,服務器把新的實體主體返回給客戶端。若ETag跟以前的同樣,則條件不成立,服務器返回響應代碼304,且不發送實體主體。
此報頭用於支持條件部分GET。 客戶端把經過前一次請求獲得的ETag或Last-Modified響應報頭的值,放在本次請求的If-Range報頭裏。假如客戶端請求的那部分表示已經變化,那麼服務器就返回新的範圍。不然,服務器就返回響應代碼304,即使表示的其餘地方發生了改變。
正常狀況下,客戶端把Last-Modified響應報頭的值做爲If-Modified-Since請求報頭的值,以進行條件GET。這個報頭也採用Last-Modified響應報頭的值,但它經常使用於給除GET之外的HTTP動做施加條件。
舉個例子:包括你在內的不少人都想修改某個資源。你獲取該資源的表示,修改它,而後再用PUT請求把它發回去。但假如在發送PUT請求以前,該資源恰好被其餘人修改了,
那麼要麼獲得409,要麼用你的修改把別人的修改覆蓋掉。
若發送上述PUT請求時經過If-Unmodified-Since施加條件,那麼若是其餘人修改了該資源的話,你將獲得響應代碼417。你能夠從新獲取表示,而後修改。
該報頭也可用於GET請求。
此報頭用於支持條件HTTP GET。它把表示的最後修改時間告訴客戶端。客戶端能夠保存這個值,並在未來發送請求時給If-Modified-Since請求報頭設置這個值。
在web應用中,Last-Modified一般取當前時間,這使得條件HTTP GET沒法發揮做用。web服務器應力圖作的更好一些,由於web服務器客戶端常會爲同一URI反覆請求服務器。
這是一個多功能的通用報頭。它跟3XX系列(重定向)響應代碼關係密切,並且不少關於HTTP重定向的混亂都源自對這個報頭的錯誤理解。
這個報頭告訴客戶端應該向哪一個URI請求資源,假定客戶端原先不知道。也許,客戶端的請求致使該資源被建立或致使該資源的URI發生變化。也許,客戶端使用的是一個資源的舊URI,雖然該URI已不對應任何資源,但服務器還認識它。在這種狀況下,響應代碼能夠是301,也能夠是307或302。
有時,Location報頭只是給出一個默認URI,好比用於300響應。有時,Location報頭的URI不是指向客戶端試圖訪問的資源,而是指向某個其餘提供補充信息的資源,好比用於303響應。
這個報頭主要跟TRACE方法配合使用。TRACE方法用於追蹤處理客戶端HTTP請求的代理。
此報頭用於在客戶端、服務器及媒介(如代理)間傳達特殊指令。惟一一個官方指定是「no-cache」。不過它在HTTP 1.1中已經不使用了。能夠經過Cache-Control報頭設置爲「no-cache」起到一樣的做用。
有些客戶端只能經過代理服務器來訪問外部web,有些代理服務器須要認證。這個報頭就是代理服務器提出認證要求的一種方式。這個報頭隨響應代碼407一塊兒發送。它有跟WWW-Authenticate同樣的工做方式,只不過Proxy-Authenticate是代理提出認證要求,而WWW-Authenticate是web服務器提出認證要求,Proxy-Authenticate響應報頭跟Proxy-Authorization請求報頭相對,而WWW-Authenticate跟Authrization請求報頭相對。一個請求可能須要同時提供Authorization和Proxy-Authorization報頭。
此報頭用於經過一個要求認證的代理來發送請求。它和Authorization的工做方式相似。該報頭的格式依賴於Proxy-Authenticate。
這個報頭代表客戶端試圖請求一個資源的部分表示。客戶端發送這個報頭,通常是由於以前在下載一個大型表示的過程當中中斷了,如今,它回來繼續下載該表示的其他部分。
此報頭一般跟If-Unmodified-Since報頭一塊兒使用。假如表示自從上次請求以後發生了改變,你極可能須要從新獲取整個表示。
當在web瀏覽器裏點擊一個連接時,瀏覽器將發出一個HTTP請求,而此請求的Referer報頭的值就是剛剛所處那個頁面的URI。
這個報頭一般與表明失敗的響應報頭一塊兒使用,好比說413或某個5XX響應代碼。它告訴客戶端:雖然服務器目前沒法處理你的請求,但也許一段時間以後就能夠了。這個報頭的值是一個時間或秒數,客戶端能夠在這個時間或秒數以後重試。
若服務器爲每個Retry-After報頭按一樣的規則來設置值得話,這隻能使各個請求按原來的次序一一遲點到來--客戶端仍將一遍遍地重複收到Retry-After報頭。服務器應該採起某種隨機機制來改變Retry-After報頭,就像以太網的衝突回退週期同樣。
這個另外一個「Accept」型報頭。客戶端經過這個報頭指定它將接受的傳送編碼。
在實際使用中,TE只被用於傳達「客戶端是否理解分塊編碼(chunked encoding)與HTTP報尾」這一信息。
當服務器採用分塊傳輸編碼(chunked transfer encoding)來發送實體主體時。它能夠在實體主體的最後附加一些HTTP報頭,使它們由報頭成爲「報尾」。服務器再把報頭做爲報尾發送時,須要把這些報頭的名稱列在Trailer報頭裏。
例如:Trailer:Content-Length
在服務器傳送完實體主體後,它會在實體主體以後附加一個Content-Length報尾,並給出實體主體的字節數。
有時,服務器須要在尚不瞭解實體主體的某些重要方面的狀況下發送該實體主體。服務器能夠一塊一塊地傳送該實體主體,並把Content-Length等報頭放在實體主體以後。待全部塊都傳送結束後,服務器即可知道先前所不知道的一些信息了,它還能夠把這些信息(如Content-Length和Content-MD5)做爲「報尾」發送給客戶端。
若是客戶端但願使用除HTTP之外的另外一種協議,它能夠經過Upgrade報頭通知服務器。若服務器恰好支持哪一個協議,它將返回響應代碼101,並當即切換到新的協議。
本報頭的值不存在標準格式,但RFC2616裏的Upgrade報頭示例反映了HTTP設計者的一些構想:
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/X11
服務器能夠經過這個報頭知道發送請求的是在哪一種客戶端軟件。在humen web上,這是一個表示web瀏覽器品牌的字符串。而在programmable web上,它一般標識用來編寫
客戶端的HTTP庫或者客戶端庫。
在human web 流行起來不久,服務器就開始經過User-Agent來了解對方是哪種瀏覽器了,服務器會爲不一樣的瀏覽器返回不一樣的表示。但根據User-Agent來發送不一樣的表示是一個槽糕的作法。檢測User-Agent不但已經形成各類web瀏覽器之間的不兼容,還致使了User-Agent報頭內部競爭。
幾乎如今全部的瀏覽器都冒充Mozilla,由於它是第一個流行的web瀏覽器的內部代碼名稱。若不冒充爲Mozilla,瀏覽器可能得不到它想要的表示。由的瀏覽器不但冒充Mozilla,還冒充MSIE,以便可以得到針對目前最流行的web瀏覽器(IE)的表示,少數瀏覽器甚至容許用戶自行選擇User-Agent,以欺騙服務器發送響應的表示。
不要讓這種狀況發生,web服務應該只經過User-Agent來收集統計數據並拒絕實現不佳的客戶端的訪問,而不該利用User-Agent來返回不一樣的表示。
此報頭用於告訴客戶端,它能夠修改哪些請求報頭以獲得一個資源的不一樣表示。如:Vary: Accept Accept-Language
該報頭的另外一個做用是告訴緩存服務器「請把資源的日文與英文表示區分開緩存」。若Vary報頭的值爲「*」,則代表響應不該被緩存。
在一個HTTP請求直接從客戶端發往服務器、或一個響應直接從服務器發往客戶端時,是沒有Via報頭的,當途中存在媒介(如代理)時,每一個代理都會在請求或響應消息上附加一個Via報頭,這樣,收到該消息的接收者就能夠經過查看Via報頭來了解該HTTP消息通過了哪些媒介。
Warning報頭是HTTP響應代碼的補充。媒介(如緩存代理)經過插入這個報頭,以告訴客戶端可能存在的,不可能從響應中明顯看出的問題。
跟響應代碼同樣,每一個HTTP Warning報頭都有一個3位數的值 -- 「警告代碼」。絕大多數警告跟緩存行爲有關。如:
Warning:110 localhost:9090 Response is statle
意思是說:位於localhost:9090的緩存代理髮送的是一個緩存的響應,雖然它知道該響應已通過期了。
這個響應代碼是配合響應代碼401使用的。服務器經過這個報頭通知客戶端,它要求客戶端從新請求該URI並提供認證信息。它同時告訴客戶端服務器指望採用何種認證方案。
例如:HTTP 基本認證,HTTP摘要認證,或者Digest auth或WSSE。
這多是第二著名的HTTP報頭,可是它不屬於HTTP標準的一部分,他是Netscape的一個擴展。
cookie是客戶端與服務器之間的一個約定,即服務器經過Set-Cookie報頭在客戶單保存一些半持久化的狀態。每當客戶端獲得一個cookie,它就應該在其後的每個HTTP請求中附上這個cookie。客戶端正是經過Cookie報頭來傳送它的全部cookie的。由於這些經過HTTP報頭傳送的數據不可見,隨意彷彿客戶端與服務器在共享一些狀態。
在REST環境中,cookie的名聲並很差,緣由有兩個,首先,它們包含「狀態」經常只是一個回話ID(seesionId),它破壞了無狀態性原則。第二,每當客戶端接受一個cookie,它就要爲其後的每一個請求都附上該cookie,這就意味着,客戶端不能再發送以前那些不包含cookie的請求,這也違反了無狀態性原則。
若是你必須使用cookie,那麼請確保你在客戶端保存全部狀態。不然REST的可伸縮性優勢將大打折扣。
服務器經過這個報頭試圖在客戶端的cookie中保存一些半持久化的狀態。客戶端應該爲其後的每一請求都附帶上這個cookie,直至該cookie過時。客戶端能夠忽略此報頭,不爲其後的請求設置Cookie報頭,但這樣作有可能得不到正確的響應。
Slug報頭是Atom發佈協議(Atom Publishing Protocol, APP)定義的,客戶端在向一個集合POST二進制文檔時,經過Slug報頭爲這個二進制文檔設置標題。
自定義報頭是最多見的一種擴展HTTP的方式,只要客戶端與服務器就報頭的含義達成一致,就能夠隨請求或響應發送任何但願發送的信息。
指導原則以下: