日常的web開(kāi)發(fā)過(guò)程中,以及其他的開(kāi)發(fā)中,接觸到最多的網(wǎng)絡(luò)交互協(xié)議就是http協(xié)議,而http協(xié)議基于tcp的二度封裝協(xié)議,既然http協(xié)議如此重要,那么我
們就開(kāi)始系統(tǒng)的對(duì)http協(xié)議進(jìn)行掃盲學(xué)習(xí)吧
請(qǐng)求/響應(yīng)模型
http屬于請(qǐng)求/響應(yīng)模型,從某種意義上來(lái)說(shuō),Http協(xié)議永遠(yuǎn)都是客戶(hù)端發(fā)起請(qǐng)求,由服務(wù)器端接受請(qǐng)求處理并返回響應(yīng)報(bào)文。如果沒(méi)有客戶(hù)端發(fā)送請(qǐng)求到服務(wù)端,那么服務(wù)端無(wú)法將消息發(fā)送回客戶(hù)端的。而HTTP交互的流程圖如下,當(dāng)客戶(hù)端發(fā)送請(qǐng)求到服務(wù)端的時(shí)候,請(qǐng)求頭常見(jiàn)的包含有請(qǐng)求方式、URI、協(xié)議版本等,以及會(huì)攜帶MIME的消息內(nèi)容,服務(wù)端作為一個(gè)狀態(tài)行的方式響應(yīng),包括協(xié)議版本、編碼、元數(shù)據(jù)和實(shí)體數(shù)據(jù)等,這樣就完成了一個(gè)請(qǐng)求/響應(yīng)流程
HTTP的發(fā)展過(guò)程
1989年3月,蒂姆 ? 伯納斯 - 李提出了一種能讓遠(yuǎn)隔兩地的研究者們共享知識(shí)的設(shè)想,起初的理念是:借助多文檔之間相互關(guān)聯(lián)形成的超文本(HyperText),連成可相互參閱的 WWW(World Wide Web,萬(wàn)維網(wǎng))隨著HTML1.0的誕生,作為其中的超文本傳輸協(xié)議的HTTP正式誕生
Http/0.9:1990年誕生,作為HTTP最早的協(xié)議版本,但是由于當(dāng)時(shí)對(duì)于HTML相關(guān)web的定義未統(tǒng)一,該版本并不是正式版
HTTP/1.0:1996年5月份,隨著微軟公司與網(wǎng)景通信公司之間爆發(fā)的瀏覽器大戰(zhàn)越來(lái)越烈,HTML兼容多個(gè)瀏覽器的頭疼問(wèn)題出現(xiàn)了,但是針對(duì)網(wǎng)絡(luò)協(xié)議的正式版HTTP1.0出現(xiàn)了
HTTP/1.1:1997年1月份對(duì)于HTTP1.0的版本進(jìn)行了部分內(nèi)容的修訂,作為更標(biāo)準(zhǔn)化的協(xié)議出現(xiàn),也是目前為止依然主流的協(xié)議版本
HTTP/1.2:1999年,針對(duì)HTTP1.1的改進(jìn)版本出現(xiàn),1.2使用了SRV records 更好地支持負(fù)載平衡 ,改進(jìn)了之前只能基于表單的認(rèn)證方式,提供了Basic和Digest訪問(wèn)認(rèn)證,增加了一套新的accepted headers
HTTP/2.0:2013年8月份出了新一代的超文本傳輸協(xié)議的草案,與之前的HTTP1.x版本差距頗大,無(wú)法兼容,此協(xié)議針對(duì)連接的安全性做了很大的提升,而HTTP2.0的絕大多數(shù)請(qǐng)求基本都是走的HTTPS,所以一般情況下,不會(huì)直接用HTTP2.0,而是HTTPS
URI和URL
看到這可能絕大多數(shù)的人都很奇怪,URL我們都知道,比如我們?yōu)g覽一個(gè)網(wǎng)站,輸入的www.xxx.com的網(wǎng)址就是URL,那么URI是什么呢?其實(shí)我們要明白,URI是Uniform Resource Identifier 的縮寫(xiě),稱(chēng)之為統(tǒng)一資源標(biāo)示符,到這可能大概明白了,URL其實(shí)就是URI的一個(gè)子集而已,而URI主要分為Uniform、Resource和Identifier
Uniform:用來(lái)方便做多種不同類(lèi)型的資源得處理,而不需要根據(jù)上下文等方法識(shí)別訪問(wèn)方式,比如我們輸入網(wǎng)址的時(shí)候輸入的Http:
Resource:傳輸過(guò)程中可以用來(lái)區(qū)別其他類(lèi)型的文件的集合定義,資源是一個(gè)類(lèi)型的統(tǒng)稱(chēng),不僅僅是單一的
Identifier:表示當(dāng)前可以標(biāo)識(shí)的對(duì)象,也稱(chēng)之為標(biāo)示符
一個(gè)URI的例子如下:
ftp://ftp.is.co.za/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc2396.txt
tel:+1-535-555-1212
telnet://192.168.1.16:80/
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
而URI使用過(guò)程中,如果需要涵蓋全部信息或者準(zhǔn)確信息,就要正確使用URI的格式:

| 名稱(chēng) | 作用 | 是否必選 |
|---|---|---|
| 登錄信息 | 指定用戶(hù)名和密碼作為從服務(wù)器端獲取資源時(shí)必要的登錄信息 | Y |
| 服務(wù)器地址 | 使用絕對(duì) URI 必須指定待訪問(wèn)的服務(wù)器地址 | Y |
| 服務(wù)器端口 | 連接服務(wù)器的端口 | N |
| 文件路徑 | 指定服務(wù)器上的文件路徑來(lái)定位特指的資源(UNLX系統(tǒng)) | N |
| 查詢(xún)字符串 | 可以作為URL攜帶的請(qǐng)求參數(shù)來(lái)協(xié)助定位具體文件資源 | N |
| 片段標(biāo)識(shí)符 | 通??蓸?biāo)記出已獲取資源中的子資源 | N |
無(wú)狀態(tài)協(xié)議
Http協(xié)議屬于一種不記錄狀態(tài)的協(xié)議,即無(wú)狀態(tài)協(xié)議,具體表現(xiàn)為,每次請(qǐng)求發(fā)起都會(huì)重新進(jìn)行連接,并不會(huì)根據(jù)之前的狀態(tài)或者持久化保持狀態(tài)。每當(dāng)有新的請(qǐng)求發(fā)送時(shí),就會(huì)有對(duì)應(yīng)的新響應(yīng)產(chǎn)生。協(xié)議本身并不保留之前一切的請(qǐng)求或響應(yīng)報(bào)文的信息。這是為了更快地處理大量事務(wù),確保協(xié)議的可伸縮性。但是Http雖然是無(wú)狀態(tài)協(xié)議,但是有保存狀態(tài)信息的需求,HTTP1.1開(kāi)始引入了Cookie技術(shù),使用cookie來(lái)代為管理狀態(tài)信息。
HTTP協(xié)議方法
Http協(xié)議支持通過(guò)不同的請(qǐng)求類(lèi)型--即協(xié)議方法來(lái)達(dá)成某種目的,實(shí)現(xiàn)功能,HTTP1.1支持的協(xié)議方法如下:
GET :獲取資源
Get方法用來(lái)訪問(wèn)已經(jīng)被URI識(shí)別的資源,指定的資源信息經(jīng)由服務(wù)端解析以后返回對(duì)應(yīng)的資源響應(yīng)內(nèi)容,也就是說(shuō)如果當(dāng)前訪問(wèn)的資源是文本等靜態(tài)資源,則會(huì)返回對(duì)應(yīng)的數(shù)據(jù),如果是網(wǎng)關(guān)等程序,則會(huì)返回對(duì)應(yīng)的結(jié)果。
POST:傳輸實(shí)體主體
在HTTP中推薦使用POST方法來(lái)傳遞我們需要傳輸?shù)膬?nèi)容或者實(shí)體信息,雖然GET方法可以添加查詢(xún)字符串來(lái)輔助傳遞一定的信息和參數(shù),但是要注意的是GET方法定義僅僅是希望根據(jù)查詢(xún)字符串來(lái)定位具體的資源,所以GET方法一般都希望得到快速響應(yīng),傳遞的數(shù)據(jù)的長(zhǎng)度有一定的限制
PUT:傳輸文件
HTTP協(xié)議中,PUT方法被定義出來(lái)用來(lái)朝服務(wù)端傳遞文件(上傳)使用的方法,要求在請(qǐng)求的報(bào)文中包含文件內(nèi)容,然后保存文件到請(qǐng)求的URI所在的位置上,但是由于HTTP1.1不帶有安全機(jī)制,所以一般當(dāng)前方法在HTTP協(xié)議上不開(kāi)放,類(lèi)似的協(xié)議如:Restful會(huì)開(kāi)放實(shí)現(xiàn)其他規(guī)范的操作
HEAD:獲得報(bào)文首部
HEAD方法和GET方法一樣,唯一的區(qū)別是GET方法返回完整的響應(yīng)信息,而HEAD方法不需要報(bào)文主體部分,因?yàn)榇朔椒▋H用來(lái)獲取頭信息,用來(lái)確認(rèn)URI是否有效或者觸發(fā)資源的緩存更新等
DELETE:刪除文件
DELETE方法和PUT方法是完全相反的定義,這里的作用是用來(lái)刪除指定請(qǐng)求URI上位置的資源文件,而和PUT一樣,在不帶有安全驗(yàn)證機(jī)制的情況下一般也是不開(kāi)放的
OPTIONS:詢(xún)問(wèn)支持的方法
OPTIONS方法使用場(chǎng)景比較特殊,一般情況下我們用來(lái)查詢(xún)針對(duì)請(qǐng)求URI指定的資源支持的方法有哪些(和跨域操作也有一定的聯(lián)系)
TRACE:追蹤路徑
TRACE方法是HTTP協(xié)議用來(lái)檢查和追蹤請(qǐng)求過(guò)程提供的方法,當(dāng)發(fā)送請(qǐng)求的時(shí)候,會(huì)在Max-Forwards 首部填入數(shù)值,每次經(jīng)過(guò)一個(gè)服務(wù)端就會(huì)-1,當(dāng)數(shù)字減少到0的時(shí)候,就會(huì)停止傳輸請(qǐng)求,直到接受到返回的狀態(tài)碼響應(yīng)才算結(jié)束。使用TRACE方法可以檢查當(dāng)前請(qǐng)求是否被篡改,但是由于當(dāng)前方法很容易引起XST(Cross-Site Tracing,跨站追蹤)攻擊,所以一般都禁止使用
CONNECT:要求用隧道協(xié)議連接代理
使用CONNECT方法要求是與代理服務(wù)器建立連接隧道,實(shí)現(xiàn)隧道間通信TCP,常見(jiàn)會(huì)使用SSL或者TLS協(xié)議把內(nèi)容加密后傳遞到隧道,CONNECT的格式如下:
CONNECT 代理服務(wù)器名:端口號(hào) HTTP版本
我們把1.0和1.1兩個(gè)版本的支持的協(xié)議方法列個(gè)表格,看下具體差異:
| 方法 | 作用 | 支持的協(xié)議版本 |
|---|---|---|
| GET | 獲取資源 | 1.0、1.1 |
| POST | 傳輸實(shí)體主體 | 1.0、1.1 |
| PUT | 傳輸文件 | 1.0、1.1 |
| HEAD | 獲得報(bào)文首部?jī)?nèi)容 | 1.0、1.1 |
| DELETE | 刪除文件 | 1.0、1.1 |
| OPTIONS | 獲取當(dāng)前URI支持的方法 | 1.1 |
| TRACE | 追蹤路徑 | 1.1 |
| CONNECT | 需要使用隧道協(xié)議連接代理 | 1.1 |
| LINK | 建立和資源之間的聯(lián)系 | 1.0 |
| UNLINE | 斷開(kāi)與資源的聯(lián)系 | 1.0 |
HTTP報(bào)文
HTTP通訊過(guò)程中用來(lái)交互傳輸數(shù)據(jù)的信息稱(chēng)之為報(bào)文,請(qǐng)求端發(fā)出的稱(chēng)之為請(qǐng)求報(bào)文,響應(yīng)端的稱(chēng)之為響應(yīng)報(bào)文,而HTTP的報(bào)文則是由多行字符串組合而成,其中回車(chē)符和換行符來(lái)區(qū)分每一個(gè)報(bào)文的內(nèi)容及其屬性以及報(bào)文首部和報(bào)文主體,報(bào)文整體組成大概如下:

從上圖我們大概可以看出來(lái)報(bào)文整體通過(guò)空行拆分為報(bào)文首部和報(bào)文主體,并且請(qǐng)求報(bào)文和響應(yīng)報(bào)文都是一樣的結(jié)構(gòu),但是我們也可以看出來(lái),請(qǐng)求報(bào)文和響應(yīng)報(bào)文都包含通用首部字段和實(shí)體首部字段,而請(qǐng)求報(bào)文則是多了請(qǐng)求行和請(qǐng)求首部字段,響應(yīng)報(bào)文則是在相同位置變成了狀態(tài)行和響應(yīng)首部字段,那么這些組成分別有什么作用呢?
請(qǐng)求行
首先請(qǐng)求行僅僅存在于請(qǐng)求報(bào)文中,用來(lái)記錄當(dāng)前發(fā)起請(qǐng)求的信息,比如URI,請(qǐng)求方法,HTTP版本等
狀態(tài)行
狀態(tài)行僅僅存在于響應(yīng)報(bào)文中,內(nèi)部記錄了響應(yīng)結(jié)果的狀態(tài)碼,成功/失敗的原因說(shuō)明,以及服務(wù)端返回的HTTP版本等
請(qǐng)求首部/響應(yīng)首部/通用首部/實(shí)體首部
四種最常見(jiàn)的首部一般包含了請(qǐng)求/響應(yīng)過(guò)程中各種屬性及其對(duì)應(yīng)的參數(shù)值,比如跨域請(qǐng)求,緩存過(guò)期時(shí)間等屬性
其他首部
一般情況下HTTP內(nèi)置的首部和組成是由上面的四種常見(jiàn)首部和請(qǐng)求行/狀態(tài)行組成的,但是不要忘記,我們HTTP可以配合Cookie等實(shí)現(xiàn)功能,其他首部中包含了其他的非HTTP規(guī)范定義的首部信息比如Cookie首部信息等
HTTP首部
上面我們分析了報(bào)文的組成部分,其中有四個(gè)首部是最常見(jiàn)的首部,分別是請(qǐng)求首部、響應(yīng)首部、通用首部和實(shí)體首部,那么我們看下四種首部分別是用來(lái)做什么的,以及HTTP規(guī)范給我們定義了那些首部字段:
通用首部
所謂通用首部,即請(qǐng)求報(bào)文和響應(yīng)報(bào)文都可以配置的首部字段,一般都是超時(shí)時(shí)間、緩存等這些通用首部字段,HTTP規(guī)范定義的通用首部字段共9個(gè),如下:
| 首部字段 | 說(shuō)明 |
|---|---|
| Cache-Control | 緩存行為控制 |
| Connection | 跳轉(zhuǎn)首部、連接的管理 |
| Date | 創(chuàng)建報(bào)文的日期時(shí)間 |
| Pragma | 報(bào)文指令 |
| Trailer | 報(bào)文末端首部一覽 |
| Transfer-Encoding | 報(bào)文主體的傳輸編碼方式 |
| Upgrade | 升級(jí)為指定的其他協(xié)議 |
| Via | 代理服務(wù)器相關(guān)信息 |
| Warning | 錯(cuò)誤信息通知 |
請(qǐng)求首部字段
當(dāng)客戶(hù)端發(fā)起請(qǐng)求的時(shí)候特有的首部,可用來(lái)指定請(qǐng)求的方式,請(qǐng)求的策略等,HTTP定義的請(qǐng)求首部字段共19個(gè),如下:
| 首部字段 | 說(shuō)明 |
|---|---|
| Accept | 用戶(hù)代理可以處理的媒體類(lèi)型 |
| Accept-Charset | 優(yōu)先的編碼字符集 |
| Accept-Encoding | 優(yōu)先的內(nèi)容編碼 |
| Accept-Language | 優(yōu)先的語(yǔ)言 |
| Authorization | web認(rèn)證信息 |
| Expect | 期望服務(wù)端的行為 |
| From | 郵箱地址 |
| Host | 請(qǐng)求資源所在服務(wù)器 |
| If-Match | 比較實(shí)體標(biāo)記(ETag) |
| If-Modified-Since | 比較資源的更新時(shí)間 |
| If-None-Match | 比較實(shí)體標(biāo)記(與 If-Match 相反) |
| If-Range | 資源未更新時(shí)發(fā)送實(shí)體 Byte 的范圍請(qǐng)求 |
| If-Unmodified-Since | 比較資源的更新時(shí)間(與If-Modified-Since相反) |
| Max-Forwards | 最大傳輸逐跳數(shù) |
| Proxy-Authorization | 代理服務(wù)器要求客戶(hù)端的認(rèn)證信息 |
| Range | 實(shí)體的字節(jié)范圍請(qǐng)求 |
| Referer | 對(duì)請(qǐng)求中 URI 的原始獲取方 |
| TE | 傳輸編碼優(yōu)先級(jí) |
| User-Agent | HTTP 客戶(hù)端程序信息 |
響應(yīng)首部字段
HTTP交互過(guò)程中,服務(wù)端返回給客戶(hù)端的時(shí)候使用的首部,包含服務(wù)端信息、重定向等,在HTTP中定義的有9種,如下:
| 首部字段 | 說(shuō)明 |
|---|---|
| Accept-Ranges | 是否接受字節(jié)范圍請(qǐng)求 |
| Age | 推算資源創(chuàng)建經(jīng)過(guò)時(shí)間 |
| ETag | 資源的匹配信息 |
| Location | 令客戶(hù)端重定向至此URI |
| Proxy-Authenticate | 代理服務(wù)器對(duì)客戶(hù)端的認(rèn)證信息 |
| Retry-After | 再次發(fā)起請(qǐng)求的時(shí)機(jī)要求信息 |
| Server | 服務(wù)器的安裝信息 |
| Vary | 代理服務(wù)器緩存的管理信息 |
| WWW-Authenticate | 服務(wù)器對(duì)客戶(hù)端的認(rèn)證信息 |
實(shí)體首部字段
實(shí)體首部字段是HTTP交互過(guò)程中,為了傳輸實(shí)體而出現(xiàn)的屬性配置,HTTP指定了10種實(shí)體首部,如下:
| 首部字段 | 說(shuō)明 |
|---|---|
| Allow | 當(dāng)前資源支持的請(qǐng)求方式 |
| Content-Encoding | 實(shí)體的編碼方式 |
| Content-Language | 實(shí)體對(duì)應(yīng)的語(yǔ)言 |
| Content-Length | 實(shí)體傳輸需要的byte大小 |
| Content-Location | 用來(lái)替代資源的URI |
| Content-MD5 | 實(shí)體的報(bào)文摘要 |
| Content-Range | 實(shí)體主體的傳輸位置范圍 |
| Content-Type | 實(shí)體主體的媒體類(lèi)型 |
| Expires | 實(shí)體主體過(guò)期時(shí)間 |
| Last-Modified | 資源的最后修改時(shí)間 |
而其中有部分首部在日常中經(jīng)常使用,下面我們就看看幾個(gè)常見(jiàn)的首部字段以及可選值:
Cache-Control:緩存行為控制
可用的值如下(請(qǐng)求):
| 屬性 | 參數(shù) | 說(shuō)明 |
|---|---|---|
| no-cache | 強(qiáng)制要求服務(wù)端請(qǐng)求真實(shí)數(shù)據(jù)進(jìn)行返回 | |
| no-store | 強(qiáng)制要求請(qǐng)求和響應(yīng)不做任何數(shù)據(jù)緩存 | |
| max-age | 秒(必須) | 可以保持響應(yīng)的最大時(shí)間 |
| max-stale | 秒 | 接受已經(jīng)過(guò)期的響應(yīng)(xxx秒內(nèi)的響應(yīng)) |
| min-fresh | 秒(必須) | 緩存過(guò)期,但是在指定時(shí)間內(nèi)客戶(hù)端依然認(rèn)可此數(shù)據(jù) |
| no-transform | 代理不可更改媒體類(lèi)型 | |
| only-if-cached | 僅僅選擇從緩存獲取數(shù)據(jù),沒(méi)有即504 | |
| cache-extension | 從新標(biāo)記獲取數(shù)據(jù)(token) |
可用的響應(yīng)值如下:
| 屬性 | 參數(shù) | 說(shuō)明 |
|---|---|---|
| public | 公開(kāi)對(duì)任何客戶(hù)端都有效的緩存 | |
| private | 僅針對(duì)指定客戶(hù)端緩存有效,彼此客戶(hù)端不干擾 | |
| no-cache | 每次都確認(rèn)數(shù)據(jù)是否有效 | |
| no-store | 請(qǐng)求或者響應(yīng)強(qiáng)制都不緩存數(shù)據(jù) | |
| no-transform | 代理不可更改媒體類(lèi)型 | |
| must-revalidate | 可緩存但必須再向源服務(wù)器進(jìn)行確認(rèn) | |
| proxy-revalidate | 要求中間緩存服務(wù)器對(duì)緩存的響應(yīng)有效性再進(jìn)行確認(rèn) | |
| max-age | 秒(必須) | 可以保持響應(yīng)的最大時(shí)間 |
| s-maxage | 秒(必須) | 公共緩存服務(wù)器響應(yīng)的最大Age值 |
| cache-extension | 新指令標(biāo)記(token) |
Warning:錯(cuò)誤信息通知
在HTTP1.1中定義的警告碼如下:
| 警告碼 | 警告內(nèi)容 | 說(shuō)明 | |
|---|---|---|---|
| 110 | Response is stale(響應(yīng)已過(guò)期) | 代理返回已過(guò)期的資源 | |
| 111 | Revalidation failed(驗(yàn)證失?。?/td> | 代理在驗(yàn)證資源有效性時(shí)失敗(服務(wù)器無(wú)法到達(dá)) | |
| 112 | Disconnection operation(斷開(kāi)連接操作) | 代理與互聯(lián)網(wǎng)連接被故意切斷 | |
| 113 | Heuristic expiration(試探性過(guò)期) | 響應(yīng)的使用期超過(guò)24小時(shí)(有效緩存時(shí)間在24h以上的情況) | |
| 199 | Miscellaneous warning(雜項(xiàng)警告) | 任意的警告 | |
| 214 | Transformation applied(使用了轉(zhuǎn)換) | 代理對(duì)內(nèi)容編碼或媒體類(lèi)型等執(zhí)行了轉(zhuǎn)換等操作 | |
| 299 | Miscellaneous persistent warning(持久雜項(xiàng)警告) | 任意的警告 |
Accept:用戶(hù)代理可以處理的媒體類(lèi)型
Accept屬性可以通知服務(wù)器,用戶(hù)代理能接受/處理的媒體文件類(lèi)型以及優(yōu)先級(jí),常見(jiàn)的如下:
| 媒體文件類(lèi)型 | 可選值(部分) |
|---|---|
| 文本文件 | text/html, text/plain, text/css,application/xhtml+xml, application/xml |
| 圖片文件 | image/jpeg, image/gif, image/png |
| 視頻文件 | video/mpeg, video/quicktime |
| 二進(jìn)制文件 | application/octet-stream, application/zip |
其中Accept還可以指定優(yōu)先級(jí),使用q=來(lái)額外表示權(quán)重值,用分號(hào)分割,權(quán)重范圍0-1,1為最大值,可以為三位小數(shù),不指定權(quán)重時(shí)默認(rèn)q=1.0
Accept-Encoding:優(yōu)先的內(nèi)容編碼
Accept-Encoding用來(lái)通知服務(wù)器用戶(hù)代理支持的內(nèi)容編碼及優(yōu)先級(jí)順序,常見(jiàn)的編碼如下:
| 編碼類(lèi)型 | 說(shuō)明 |
|---|---|
| gzip | 傳輸數(shù)據(jù)由文本壓縮程序gzip生成對(duì)應(yīng)編碼數(shù)據(jù) |
| compress | 由 UNIX 文件壓縮程序 compress 生成的編碼格式,采用 Lempel-Ziv-Welch 算法(LZW) |
| deflate | 組合使用 zlib 格式(RFC1950)及由 deflate 壓縮算法生成的編碼 |
| identity | 不執(zhí)行任何壓縮等操作的默認(rèn)編碼 |
HTTP狀態(tài)碼
了解了HTTP的報(bào)文組成和組成HTTP請(qǐng)求/響應(yīng)的首部信息,在完成了HTTP請(qǐng)求后,我們會(huì)根據(jù)響應(yīng)報(bào)文來(lái)確定用戶(hù)操作是否規(guī)范,而依據(jù)則是響應(yīng)報(bào)文中很重要的一部分--HTTP狀態(tài)碼
而在HTTP規(guī)范中,響應(yīng)碼以三位數(shù)的短數(shù)值和簡(jiǎn)要的信息表示,而三位數(shù)值的第一位數(shù)(百位數(shù))決定了響應(yīng)的類(lèi)型,后兩位數(shù)則是當(dāng)前類(lèi)型的具體子類(lèi)型,目前HTTP中的code主要分為以下五種:
| 響應(yīng)code | 類(lèi)型 | 響應(yīng)原因短語(yǔ) |
|---|---|---|
| 1XX | Informational(信息性狀態(tài)碼) | 接收的請(qǐng)求正在處理 |
| 2XX | Success(成功狀態(tài)碼) | 請(qǐng)求正常處理完畢 |
| 3XX | Redirection(重定向狀態(tài)碼) | 需要進(jìn)行附加操作以完成請(qǐng)求 |
| 4XX | Client Error(客戶(hù)端錯(cuò)誤狀態(tài)碼) | 服務(wù)器無(wú)法處理請(qǐng)求 |
| 5XX | Server Error(服務(wù)器錯(cuò)誤狀態(tài)碼) | 服務(wù)器處理請(qǐng)求出錯(cuò) |
而這五大類(lèi)型的具體子類(lèi)在RFC2616 上的 HTTP 狀態(tài)碼就達(dá) 40 種,后續(xù)擴(kuò)展了數(shù)十種,而在我們開(kāi)發(fā)過(guò)程中,絕大多數(shù)幾乎見(jiàn)不到,所以接下來(lái)我們看看開(kāi)發(fā)中能碰到的十來(lái)種常見(jiàn)的狀態(tài)碼
200:完全成功
當(dāng)HTTP的返回碼為200的時(shí)候,恭喜你,整個(gè)流程沒(méi)有出現(xiàn)任何問(wèn)題,完全成功!說(shuō)明客戶(hù)端的請(qǐng)求信息被服務(wù)端正常處理并且成功返回給了客戶(hù)端
204:Not Content
當(dāng)前的狀態(tài)碼代表客戶(hù)端的請(qǐng)求已經(jīng)被服務(wù)端處理完畢,并且服務(wù)端也給了響應(yīng)信息,但是當(dāng)前的返回信息中不包含響應(yīng)信息主體
206:Partial Content
當(dāng)前返回碼比較特殊,因?yàn)橹粫?huì)出現(xiàn)在客戶(hù)端的請(qǐng)求是部分范圍請(qǐng)求并且成功響應(yīng)的時(shí)候,比如報(bào)文中包含 Content-Range 進(jìn)行部分范圍請(qǐng)求的操作
301:Moved Permanently
當(dāng)前響應(yīng)碼代表著請(qǐng)求的資源已經(jīng)被永久性重定向,即我們請(qǐng)求的資源在服務(wù)端的URI已經(jīng)變更,服務(wù)端期望我們使用Loaction首部字段等方式保存新的URI地址,后續(xù)使用當(dāng)前URI進(jìn)行訪問(wèn)
302:Found
當(dāng)前響應(yīng)碼和301有類(lèi)似的地方,即都是請(qǐng)求資源被重定向了,但是區(qū)別在于301是請(qǐng)求的資源URI的永久性移動(dòng)變更,而302響應(yīng)碼代表著當(dāng)前請(qǐng)求的時(shí)候這個(gè)資源的URI被變更了,但是這個(gè)變更只是臨時(shí)的,僅僅本次請(qǐng)求期望使用變更后的URI請(qǐng)求
303:See Other
如果是302響應(yīng)碼是臨時(shí)性URI變更的話,那么303就是302的升級(jí)版,因?yàn)?03響應(yīng)碼擁有302響應(yīng)碼的全部功能,但是更嚴(yán)格的是,303告訴你URI對(duì)應(yīng)的資源中存在其他URI,并且嚴(yán)格要求你使用GET方式去重新訪問(wèn)新的URI
307:Temporary Redirect
303作為302的升級(jí)版已經(jīng)出現(xiàn)了,但是在嚴(yán)格程度上還遠(yuǎn)遠(yuǎn)不夠,因?yàn)榘凑誋TTP規(guī)范,302,303的響應(yīng)碼都是希望用戶(hù)不要把POST請(qǐng)求變?yōu)镚ET,但是不能束縛瀏覽器或者用戶(hù)行為,而307作為嚴(yán)格的執(zhí)行者,只要響應(yīng)了當(dāng)前的code,瀏覽器會(huì)遵照約定,不能把POST請(qǐng)求變成GET去訪問(wèn)資源
400:Bad Request
400響應(yīng)碼可能是最詭異的響應(yīng)碼之一了,開(kāi)發(fā)的過(guò)程中需要格外注意當(dāng)前的響應(yīng)碼,因?yàn)楫?dāng)前響應(yīng)碼雖然是告訴我們報(bào)文請(qǐng)求中存在著語(yǔ)法錯(cuò)誤,但是瀏覽器會(huì)按照200對(duì)待此響應(yīng)
401:Unauthorized
當(dāng)響應(yīng)401響應(yīng)碼的時(shí)候,即代表服務(wù)端會(huì)發(fā)起質(zhì)詢(xún)的方式的一個(gè)認(rèn)證請(qǐng)求,告訴我們需要進(jìn)行認(rèn)證才可以訪問(wèn),這個(gè)時(shí)候我們需要將信息填寫(xiě)并確定才可以拿到具體的結(jié)果
403:Forbidden
403響應(yīng)碼在開(kāi)發(fā)的時(shí)候也是經(jīng)常出現(xiàn),經(jīng)常讓人琢磨不透原因,因?yàn)榇隧憫?yīng)碼出現(xiàn)即代表我們的請(qǐng)求被服務(wù)端拒絕訪問(wèn)了,但是服務(wù)端經(jīng)常不會(huì)返回給具體的響應(yīng)實(shí)體描述
404:Not Found
404作為開(kāi)發(fā)過(guò)程中接觸最多的響應(yīng)碼之一,對(duì)此已經(jīng)非常熟悉,此響應(yīng)碼代表服務(wù)端無(wú)法找到具體的請(qǐng)求資源
501:Internal Server Error
501狀態(tài)碼表明當(dāng)前服務(wù)端在執(zhí)行過(guò)程中發(fā)生了錯(cuò)誤,也可能是某個(gè)流程突發(fā)bug
503:Service Unavailable
503狀態(tài)碼代表我們請(qǐng)求服務(wù)端的過(guò)程中,服務(wù)端可能超過(guò)了負(fù)載或者服務(wù)端的機(jī)器已經(jīng)宕機(jī)又或者正在停服更新?tīng)顟B(tài)等
BASIC 認(rèn)證
上面有分析開(kāi)發(fā)和日常使用過(guò)程中最常見(jiàn)的十?dāng)?shù)種響應(yīng)碼及其含義,其中401是代表我們需要經(jīng)過(guò)認(rèn)證,那么接下來(lái)我們了解下HTTP協(xié)議給我們提供的幾種認(rèn)證方式吧,其中HTTP1.1版本默認(rèn)支持的認(rèn)證方式有如下:
BASIC:基礎(chǔ)認(rèn)證、DIGEST:信息摘要認(rèn)證、SSL:基于ssl協(xié)議的客戶(hù)端認(rèn)證、FormBase:基于表單的認(rèn)證方式
那么我們從BASIC認(rèn)證開(kāi)始,此認(rèn)證是HTTP1.0就開(kāi)始存在的認(rèn)證方式,比較古老,現(xiàn)在的web開(kāi)發(fā)過(guò)程中基本已經(jīng)不使用此方式,但是一些古老的工程依然存在(比如我之前的某企業(yè)的工程),其認(rèn)證過(guò)程大概如下:
1).發(fā)起請(qǐng)求,服務(wù)端返回401,并且返回帶 WWW-Authenticate 首部字段的響應(yīng)
2).客戶(hù)端接受到401響應(yīng)后,將用戶(hù)ID和密碼直接明文方式填寫(xiě),而發(fā)送的字符串會(huì)以id:密碼進(jìn)行組合后,經(jīng)過(guò)base64編碼為字符串發(fā)送

需要注意的是此認(rèn)證方式弊端很多,首先是明文填寫(xiě),發(fā)送的過(guò)程中也沒(méi)有加密,僅僅是組合+base64進(jìn)行編碼,最重要的是此認(rèn)證方式基本上沒(méi)有注銷(xiāo)的選項(xiàng),所以基本沒(méi)人使用了
DIGEST 認(rèn)證
為彌補(bǔ) BASIC 認(rèn)證存在的弱點(diǎn),從 HTTP/1.1 起就有了 DIGEST 認(rèn) 證。DIGEST 認(rèn)證同樣使用質(zhì)詢(xún) / 響應(yīng)的方式 ,但是不會(huì)和BASIC一樣直接發(fā)送明文密碼,請(qǐng)求過(guò)程如下:
1).發(fā)送請(qǐng)求,服務(wù)端返回401,并且返 回帶 WWW-Authenticate 首部字段的響應(yīng) ,此字段中包含響應(yīng)方式對(duì)應(yīng)的質(zhì)詢(xún)碼(首部字段 WWW-Authenticate 內(nèi)必須包含 realm 和 nonce 這兩個(gè)字段的 信息。客戶(hù)端就是依靠向服務(wù)器回送這兩個(gè)值進(jìn)行認(rèn)證的)
2).此時(shí)客戶(hù)端接受到401的響應(yīng)以后,可以拿到DIGEST認(rèn)證需要的相關(guān)信息,比如realm和nonce,而完成此認(rèn)證還需要username和uri,這部分內(nèi)容填寫(xiě)完畢后開(kāi)始進(jìn)行計(jì)算發(fā)送給服務(wù)端(這部分進(jìn)行了加密計(jì)算,比較復(fù)雜,可以參考 RFC2617 )
3).接受到到包含首部字段 Authorization 請(qǐng)求的服務(wù)器,會(huì)確認(rèn)認(rèn) 證信息的正確性。認(rèn)證通過(guò)后則返回包含 Request-URI 資源的響應(yīng)

但是需要注意的是,此認(rèn)證雖然改善了basic認(rèn)證的明文問(wèn)題,但是不能防止客戶(hù)端被攻擊或者偽造的情況,使用起來(lái)也不能定制化,所以和basic一樣,很少有人使用
SSL 客戶(hù)端認(rèn)證
SLL認(rèn)證是借助HTTPS的客戶(hù)端證書(shū)完成用戶(hù)身份認(rèn)證,服務(wù)端也可以確認(rèn)當(dāng)前請(qǐng)求的客戶(hù)端是不是符合規(guī)范的客戶(hù)端,此種方式一般都是選擇HTTPS,是目前主流的安全的認(rèn)證方式之一,認(rèn)證步驟大概如下:
1).接受到客戶(hù)端的請(qǐng)求后,服務(wù)端發(fā)送送 Certificate Request 報(bào)文,要求客戶(hù)端提供客戶(hù)端證書(shū)
2).用戶(hù)在客戶(hù)端選擇證書(shū),客戶(hù)端會(huì)把證書(shū)信息發(fā)送給服務(wù)端
3).服務(wù)端會(huì)對(duì)證書(shū)進(jìn)行驗(yàn)證簽名等操作確定客戶(hù)端證書(shū)的有效性,通過(guò)后會(huì)按照證書(shū)內(nèi)部的公開(kāi)密鑰開(kāi)始進(jìn)行HTTPS通信
表單認(rèn)證
HTTPS雖然是能保證相對(duì)的安全性,但是在使用和操作上繁瑣,并且更重要的一點(diǎn)是,證書(shū)是要錢(qián)的,在企業(yè)開(kāi)發(fā)中,一般只會(huì)給比較私密的接口或者服務(wù)比如交易等進(jìn)行HTTPS通信,其他部分基本也不會(huì)選擇HTTPS,這個(gè)時(shí)候就需要一種自定義的安全擴(kuò)展認(rèn)證方式,而HTTP給我們提供了表單認(rèn)證,也是目前互聯(lián)網(wǎng)企業(yè)使用最多的方式
使用表單認(rèn)證基本是企業(yè)內(nèi)部自己開(kāi)發(fā)和定義具體的認(rèn)證響應(yīng)流程,而具體使用僅僅是在網(wǎng)頁(yè)提供表單填寫(xiě)相關(guān)信息,提交給服務(wù)端,服務(wù)端根據(jù)自定義的規(guī)則解析或者解密并響應(yīng),此種方式主要在于靈活,比如表單填寫(xiě)的信息可任意,文本形式可以任意,而請(qǐng)求過(guò)程可以自定義也可以選擇表單的submit提交,服務(wù)端靈活度更高,是目前主流并且推薦的認(rèn)證方式