本文為《三萬(wàn)長(zhǎng)文50+趣圖帶你領(lǐng)悟web編程的內(nèi)功心法》第三個(gè)章節(jié)。
3、HTTP/1.1報(bào)文詳解
在RFC2616中心詳細(xì)的描述了HTTP/1.1[1]的報(bào)文,感興趣的朋友也可以前往閱讀。
HTTP是基于TCP的,HTTP作為應(yīng)用層協(xié)議,會(huì)在TCP/IP協(xié)議棧往下傳遞的時(shí)候,不斷封裝數(shù)據(jù)幀,如下圖:
上面HTTP正文即是以我們HTTP報(bào)文格式來(lái)組織的。下面我們看看具體的HTTP報(bào)文的格式。
3.1、HTTP報(bào)文組成部分
HTTP請(qǐng)求和響應(yīng)都使用如下通用的格式:
-
start-line
:起始行,起始行可以為以下兩者之一:-
Request-Line
:請(qǐng)求行,如:GET /hello-world2.html HTTP/1.1
-
Status-Line
:狀態(tài)行,如:HTTP/1.1 200 OK
-
*(message-header CRLF)
:0個(gè)或者多個(gè)消息頭
;CRLF
:一個(gè)空行;[message-body]
:可選的消息體;
可以分別把請(qǐng)求報(bào)文和響應(yīng)報(bào)文分開(kāi)來(lái)描述:
請(qǐng)求報(bào)文
響應(yīng)報(bào)文
可以發(fā)現(xiàn),請(qǐng)求報(bào)文和響應(yīng)報(bào)文格式就起始行不一樣。
下面我們逐個(gè)來(lái)介紹。
為了盡可能保證內(nèi)容的準(zhǔn)確性,下面報(bào)文各種字段說(shuō)明部分內(nèi)容,大部分整理自RFC2616和MDN web docs:
- Hypertext Transfer Protocol -- HTTP/1.1 2616[1]
- HTTP. MDN web docs[2]
- 《HTTP權(quán)威指南》
以上資料內(nèi)容有沖突的,以RFC2616的為準(zhǔn)。
3.2、請(qǐng)求行
請(qǐng)求行格式:
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
3.2.1、Method
方法是區(qū)分大消息的,以下是常用的方法:
方法 | 說(shuō)明 |
---|---|
OPTIONS | 列出可以對(duì)服務(wù)器資源執(zhí)行哪些方法 |
GET | 獲取資源 |
HEAD | 獲取資源的首部,與GET類(lèi)似,但是不會(huì)響應(yīng)消息體 |
POST | 向服務(wù)器提交數(shù)據(jù) |
PUT | 將請(qǐng)求主體部分存儲(chǔ)在服務(wù)器上 |
DELETE | 刪除資源 |
TRACE | 對(duì)可能經(jīng)過(guò)代理服務(wù)器傳送到服務(wù)器上的報(bào)文進(jìn)行追蹤 |
CONNECT | 建立連接隧道 |
extension-method | 擴(kuò)展方法 |
另外,服務(wù)器還可以實(shí)現(xiàn)一些自己的請(qǐng)求方法,這些附加的方法是對(duì)HTTP規(guī)范的擴(kuò)展,因此也成為擴(kuò)展方法。
extension-method = token
請(qǐng)求可能的返回結(jié)果:
-
405:表示請(qǐng)求的方法不被允許,這個(gè)時(shí)候服務(wù)器響應(yīng)頭會(huì)響應(yīng)當(dāng)前資源允許的方法,如:
Allow: GET, HEAD, PUT
501:代表原服務(wù)器的該方法未能被識(shí)別或者未實(shí)現(xiàn);
下面逐個(gè)方法介紹下:
GET
GET方法意味著可以檢索 Request-URI標(biāo)識(shí)的任何信息。
如果Request-URI涉及到創(chuàng)建數(shù)據(jù),則應(yīng)該將新建的數(shù)據(jù)作為響應(yīng)實(shí)體返回。
如果請(qǐng)求消息包含 If-Modified-Since,If-Unmodified-Since,If-Match,If-None_match或If-Range標(biāo)頭字段,則此時(shí)的Get為條件GET。通過(guò)使用緩存標(biāo)頭,可以盡可能避免不必要的網(wǎng)絡(luò)傳輸。
如果請(qǐng)求標(biāo)頭包含Range,則GET方法變?yōu)椴糠諫ET。
HEAD
HEAD方法與GET方法很類(lèi)似,但是HEAD方法在在響應(yīng)中只返回首部,不會(huì)反悔消息體。
這就允許客戶端再不用獲取實(shí)際資源的情況下,對(duì)資源首部進(jìn)行檢查。如:
- 檢查資源是否有更新:如果獲取到的 Content-Length、Content-MD5、ETag、Last-Modified與之前獲取到的值不同,那么緩存應(yīng)該被視為過(guò)期;
- 查看響應(yīng)狀態(tài)碼,查看資源是否存在;
- 獲取首部更多信息,判斷資源情況。
POST
POST方法起初是用來(lái)向服務(wù)器傳輸數(shù)據(jù)的,通常用來(lái)提交HTML的表單到服務(wù)器。
PUT
PUT方法用于向服務(wù)器寫(xiě)入資源,如果Request-URI對(duì)應(yīng)的資源已經(jīng)存在的話,就進(jìn)行更新。
注意:
POST用于向服務(wù)器發(fā)送數(shù)據(jù),PUT用于向服務(wù)器上的資源中存儲(chǔ)數(shù)據(jù)。
DELETE
請(qǐng)求服務(wù)器刪除URL所指示的資源,但是客戶端無(wú)法保證刪除操作一定會(huì)被執(zhí)行,除非在響應(yīng)式服務(wù)器打算刪除資源或者將其移動(dòng)到無(wú)法訪問(wèn)的位置。可能的響應(yīng):
- 如果響應(yīng)包含描述狀態(tài)的實(shí)體,則響應(yīng)200(確定);
- 如果尚未執(zhí)行刪除操作,則響應(yīng)202(接受);
- 如果已執(zhí)行該操作,并且響應(yīng)不包含任何實(shí)體,則響應(yīng)204(無(wú)內(nèi)容)。
此方法的響應(yīng)不可緩存。
TRACE
一個(gè)請(qǐng)求從客戶端到服務(wù)端,中間可能會(huì)經(jīng)歷各種代理、網(wǎng)關(guān)等程序,每個(gè)中間節(jié)點(diǎn)都可能修改原始HTTP請(qǐng)求。為此,通過(guò)TRACE,服務(wù)端會(huì)在接收到請(qǐng)求后反饋一個(gè)TRACE響應(yīng),并且在響應(yīng)主體中攜帶它收到的原始請(qǐng)求報(bào)文。客戶端拿到TRACE響應(yīng),就可以進(jìn)行測(cè)試和診斷了。其中Via標(biāo)頭字段特別有用,它用于充當(dāng)請(qǐng)求鏈的跟蹤。
可以使用Max-Forwards標(biāo)頭字段限制請(qǐng)求鏈的長(zhǎng)度,這對(duì)于測(cè)試無(wú)限循環(huán)中轉(zhuǎn)發(fā)消息的代理很有用。
如果請(qǐng)求有效,則響應(yīng)應(yīng)該在實(shí)體正文中包含整個(gè)請(qǐng)求消息,其 Content-Type為"message/http"。對(duì)此方法的響應(yīng)絕對(duì)不能緩存。
TRACE允跨站點(diǎn)跟蹤問(wèn)題,并且可能使黑客可以選擇竊取您的cookie信息。基于安全的考慮,一般的服務(wù)器會(huì)關(guān)掉TRACE:
TraceEnable off
這樣執(zhí)行TRACE會(huì)導(dǎo)致客戶端收到一個(gè)405不允許使用方法的狀態(tài)碼。
CONNECT
CONNECT 方法可以開(kāi)啟一個(gè)客戶端與所請(qǐng)求資源之間的雙向溝通的通道。它可以用來(lái)創(chuàng)建隧道(tunnel)。
例如,CONNECT
可以用來(lái)訪問(wèn)采用了 SSL (HTTPS) 協(xié)議的站點(diǎn)。客戶端要求代理服務(wù)器將 TCP 連接作為通往目的主機(jī)隧道。之后該服務(wù)器會(huì)代替客戶端與目的主機(jī)建立連接。連接建立好之后,代理服務(wù)器會(huì)面向客戶端發(fā)送或接收 TCP 消息流。[3]
OPTIONS
通過(guò)該方法,可以請(qǐng)求服務(wù)器獲取Request-URI對(duì)應(yīng)支持的各種通信選項(xiàng)的信息。最常見(jiàn)的如:詢問(wèn)服務(wù)器當(dāng)前URI支持哪些請(qǐng)求方法。
此方法響應(yīng)不能緩存。
方法的安全性與冪等性
所謂安全性,就是無(wú)論方法執(zhí)行多少次,服務(wù)器上的數(shù)據(jù)都不會(huì)被改變。
安全方法
:GET、HEAD;
不安全方法
:POST、PUT、DELETE操作則會(huì)改動(dòng)數(shù)據(jù)。
所謂冪等,就是多次執(zhí)行一個(gè)方法,結(jié)果都是相同的。
冪等方法
:GET、HEAD、PUT、DELETE;
非冪等方法
:POST。
3.2.2、Request-URI
URI,Uniform Resource Identifier,請(qǐng)求的統(tǒng)一資源標(biāo)識(shí)符。
3.2.2.1、URI與URL什么關(guān)系?
我們經(jīng)常會(huì)用到這兩個(gè)概念,但是他們是什么意思呢?
URI,Uniform Resource Identifier,統(tǒng)一資源標(biāo)識(shí)符,能夠唯一的標(biāo)識(shí)網(wǎng)上的一個(gè)資源,比如,我的網(wǎng)站IT宅的Logo:
https://www.itzhai.com/resources/images/itzhai_logo_home_page.jpg
只要在世界的任何一個(gè)有網(wǎng)絡(luò)的地方,發(fā)起請(qǐng)求,就可以拿到這個(gè)圖片,這個(gè)URI具有唯一性。那什么是URL呢?
URI有兩種形式:URL和URN。
URL
URL,Uniform Resource Locator,統(tǒng)一資源定位符,描述了一臺(tái)特定服務(wù)器上某個(gè)資源的特定位置。例如上面的鏈接就是一個(gè)統(tǒng)一資源定位符:
-
secheme方案
:指定方位資源所使用的協(xié)議類(lèi)型,如HTTPS; -
主機(jī)與端口
:英特網(wǎng)地址,即域名,這里默認(rèn)為80端口; -
路徑
:其余部分指定web服務(wù)器上的某個(gè)資源。
幾乎所有的 URI都是URL。
一個(gè)完整的URL格式如下:
-
用戶名和密碼
:有寫(xiě)服務(wù)器要求輸入用戶名和密碼才允許用戶訪問(wèn)數(shù)據(jù),如FTP; -
?query 查詢字符串
:可以通過(guò)查詢字符串進(jìn)行查詢來(lái)縮小所請(qǐng)求資源類(lèi)型的范圍; -
fragment片段
:指向HTML文檔中特定的圖片或者小節(jié)。
URN
URL,Uniform Resource Name,統(tǒng)一資源名,作為特定內(nèi)容的唯一名稱,與資源所在位置無(wú)關(guān)。也就是說(shuō),我可以給一份文檔定義一個(gè)URN,不管你把這個(gè)文檔放到哪里,有多少個(gè)URL,但是都只有唯一個(gè)URN。舉個(gè)例子,因特網(wǎng)標(biāo)準(zhǔn)文檔 RFC 3986不管存在哪個(gè)服務(wù)器上,都可以用唯一的URN來(lái)命名:
urn:ietf:rfc:3986
URN處于試驗(yàn)階段,暫未大范圍使用。
再通俗易懂點(diǎn)來(lái)說(shuō):URN就相當(dāng)于身份證,通過(guò)特定的規(guī)則,制定了一串唯一的字符串作為你的身份證,但是沒(méi)有規(guī)定身份證一定要放在哪里,只是作為你的個(gè)人唯一憑證。URL相當(dāng)于是快遞單上的地址,根據(jù)地址,快遞員一定可以把快遞送到唯一的一個(gè)目的地。
3.2.3、HTTP-Version
指定了當(dāng)前請(qǐng)求用到的HTTP協(xié)議版本。
3.3、消息頭[4]
通過(guò)傳遞消息頭(首部),服務(wù)器和客戶端可以把自己的信息或者是請(qǐng)求響應(yīng)相關(guān)信息進(jìn)行傳遞。
可以把首部分為:通用首部,請(qǐng)求首部,響應(yīng)首部,實(shí)體首部,擴(kuò)展首部。下面就來(lái)詳細(xì)介紹下。
3.3.1、通用首部
有些首部,不管是請(qǐng)求還是響應(yīng)都會(huì)出現(xiàn)他們的身影,我們把他們歸類(lèi)為通用首部。常見(jiàn)通用首部如下表格所示:
首部 | 說(shuō)明 |
---|---|
Cache-Control | 通過(guò)指定指令來(lái)實(shí)現(xiàn)緩存機(jī)制 |
Connection | Connection 頭(header) 決定當(dāng)前的事務(wù)完成后,是否會(huì)關(guān)閉網(wǎng)絡(luò)連接。如果該值是“keep-alive”,網(wǎng)絡(luò)連接就是持久的,不會(huì)關(guān)閉,使得對(duì)同一個(gè)服務(wù)器的請(qǐng)求可以繼續(xù)在該連接上完成:<br />Connection: keep-alive <br />Connection: close |
Data | 提供報(bào)文創(chuàng)建的時(shí)間 |
MIME-Version | 提供發(fā)送端使用的MIME版本 |
Trailer | 允許發(fā)送方在分塊發(fā)送的消息后面添加額外的元信息,這些元信息可能是隨著消息主體的發(fā)送動(dòng)態(tài)生成的,比如消息的完整性校驗(yàn),消息的數(shù)字簽名,或者消息經(jīng)過(guò)處理之后的最終狀態(tài)等。 |
Transfer-Encoding | 告知接收端報(bào)文的編碼方式 |
Upgrade | 允許客戶端指定它支持并且希望使用的通信協(xié)議,如果服務(wù)器認(rèn)為適合,則切換協(xié)議,服務(wù)器必須使用101(交換協(xié)議)中的Upgrade標(biāo)頭字段響應(yīng),以知識(shí)正在交換的協(xié)議。 |
Via | 顯示報(bào)文經(jīng)過(guò)的中間節(jié)點(diǎn),用來(lái)追蹤消息轉(zhuǎn)發(fā)情況,防止循環(huán)請(qǐng)求,以及識(shí)別在請(qǐng)求或響應(yīng)傳遞鏈中消息發(fā)送者對(duì)于協(xié)議的支持能力 |
Warning | 包含報(bào)文當(dāng)前狀態(tài)可能存在的問(wèn)題。在響應(yīng)中可以出現(xiàn)多個(gè) Warning 首部。一般來(lái)說(shuō), Warning 首部可以應(yīng)用于任何類(lèi)型的報(bào)文。然而一部分警告碼(warn-code)是為緩存代理服務(wù)器定制的,并且只可以應(yīng)用在響應(yīng)報(bào)文中。 |
3.3.2、請(qǐng)求首部
客戶端通過(guò)傳遞請(qǐng)求頭字段,將有關(guān)請(qǐng)求以及有關(guān)客戶端本身的其他信息傳遞給服務(wù)器,這些字段充當(dāng)請(qǐng)求修飾符,其語(yǔ)義等同于編程語(yǔ)言方法調(diào)用中的參數(shù)。
常見(jiàn)的請(qǐng)求頭如下:
Accept首部
首部 | 說(shuō)明 |
---|---|
Accept | 表明客戶端能夠接受的媒體類(lèi)型 |
Accept-Charset | 表明客戶端能夠接受的字符集 |
Accept-Encoding | 表明客戶端能夠接受的編碼方式 |
Accept-Language | Section 14.4 |
TE | 表明客戶端能夠接受的擴(kuò)展傳輸編碼 |
條件請(qǐng)求首部
首部 | 說(shuō)明 |
---|---|
Expect | 指示客戶端要求特定的服務(wù)器行為<br />目前規(guī)范中只規(guī)定了 "100-continue" 這一個(gè)期望條件:通知接收方客戶端要發(fā)送一個(gè)體積可能很大的消息體,期望收到狀態(tài)碼為100 (Continue) 的臨時(shí)回復(fù) |
If-Match | 請(qǐng)求首部 If-Match 的使用表示這是一個(gè)條件請(qǐng)求。在請(qǐng)求方法為 GET 和 HEAD 的情況下,服務(wù)器僅在請(qǐng)求的資源滿足此首部列出的 ETag 值時(shí)才會(huì)返回資源。而對(duì)于 PUT 或其他非安全方法來(lái)說(shuō),只有在滿足條件的情況下才可以將資源上傳。 |
If-Modified-Since |
If-Modified-Since 是一個(gè)條件式請(qǐng)求首部,服務(wù)器只在所請(qǐng)求的資源在給定的日期時(shí)間之后對(duì)內(nèi)容進(jìn)行過(guò)修改的情況下才會(huì)將資源返回,狀態(tài)碼為 200 。如果請(qǐng)求的資源從那時(shí)起未經(jīng)修改,那么返回一個(gè)不帶有消息主體的 304 響應(yīng),而在 Last-Modified 首部中會(huì)帶有上次修改時(shí)間。 不同于 If-Unmodified-Since , If-Modified-Since 只可以用在GET 或 HEAD 請(qǐng)求中。 |
If-None-Match | 對(duì)于 GET 和 HEAD 請(qǐng)求方法來(lái)說(shuō),當(dāng)且僅當(dāng)服務(wù)器上沒(méi)有任何資源的 ETag 屬性值與這個(gè)首部中列出的相匹配的時(shí)候,服務(wù)器端會(huì)才返回所請(qǐng)求的資源,響應(yīng)碼為 200 。對(duì)于其他方法來(lái)說(shuō),當(dāng)且僅當(dāng)最終確認(rèn)沒(méi)有已存在的資源的 ETag 屬性值與這個(gè)首部中所列出的相匹配的時(shí)候,才會(huì)對(duì)請(qǐng)求進(jìn)行相應(yīng)的處理。 |
If-Range |
If-Range HTTP 請(qǐng)求頭字段用來(lái)使得 Range 頭字段在一定條件下起作用:當(dāng)字段值中的條件得到滿足時(shí),Range 頭字段才會(huì)起作用,同時(shí)服務(wù)器回復(fù)206 部分內(nèi)容狀態(tài)碼,以及Range 頭字段請(qǐng)求的相應(yīng)部分;如果字段值中的條件沒(méi)有得到滿足,服務(wù)器將會(huì)返回 200 OK 狀態(tài)碼,并返回完整的請(qǐng)求資源。 |
If-Unmodified-Since | HTTP協(xié)議中的 If-Unmodified-Since 消息頭用于請(qǐng)求之中,使得當(dāng)前請(qǐng)求成為條件式請(qǐng)求:只有當(dāng)資源在指定的時(shí)間之后沒(méi)有進(jìn)行過(guò)修改的情況下,服務(wù)器才會(huì)返回請(qǐng)求的資源,或是接受 POST 或其他 non-safe 方法的請(qǐng)求。如果所請(qǐng)求的資源在指定的時(shí)間之后發(fā)生了修改,那么會(huì)返回 412 (Precondition Failed) 錯(cuò)誤。 |
Range | The Range 是一個(gè)請(qǐng)求首部,告知服務(wù)器返回文件的哪一部分。在一個(gè) Range 首部中,可以一次性請(qǐng)求多個(gè)部分,服務(wù)器會(huì)以 multipart 文件的形式將其返回。如果服務(wù)器返回的是范圍響應(yīng),需要使用 206 Partial Content 狀態(tài)碼。假如所請(qǐng)求的范圍不合法,那么服務(wù)器會(huì)返回 416 Range Not Satisfiable 狀態(tài)碼,表示客戶端錯(cuò)誤。服務(wù)器允許忽略 Range 首部,從而返回整個(gè)文件,狀態(tài)碼用 200 。 |
安全請(qǐng)求首部
首部 | 說(shuō)明 |
---|---|
Authorization | HTTP協(xié)議中的 Authorization 請(qǐng)求消息頭含有服務(wù)器用于驗(yàn)證用戶代理身份的憑證,通常會(huì)在服務(wù)器返回401 Unauthorized 狀態(tài)碼以及WWW-Authenticate 消息頭之后在后續(xù)請(qǐng)求中發(fā)送此消息頭。 |
Cookie |
Cookie 是一個(gè)請(qǐng)求首部,其中含有先前由服務(wù)器通過(guò) Set-Cookie 首部投放并存儲(chǔ)到客戶端的 HTTP cookies。 |
Cookie2 | 這個(gè)已經(jīng)被廢棄的 Cookie2 請(qǐng)求首部曾經(jīng)被用來(lái)告知瀏覽器該用戶代理支持“新型” cookies,但是現(xiàn)代的用戶代理一般使用 Cookie 來(lái)替代 Cookie2。
|
代理請(qǐng)求首部
首部 | 說(shuō)明 |
---|---|
Max-Forwards | 在通往源端服務(wù)器的路徑上,將請(qǐng)求轉(zhuǎn)發(fā)給其他代理或者網(wǎng)關(guān)的最大次數(shù),與TRACE方法類(lèi)似。 |
Proxy-Authorization |
Proxy-Authorization 是一個(gè)請(qǐng)求首部,其中包含了用戶代理提供給代理服務(wù)器的用于身份驗(yàn)證的憑證。這個(gè)首部通常是在服務(wù)器返回了 407 Proxy Authentication Required 響應(yīng)狀態(tài)碼及 Proxy-Authenticate 首部后發(fā)送的。 |
Proxy-Connection | 同Connection,不過(guò)這個(gè)首部是在與代理建立連接時(shí)使用。 |
3.3.3、響應(yīng)首部
首部 | 說(shuō)明 |
---|---|
Age |
Age 消息頭里包含對(duì)象在緩存代理中存貯的時(shí)長(zhǎng),以秒為單位。<br />Age的值通常接近于0。表示此對(duì)象剛剛從原始服務(wù)器獲取不久;其他的值則是表示代理服務(wù)器當(dāng)前的系統(tǒng)時(shí)間與此應(yīng)答中的通用頭 Date 的值之差。 |
Retry-After | 在HTTP協(xié)議中,響應(yīng)首部 Retry-After 表示用戶代理需要等待多長(zhǎng)時(shí)間之后才能繼續(xù)發(fā)送請(qǐng)求。這個(gè)首部主要應(yīng)用于以下兩種場(chǎng)景:<br />- 當(dāng)與 503 響應(yīng)一起發(fā)送的時(shí)候,表示服務(wù)下線的預(yù)期時(shí)長(zhǎng);<br />- 當(dāng)與重定向響應(yīng)一起發(fā)送的時(shí)候,比如 301 (Moved Permanently,永久遷移),表示用戶代理在發(fā)送重定向請(qǐng)求之前需要等待的最短時(shí)間。 |
Server |
Server 首部包含了處理請(qǐng)求的源頭服務(wù)器所用到的軟件相關(guān)信息。<br />避免描述的過(guò)于詳細(xì),因?yàn)檫@有可能泄露服務(wù)器內(nèi)部實(shí)現(xiàn)細(xì)節(jié),或者被攻擊者找到已知安全漏洞。 |
Title | 對(duì)于HTML文檔來(lái)說(shuō),就是HTML文案定的源端給出的標(biāo)題。<br />該首部定義與原始的 HTTP/1.0草案,并未列入RFC2616。 |
Warning |
Warning 是一個(gè)通用報(bào)文首部,包含報(bào)文當(dāng)前狀態(tài)可能存在的問(wèn)題。在響應(yīng)中可以出現(xiàn)多個(gè) Warning 首部。<br />一般來(lái)說(shuō), Warning 首部可以應(yīng)用于任何類(lèi)型的報(bào)文。然而一部分警告碼(warn-code)是為緩存代理服務(wù)器定制的,并且只可以應(yīng)用在響應(yīng)報(bào)文中。格式:<br />Warning: <warn-code> <warn-agent> <warn-text> [<warn-date>]
|
協(xié)商首部
如果資源有多種表示方法,服務(wù)器可以通過(guò)協(xié)商首部來(lái)傳遞可協(xié)商資源有關(guān)的信息。
首部 | 說(shuō)明 |
---|---|
Accept-Range | 服務(wù)器使用 HTTP 響應(yīng)頭 **Accept-Ranges** 標(biāo)識(shí)自身支持范圍請(qǐng)求(partial requests)。字段的具體值用于定義范圍請(qǐng)求的單位。<br />當(dāng)瀏覽器發(fā)現(xiàn)Accept-Ranges 頭時(shí),可以嘗試繼續(xù)中斷了的下載,而不是重新開(kāi)始。 |
Vary |
Vary 是一個(gè)HTTP響應(yīng)頭部信息,它決定了對(duì)于未來(lái)的一個(gè)請(qǐng)求頭,應(yīng)該用一個(gè)緩存的回復(fù)(response)還是向源服務(wù)器請(qǐng)求一個(gè)新的回復(fù)。<br />例如,移動(dòng)端和桌面端響應(yīng)內(nèi)容是不同的,為了防止移動(dòng)端誤用了桌面端的緩存,可以這樣指定Vary:Vary: User-Agent
|
安全響應(yīng)首部
首部 | 描述 |
---|---|
Proxy-Authenticate | 指定了獲取 proxy server (代理服務(wù)器)上的資源訪問(wèn)權(quán)限而采用的身份驗(yàn)證方式。代理服務(wù)器對(duì)請(qǐng)求進(jìn)行驗(yàn)證,以便它進(jìn)一步傳遞請(qǐng)求。<br />Proxy-Authenticate 首部需要與 407 Proxy Authentication Required 響應(yīng)一起發(fā)送。 |
Set-Cookie | 響應(yīng)首部 Set-Cookie 被用來(lái)由服務(wù)器端向客戶端發(fā)送 cookie。 |
Set-Cookie2 | 已廢棄使用。它被服務(wù)器用來(lái)向客戶端發(fā)送 cookie 數(shù)據(jù),但是已經(jīng)在協(xié)議中被標(biāo)記為不贊成使用了。請(qǐng)使用 Set-Cookie 將其代替。 |
WWW-Authenticate | 定義了使用何種驗(yàn)證方式去獲取對(duì)資源的連接。<br />WWW-Authenticate header通常會(huì)和一個(gè) 401 Unauthorized 的響應(yīng)一同被發(fā)送。 |
3.3.4、實(shí)體首部
用來(lái)描述HTTP報(bào)文中實(shí)體相關(guān)信息的首部,我們成為實(shí)體首部。
首部 | 描述 |
---|---|
Allow |
Allow 首部字段用于枚舉資源所支持的 HTTP 方法的集合。 |
Location |
Location 首部指定的是需要將頁(yè)面重新定向至的地址。一般在響應(yīng)碼為3xx的響應(yīng)中才會(huì)有意義:<br />- 303 (See Also) 始終引致請(qǐng)求使用 GET 方法,而,而 307 (Temporary Redirect) 和 308 (Permanent Redirect) 則不轉(zhuǎn)變初始請(qǐng)求中的所使用的方法;<br />- 301 (Permanent Redirect) 和 302 (Found) 在大多數(shù)情況下不會(huì)轉(zhuǎn)變初始請(qǐng)求中的方法,不過(guò)一些比較早的用戶代理可能會(huì)引發(fā)方法的變更;<br />除了重定向響應(yīng)之外, 狀態(tài)碼為 201 (Created) 的消息也會(huì)帶有Location首部。它指向的是新創(chuàng)建的資源的地址。 |
內(nèi)容首部
首部 | 描述 |
---|---|
Content-Encoding |
Content-Encoding 是一個(gè)實(shí)體消息首部,用于對(duì)特定媒體類(lèi)型的數(shù)據(jù)進(jìn)行壓縮。 |
Content-Languate |
Content-Language 用來(lái)說(shuō)明訪問(wèn)者希望采用的語(yǔ)言或語(yǔ)言組合,這樣的話用戶就可以根據(jù)自己偏好的語(yǔ)言來(lái)定制不同的內(nèi)容。 |
Content-Length | 指明發(fā)送給接收方的消息主體的大小,即用十進(jìn)制數(shù)字表示的八位元組的數(shù)目。 |
Content-Location | 指定的是要返回的數(shù)據(jù)的地址選項(xiàng)。最主要的用途是用來(lái)指定要訪問(wèn)的資源經(jīng)過(guò)內(nèi)容協(xié)商后的結(jié)果的URL。 |
Content-MD5 | 消息主題的MD5校驗(yàn)和 |
Content-Range | 描述一個(gè)數(shù)據(jù)片段在整個(gè)文件中的位置 |
Content-Type | 指示資源的MIME類(lèi)型 media type |
實(shí)體緩存首部
實(shí)體緩存首部提供與被緩存實(shí)體有關(guān)的信息,如什么時(shí)候或者如何緩存,緩存是否有效等,通過(guò)緩存首部可以估計(jì)緩存何時(shí)失效。
首部 | 描述 |
---|---|
ETag | 資源的特定版本的標(biāo)識(shí)符。這可以讓緩存更高效,并節(jié)省帶寬,因?yàn)槿绻麅?nèi)容沒(méi)有改變,Web服務(wù)器不需要發(fā)送完整的響應(yīng)。<br />如果給定URL中的資源更改,則一定要生成新的Etag值。 |
Expires | 該首部包含日期/時(shí)間, 即在此時(shí)候之后,響應(yīng)過(guò)期。<br />無(wú)效的日期,比如 0, 代表著過(guò)去的日期,即該資源已經(jīng)過(guò)期。 |
Last-Modified | 含源頭服務(wù)器認(rèn)定的資源做出修改的日期及時(shí)間。 它通常被用作一個(gè)驗(yàn)證器來(lái)判斷接收到的或者存儲(chǔ)的資源是否彼此一致。<br />由于精確度比 ETag 要低,所以這是一個(gè)備用機(jī)制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的條件請(qǐng)求會(huì)使用這個(gè)字段。 |
3.4、消息體
3.4.1、請(qǐng)求消息體
并不是所有的請(qǐng)求都需要body,如:GET,HEAD,DELETE,OPTIONS通產(chǎn)不需要body。
請(qǐng)求body可以分為兩類(lèi):
- Single-resource bodies,由單個(gè)文件組成。該類(lèi)型 body 由兩個(gè) header 定義:
Content-Type
和Content-Length
; - Multiple-resource bodies,由多部分body組成,每一部分包含不同的信息位。通常是和 HTML Forms 連系在一起。
3.4.2、響應(yīng)消息體
并不是所有的響應(yīng)都有body,如 201
或 204
狀態(tài)碼的響應(yīng)一般不會(huì)有body。
響應(yīng)body可以分為三類(lèi):
- Single-resource bodies,由已知長(zhǎng)度的單個(gè)文件組成。該類(lèi)型 body 由兩個(gè) header 定義:
Content-Type
和Content-Length
; - Single-resource bodies,由未知長(zhǎng)度的單個(gè)文件組成,通過(guò)將
Transfer-Encoding
設(shè)置為chunked
來(lái)使用 chunks 編碼; - Multiple-resource bodies,由多部分 body 組成,每部分包含不同的信息段。但這是比較少見(jiàn)的。
3.5、狀態(tài)行
響應(yīng)消息的第一行是狀態(tài)行,由協(xié)議版本,數(shù)字狀態(tài)代碼及其關(guān)聯(lián)的文本短語(yǔ)組成,每個(gè)元素由SP字符分隔。 除最后的CRLF序列外,不允許CR或LF。
狀態(tài)行格式:
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
3.5.1、Status-Code狀態(tài)碼和Reason-Phrase狀態(tài)描述
狀態(tài)碼是3位數(shù)的整數(shù)結(jié)果代碼。
狀態(tài)碼的第一位數(shù)字定義響應(yīng)的類(lèi)別。 后兩位數(shù)字沒(méi)有任何分類(lèi)作用。可以分為5個(gè)類(lèi)別:
- 1xx:信息狀態(tài)碼,收到請(qǐng)求,繼續(xù)進(jìn)行;
- 2xx:請(qǐng)求成功接收;
- 3xx:重定向,必須采取進(jìn)一步措施才能完成請(qǐng)求;
- 4xx:客戶端錯(cuò)誤,請(qǐng)求包含錯(cuò)誤語(yǔ)法,或者不能被完成;
- 5xx:服務(wù)器錯(cuò)誤,服務(wù)器無(wú)法完成看似有效的請(qǐng)求;
RFC中定義的狀態(tài)碼很多,這里我們列出最常見(jiàn)的一些狀態(tài)碼:
狀態(tài)碼 | 描述 | 詳細(xì)說(shuō)明 |
---|---|---|
101 | Switching Protocol | 該代碼是響應(yīng)客戶端的 Upgrade 標(biāo)頭發(fā)送的,并且指示服務(wù)器也正在切換的協(xié)議。 |
200 | OK | 請(qǐng)求成功。 |
204 | No Content | 服務(wù)器成功處理了請(qǐng)求,但不需要返回任何實(shí)體內(nèi)容,并且希望返回更新了的元信息。<br />用這個(gè)狀態(tài)碼區(qū)分成功狀態(tài)下又返回內(nèi)容和沒(méi)返回內(nèi)容的響應(yīng)。 |
206 | Partial Content | 服務(wù)器已經(jīng)成功處理了部分 GET 請(qǐng)求。通過(guò)HTTP的分塊下載,獲取資源的部分時(shí)返回。該請(qǐng)求必須包含 Range 頭信息來(lái)指示客戶端希望得到的內(nèi)容范圍,并且可能包含 If-Range 來(lái)作為請(qǐng)求條件。<br />206狀態(tài)碼通常會(huì)攜帶Content-Range ,用于表示報(bào)文里面body數(shù)據(jù)的具體范圍。 |
301 | Moved Permanently | 永久重定向,將來(lái)任何對(duì)此資源的引用都應(yīng)該使用本響應(yīng)返回的若干個(gè) URI 之一。 |
302 | Found | 臨時(shí)重定向,客戶端下次應(yīng)當(dāng)繼續(xù)向原有地址發(fā)送以后的請(qǐng)求。只有在Cache-Control或Expires中進(jìn)行了指定的情況下,這個(gè)響應(yīng)才是可緩存的。 |
304 | Not Modified | 如果客戶端發(fā)送了一個(gè)帶條件的 GET 請(qǐng)求且該請(qǐng)求已被允許,而文檔的內(nèi)容(自上次訪問(wèn)以來(lái)或者根據(jù)請(qǐng)求的條件)并沒(méi)有改變,則服務(wù)器應(yīng)當(dāng)返回這個(gè)狀態(tài)碼。304 響應(yīng)禁止包含消息體,因此始終以消息頭后的第一個(gè)空行結(jié)尾。 |
400 | Bad Request | 語(yǔ)義有誤,當(dāng)前請(qǐng)求無(wú)法被服務(wù)器理解。除非進(jìn)行修改,否則客戶端不應(yīng)該重復(fù)提交這個(gè)請(qǐng)求。 |
401 | Unauthorized | 當(dāng)前請(qǐng)求需要用戶驗(yàn)證。該響應(yīng)必須包含一個(gè)適用于被請(qǐng)求資源的 WWW-Authenticate 信息頭用以詢問(wèn)用戶信息。客戶端可以重復(fù)提交一個(gè)包含恰當(dāng)?shù)?Authorization 頭信息的請(qǐng)求。 |
403 | Forbidden | 服務(wù)器已經(jīng)理解請(qǐng)求,但是拒絕執(zhí)行它。如果這不是一個(gè) HEAD 請(qǐng)求,而且服務(wù)器希望能夠講清楚為何請(qǐng)求不能被執(zhí)行,那么就應(yīng)該在實(shí)體內(nèi)描述拒絕的原因。當(dāng)然服務(wù)器也可以返回一個(gè) 404 響應(yīng),假如它不希望讓客戶端獲得任何信息。 |
404 | Not Found | 請(qǐng)求失敗,請(qǐng)求所希望得到的資源未被在服務(wù)器上發(fā)現(xiàn)。<br />究竟是不是真的資源不存在呢?還得看程序是怎么寫(xiě)的。 |
405 | Method Not Allowed | 請(qǐng)求行中指定的請(qǐng)求方法不能被用于請(qǐng)求相應(yīng)的資源。該響應(yīng)必須返回一個(gè)Allow 頭信息用以表示出當(dāng)前資源能夠接受的請(qǐng)求方法的列表。 |
408 | Request Timeout | 請(qǐng)求超時(shí)。客戶端沒(méi)有在服務(wù)器預(yù)備等待的時(shí)間內(nèi)完成一個(gè)請(qǐng)求的發(fā)送。客戶端可以隨時(shí)再次提交這一請(qǐng)求而無(wú)需進(jìn)行任何更改。 |
409 | Conflict | 由于和被請(qǐng)求的資源的當(dāng)前狀態(tài)之間存在沖突,請(qǐng)求無(wú)法完成。 |
413 | Payload Too Large | 請(qǐng)求提交的實(shí)體數(shù)據(jù)大小超過(guò)了服務(wù)器愿意或者能夠處理的范圍。此種情況下,服務(wù)器可以關(guān)閉連接以免客戶端繼續(xù)發(fā)送此請(qǐng)求。如果這個(gè)狀況是臨時(shí)的,服務(wù)器應(yīng)當(dāng)返回一個(gè) Retry-After 的響應(yīng)頭,以告知客戶端可以在多少時(shí)間以后重新嘗試。 |
429 | Too Many Requests | 用戶在給定的時(shí)間內(nèi)發(fā)送了太多請(qǐng)求(“限制請(qǐng)求速率”)。 |
431 | Request Header Fields Too Large | 請(qǐng)求頭字段太大( Request Header Fields Too Large) |
500 | Internal Server Error | 服務(wù)器遇到了不知道如何處理的情況。通常用來(lái)捕獲服務(wù)器異常,統(tǒng)一返回500,避免輸出詳細(xì)錯(cuò)誤堆棧給別人利用。 |
501 | Not Implemented | 此請(qǐng)求方法不被服務(wù)器支持且無(wú)法被處理。只有GET 和HEAD 是要求服務(wù)器支持的,它們必定不會(huì)返回此錯(cuò)誤代碼。
|
502 | Bad Gateway | 此錯(cuò)誤響應(yīng)表明服務(wù)器作為網(wǎng)關(guān)需要得到一個(gè)處理這個(gè)請(qǐng)求的響應(yīng),但是得到一個(gè)錯(cuò)誤的響應(yīng)。 |
503 | Service Unavailable | 服務(wù)器沒(méi)有準(zhǔn)備好處理請(qǐng)求。 常見(jiàn)原因是服務(wù)器因維護(hù)或重載而停機(jī)。 |
504 | Gateway Timeout | 當(dāng)服務(wù)器作為網(wǎng)關(guān),不能及時(shí)得到響應(yīng)時(shí)返回此錯(cuò)誤代碼。 |
更多狀態(tài)碼說(shuō)明:
上面我們把HTTP報(bào)文介紹了一遍,HTTP作為一個(gè)協(xié)議,只是規(guī)定了大家要遵循這樣的約定,但是具體實(shí)現(xiàn)的時(shí)候,還是要看應(yīng)用程序的兼容程度。我們?cè)趯?xiě)程序的時(shí)候,也不要跟協(xié)議對(duì)著干,這會(huì)讓對(duì)接的同事無(wú)法理解的。
你都知道以下?tīng)顟B(tài)碼的含義了嗎?
200 204 206 301 302 304 401 403 405 500 501 502 503 504
本文首次發(fā)表于: HTTP/1.1報(bào)文詳解 以及公眾號(hào) Java架構(gòu)雜談,未經(jīng)許可,不得轉(zhuǎn)載。
本文為arthinking基于相關(guān)技術(shù)資料和官方文檔撰寫(xiě)而成,確保內(nèi)容的準(zhǔn)確性,如果你發(fā)現(xiàn)了有何錯(cuò)漏之處,煩請(qǐng)高抬貴手幫忙指正,萬(wàn)分感激。
如果您覺(jué)得讀完本文有所收獲的話,可以關(guān)注我的賬號(hào),或者點(diǎn)贊吧,碼字不易,您的支持就是我寫(xiě)作的最大動(dòng)力,再次感謝!
為了把相關(guān)系列文章收集起來(lái),方便后續(xù)查閱,這里我創(chuàng)建了一個(gè)Github倉(cāng)庫(kù),把發(fā)布的文章按照分類(lèi)收集起來(lái)了,感興趣的朋友可以Star跟進(jìn):
關(guān)注我的博客IT宅(itzhai.com)
或者公眾號(hào)Java架構(gòu)雜談
,及時(shí)獲取最新的文章。我將持續(xù)更新后端相關(guān)技術(shù),涉及JVM、Java基礎(chǔ)、架構(gòu)設(shè)計(jì)、網(wǎng)絡(luò)編程、數(shù)據(jù)結(jié)構(gòu)、數(shù)據(jù)庫(kù)、算法、并發(fā)編程、分布式系統(tǒng)等相關(guān)內(nèi)容。
References
- 謝希仁. 計(jì)算機(jī)網(wǎng)絡(luò)(第6版). 電子工業(yè)出版社.
- TCP/IP詳解 卷1:協(xié)議(原書(shū)第2版). 機(jī)械工業(yè)出版社.
- UNIX網(wǎng)絡(luò)編程 卷1:套接字聯(lián)網(wǎng)API. 人民郵電出版社
- HTTP權(quán)威指南. 人民郵電出版社
- HTTP/2基礎(chǔ)教程. 人民郵電出版社
- 劉超. 趣談網(wǎng)絡(luò)協(xié)議. 極客時(shí)間
- 羅劍鋒. 透視HTTP協(xié)議. 即可時(shí)間
本文同步發(fā)表于我的博客IT宅(itzhai.com)和公眾號(hào)(Java架構(gòu)雜談)
作者:arthinking | 公眾號(hào):Java架構(gòu)雜談
博客鏈接:https://www.itzhai.com/articles/detailed-explanation-of-http-1-1-messages.html
版權(quán)聲明: 版權(quán)歸作者所有,未經(jīng)許可不得轉(zhuǎn)載,侵權(quán)必究!聯(lián)系作者請(qǐng)加公眾號(hào)。
-
Hypertext Transfer Protocol -- HTTP/1.1 2616. Retrieved from https://tools.ietf.org/html/rfc2616 ? ?
-
HTTP. MDN web docs. Retrieved from https://developer.mozilla.org/zh-CN/docs/Web/HTTP ?
-
CONNECT. Retrieved from https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/CONNECT ?
-
HTTP Headers. Retrieved from https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers ?
-
List of HTTP status codes. Retrieved from https://en.wikipedia.org/wiki/List_of_HTTP_status_codes ?
-
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status. Retrieved from https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status ?