繼上篇講了HTTP協議的基礎以後,本篇重點介紹一下HTTP經常使用的Header。html
HTTP Header很是之多,不多有人能徹底分清這些Header究竟是幹什麼的。鑑於RFC文件規範艱深晦澀難懂,本文對協議規範中列出的HTTP Header進行了梳理,用通俗的語言進行表達,便於讀者吃透HTTP協議。前端
做者在閱讀RFC文檔的時候發現了不少之前沒注意到的知識,估計作web開發的小夥伴們也大多忽視了這些知識,閱讀文本會給大家帶來不少意外的驚喜。nginx
免責聲明:若是下面有那句話有不對的地方,還請噴少點口水。web
表示客戶端指望服務器返回的媒體格式。客戶端指望的資源類型服務器可能沒有,因此客戶端會指望多種類型,而且設置優先級,服務器根據優先級尋找相應的資源返回給客戶端。算法
# 注意:先逗號分割類型,再分號分割屬性
Accept: audio/*; q=0.2, audio/basic
複製代碼
表示audio/basic類型的資源優先,若是沒有,就隨便其它什麼格式的audio資源均可以。q的取值範圍是(0-1],其具體值並無意義,它僅用來排序優先級,若是沒有q,默認q=1,也就是最高優先級。瀏覽器
表示客戶端指望服務器返回的內容的編碼格式。它同Accept頭同樣,也能夠指定多個編碼,以q值表明優先級。緩存
# 注意:先逗號分割類型,再分號分割屬性
Accept-Charset: utf8, gbk; q=0.6
複製代碼
表示utf8編碼優先,若是不行,就拿gbk編碼返回.安全
Content-Type是服務器向客戶端發送的頭,表明內容的媒體類型和編碼格式,是對Accept頭和Accept-Charset頭的統一應答。bash
Content-Type: text/html; charset=utf8
複製代碼
表示返回的Body是個html文本,編碼爲utf8服務器
表示客戶端指望服務器返回的內容的語言。不少大型互聯網公司是全球化的,它的技術文檔通常有有多種語言,經過這個字段能夠實現文檔的本地化,對國內用戶呈現簡體中文文檔,對英語系用戶呈現英文文檔。
Accept-Language:zh-CN,en-US;q=0.8,zh-TW;q=0.6
複製代碼
表示大陸簡體中文優先,其次英語,再其次臺灣繁體中文
這個頭字段內容是對Accept-Language的應答。服務器經過此字段告知客戶端返回的Body信息的語言是什麼。
表示傳輸的請求/響應的Body的長度。GET請求由於沒有Body,因此不須要這個頭。攜帶Body的而且能夠提早知道Body長度的請求/響應必須帶上這個字段,以便對方能夠方便的分辨出報文的邊界,也就是Body數據什麼時候結束。若是Body太大,須要邊計算邊傳輸,不到最後計算結束是沒法知道整個Body大小的,這個時候可使用http分塊傳輸,這個時候也是不須要Content-Length字段的。
當客戶端請求的資源在服務器有多個地址時,服務器能夠經過Content-Location字段告知客戶端其它的可選地址。這個字段比較少見。
在Header中提供這個信息是用來作Body內容校驗。它表示Body信息被md5算法處理後的base64字符串。這個字段也比較少見。由於校驗機制在TCP層已經有實現了,再來一層校驗並無多大意義。另外資源的md5值每每用來放在後面的ETag頭信息中做爲資源的惟一標識來使用。
若是服務器沒有緩存,那麼Date就是響應的即時生成時間。若是服務器設有緩存,那麼Date就是響應內容被緩存的時間。它必須符合規範裏定義的特定格式,這種格式叫着HTTP-Date,不支持隨意定義本身的時間格式。
Date: Tue, 15 Nov 1994 08:12:31 GMT
複製代碼
表示資源緩存的年齡,也就是資源自緩存以來到如今已通過去了多少時間,單位是秒。
Age: 86400
複製代碼
服務器使用Expect頭來告知對方資源什麼時候失效。若是它的值等於Date頭的值,就表示資源已經實效。
Expires: Thu, 01 Dec 1994 16:00:00 GMT
複製代碼
資源標籤,每一個資源能夠提供多個標籤信息。它通常用來和下面的If-Match和If-None-Match配合使用,用來判斷緩存資源的有效性。比較常見的標籤是資源的版本號,好比能夠拿資源數據的md5校驗碼做爲版本號。
If-Match的值通常是上面提到的ETag的值,它經常使用於HTTP的樂觀鎖。所謂HTTP樂觀鎖,是指客戶端先GET這個資源獲得ETag中的版本號,而後發起一個資源修改請求PUT|PATCH時經過If-Match頭來指定資源的版本號,若是服務器資源知足If-Match中指定的版本號,請求就會被執行。若是不知足,說明資源被併發修改了,就須要返回狀態碼爲412 Precondition failed 的錯誤。客戶端能夠選擇放棄或者重試整個過程。
相似於If-Match,只是條件相反。
表示資源支持訪問的HTTP Method類型。它是服務器對客戶端的建議,告知對方請使用Allow中提到的Method來訪問資源。
Allow: GET, HEAD, PUT
複製代碼
當客戶端和服務器須要協商鏈接的屬性時,可使用Connection頭部。比較經常使用的一個值是close,用來通知對方在當前請求結束後關閉鏈接。
Connection: close
複製代碼
用於請求發送以前向服務器詢問許可。譬如要向服務器發送一個很大的文件而不肯定是否超出限制,就能夠在請求頭裏攜帶一個Expect頭部
Expect: 100-continue
複製代碼
若是服務器說不行,就會返回417 Expectation Failed錯誤告知客戶端放棄。若是能夠那就返回100 continue狀態碼告知客戶端放馬過來吧,因而客戶端就會繼續上傳Body內容。若是服務器提早收到Body內容就會放棄返回100 continue響應。
該字段通常用來標記請求發起者的郵件地址,至關於給請求賦予一個責任人。若是服務器發現請求存在問題,就會經過此字段聯繫到發起人進行處理。由於郵件地址涉及到隱私信息,因此請求攜帶From頭須要徵得用戶的贊成。RFC協議建議全部的機器人代理髮起的請求應該攜帶此頭部,以避免遇到問題時能夠找到責任人。不過若是是惡意的機器人,估計這樣的建議也只是耳邊風而已。
RFC協議規定全部的HTTP請求必須攜帶Host頭,即便Host沒有值,也必須帶上這個Host頭附加一個空串,若是不知足,應用服務器應該拋出400 Bad Request。協議雖然這樣規定,不過大部分網關或者服務器都比較仁慈,既然沒有指定Host字段,那就給你默認加上一個。 網關代理能夠根據不一樣的Host值轉發到不一樣的upstream服務節點,它經常使用於虛擬主機服務業務。
標記資源的最近修改時間,它和Date比較相似,區別是Last-Modified表明修改時間,而Date是建立時間。
瀏覽器向服務器請求靜態資源時,若是瀏覽器本地已經有了緩存,就會攜帶If-Modified-Since頭,值爲資源的Last-Modified時間,詢問服務器該資源自從這個Last-Modified時間以後有沒有被修改。若是沒有修改過,就會向瀏覽器返回304 Not Modified通知瀏覽器能夠放心使用緩存內的資源。若是資源修改過,那就像正常的GET請求同樣,攜帶資源的內容返回200 OK。
相似於If-Modified-Since,意義相反。區別是當服務器資源條件不知足時,不是返回304 Not Modified,而是返回412 Precondition Failed。
支持斷點續傳的服務器必須處理Range頭,它表示客戶端請求資源的一部分時指定的請求字節範圍。它是客戶端向服務器發送的請求頭。
Range: bytes=500-999
複製代碼
針對上面的Range頭,服務器響應客戶端時也需提供相應的Content-Range頭,表示傳輸的Body數據在總體資源塊中的字節範圍。好比下面的例子表示該資源總共有47022字節,當前響應的內容是21010-47021字節之間的內容。
Content-Range: bytes 21010-47021/47022
複製代碼
之因此是47021而不是47022是由於offset是以0開始的,47021就是最後一個字節。
在斷點續傳時,爲確保連續2個請求之間服務器資源自己沒有發生變化,須要If-Range頭帶上ETag的資源版本號。服務器資源根據這個版本號來斷定資源是否改變了。若是沒變,就返回206 Partial Content將部分資源返回。若是資源變了,那就至關於一個普通的GET請求,返回200 OK和整個資源內容。
服務器向客戶端發送302跳轉的時候,總會攜帶Location頭信息,它的值爲目標URL。
HTTP/1.1 302 Temporary Redirect
Location: https://www-temp.example.org/
複製代碼
用來限定網關或者代理的層數,也就是最大轉發次數。HTTP每通過一個網關或者代理層,Max-Forwards值就要減1。若是nginx接收到前端請求的時候Max-Forwards已經等於0,那麼它就不該該再將請求轉發到upstream指定的服務節點上。
這個頭是比較常見的,在前端開發模式下常常會加上這個頭部。
Pragma: no-cache
複製代碼
當網關收到一個帶有這樣請求的頭部時,即便內部存在該請求資源的緩存而且有效也不能夠直接發送給客戶端,而必須轉發給後面的upstream進行處理。 不過若是真的全部的網關都遵循這個協議的話,攻擊是很容易構造的,因此它通常僅用於開發模式,防止靜態資源修改後前端得不到即時更新。其它值的pragma值沒有遇到過。
Referer是很是經常使用的頭,它表示請求的發起來源URI,也就是當前頁面資源的父頁面。若是你從A頁面跳轉到B頁面,那麼請求B頁面的請求頭裏面就會有Referer信息,它的值就是A頁面的訪問地址。經過追蹤Referer,可得出資源頁面之間複雜的跳轉鏈,它很是適合用於網頁的數據分析和路徑優化。
服務器升級時,來自客戶端的請求會直接給予503(Service Unavailable)錯誤,經過在返回頭裏面加入Retry-After字段告知客戶端什麼時候服務能夠恢復正常訪問。Retry-After的頭能夠是HTTP-Date,也能夠是整數,表示多少秒後服務能夠恢復正常訪問。瀏覽器在拿到這個值以後能夠考慮增長一個定時器在將來的某個時間進行重試。
用於返回服務器相關的軟件信息,來告知客戶端當前的HTTP服務是由某某軟件提供的,能夠當作是一種軟件廣告。 RFC協議裏對這個頭信息作了警告:暴露出服務器信息可能會致使黑客更易於攻擊你的服務,建議謹慎使用。
攜帶當前的用戶代理信息,通常包含瀏覽器、瀏覽器內核和操做系統的版本型號信息。它和Server頭是對應的,一個是表達服務器信息,一個是表達客戶端信息。服務器能夠根據用戶代理信息統計出網頁服務的瀏覽器、操做系統的使用佔比狀況,服務器也能夠根據UA的信息來定製不同的內容。
傳送Body信息時須要對Body數據採起何種變換。當HTTP對Body進行分塊傳送時,須要增長下面的頭部信息才能夠進行分塊傳送。其它類型目前沒有遇到過。
Transfer-Encoding: chunked
複製代碼
服務器建議客戶端升級傳輸協議。好比當客戶端使用HTTP/1.0發送請求時,服務器就能夠建議客戶端升級到HTTP/1.1。 這個時候就可使用Upgrade頭。客戶端收到這個Upgrade後就會將後續請求轉成HTTP/1.1格式繼續進行交流。能夠支持多個參數,使用逗號分割便可。
Upgrade: HTTP/1.1
複製代碼
當客戶端要和服務器進行Websocket進行通信時,在握手階段服務器也會向客戶端發送Upgrade頭部信息,提示客戶端將協議切換到Websocket。
Upgrade: WebSocket
複製代碼
該頭部用於緩存控制。對於一些緩存服務器,咱們在請求里加入Vary參數能夠告知緩存服務器對不一樣的Vary參數的響應使用不一樣的緩存單元。好比Vary參數裏放入編碼參數,那麼不一樣編碼的網頁就會有不一樣的緩存。Vary的值能夠有多個,只要任意一個值不同就會有不一樣的緩存。 好比下面的這個例子告知緩存服務器對不一樣語言和不一樣編碼的網頁響應使用不一樣的緩存單元。
Vary: Accept-Encoding,Accept-Language
複製代碼
該字段用來標識一個請求通過的網關路由節點。若是這個請求通過了多個代理層,Via頭部就會有多個網關信息。
用於在響應中添加一些附加的警告信息,警告信息包含一個錯誤碼和錯誤說明。通用的一些錯誤碼在RFC協議中有具體規定。好比111號錯誤碼錶示緩存服務器的緩存項目已通過期,而且嘗試reload資源,可是reload失敗了,因此只好返回了舊的已通過期的內容,這個時候就須要經過warning頭反饋客戶端。
Warning: 111 Revalidation failed
複製代碼
WWW-Authenticate是401 Unauthorized錯誤碼返回時必須攜帶的頭,該頭會攜帶一個問題Challenge給客戶端,告知客戶端須要攜帶這個問題的答案來請求服務器才能夠繼續訪問目標資源。這種問題Challenge能夠自定義,比較常見的是Basic認證。
WWW-Authenticate: Basic realm=xxx
複製代碼
Basic指代base64加密算法(不安全),realm指代認證範圍/場合/情景名稱。
對於某些須要特殊權限才能訪問的資源須要客戶端在請求裏提供用戶名密碼的認證信息。它是對WWW-Authenticate的應答。
# value = base64(user_name:password)
Authorization: Basic YWRtaW46YWRtaW4xMjM=
複製代碼
同WWW-Authorization頭部,用於代理服務器認證。
同Authorization頭部,用於代理服務器認證。
ETag通常攜帶的是資源的版本號,協議沒有具體規定版本號是什麼。它能夠是資源的md5校驗碼,也能夠是uuid,甚至能夠是自增的數字,也能夠是資源的修改時間。它的匹配方式是相等/不相等。由於服務器須要維護版本號,取決的版本號是什麼,這多是一個存儲和計算的負擔。
Last-Modified攜帶的資源的修改時間。它的匹配方式是大於/小於。若是是靜態資源文件,通常就是操做系統記錄的文件修改時間。
Expires是服務器告知客戶端資源的過時時間。客戶端緩存的資源在這個時間以後自動過時,而不須要非得向服務器確認一下是否是304 Not Modified才認爲沒過時。
這多是HTTP頭裏面最複雜的一個頭了。這個頭既能夠用於請求,也能夠用於響應。在請求和響應的取值不同,分別表明了不一樣的意思。
由於HTTP協議細節很是繁多,以上文字並不能徹底將HTTP的全部的頭部細節都講清楚。後續【碼洞】會繼續更新更加精細的文章,建議讀者關注公衆號【碼洞】第一時間看到相關文章。