1. 簡介
HTTP 協議是 Hyper Text Transfer Protocol(超文本傳傳輸協議)的縮寫,是用於從萬維網服務器傳輸超文本到本地瀏覽器的傳送協議。HTTP 一般架構在 TCP 傳輸協議之上,以下圖所示。有時出於安全的考慮,HTTP 還須要通過 TLS 或 SSL 層的封裝,架構在 SSL 層之上的 HTTP 協議一般稱爲 HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)協議。
html
HTTP 協議是一個無狀態的協議,即客戶端向服務器端發送出請求時,服務器並無存儲關於該客戶端和請求的任何狀態信息。即使同一個客戶端在幾秒鐘內再次請求經過一個對象,服務器也不會響應說本身剛剛給它發送了這個對象。相反,服務器會從新發送這個對象,由於它已經完全忘記本身早先作過什麼了,同一個客戶端的此次請求和上次請求沒有任何關係。web
HTTP 1.1 支持持續鏈接機制,即客戶端和服務端創建 TCP 鏈接後,後續相關聯的 HTTP 請求能夠重複利用已經創建起來的 TCP 鏈接,不只整個 Web 頁面(包括基本的 HTML 文件和其餘對象)可使用這個持續的 TCP 鏈接來完成 HTTP 請求和響應,並且同一個服務器內的多個 Web 頁面也能夠經過同一個持續 TCP 鏈接來請求和響應。一般狀況下,這個持續的 TCP 鏈接會在空閒一段特定的時間後關閉,而這個最大空閒時間是能夠設置的。算法
持續鏈接的 TCP 鏈接通常能夠分爲兩類:帶流水線和不帶流水線。在不帶流水線的持續鏈接下,用戶的 HTTP 請求只能在上一個請求獲得響應後才能發出;帶流水線的持續鏈接則沒有這個限制,客戶端在 Web 頁面發現引用時就能夠發起 HTTP 請求,無須考慮上一個請求的響應消息是否已經收到。數據庫
不帶流水線的持續性鏈接示意圖
帶流水線的持續性鏈接示意圖
HTTP 1.1 中,客戶端和服務器都默認支持持續的帶流水線的 TCP 鏈接。若是客戶端使用 HTTP 1.1 協議而又不但願使用持續的 TCP 鏈接,則能夠將請求消息中的 Connection 頭的值設置爲 close;同理,使用 HTTP 1.1 的服務器若是不但願使用持續的 TCP 鏈接,也能夠將響應消息中的 Connection 頭的值設置爲 close。瀏覽器
2. 基本工做方式
HTTP 協議是一個標準的 "請求+響應" 協議,即客戶端與服務器創建鏈接後,就向服務器發送一個 HTTP 請求,告訴服務器客戶要操做什麼,對什麼進行操做以及怎麼操做。服務器在完成請求分析後,通知客戶端能不能作,爲何不能作。
緩存
2.1 HTTP 之請求消息 Request
客戶端發送一個 HTTP 請求到服務器的請求消息包括如下格式:安全
- 請求行(request line)、請求頭部(header)、空行和請求數據四個部分組成。
請求行以一個方法符號開頭,以空格分開,後面跟着請求的 URI 和協議的版本。服務器
Get 請求例子,使用 Charles 抓取的 request:
GET /562f25980001b1b106000338.jpg HTTP/1.1
Host: img.mukewang.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept: image/webp,image/*,*/*;q=0.8
Referer: http://www.imooc.com/
Accept-Encoding: gzip, deflate, sdch
Accpet-Language: zh-CN,zh;q=0.8
- 第一部分:請求行,用來講明請求類型,要訪問的資源以及所使用的 HTTP 版本。
GET 說明請求類型爲 GET,/562f25980001b1b106000338.jpg 爲要訪問的資源,該行的最後一部分說明使用的是 HTTP 1.1 版本。網絡
- 第二部分:請求頭部,緊接着請求行(即第一行)以後的部分,用來講明服務器要使用的附加信息。
從第二行起 爲請求頭部,HOST 將指出請求的目的地。User-Agent,服務器端和客戶端腳本都能訪問它,它是瀏覽器類型檢測邏輯的重要基礎。該信息由你的瀏覽器來定義,而且在每一個請求中自動
發送等等。架構
即便第四部分的請求數據爲空,也必須有空行。
- 第四部分:請求數據也叫主體,能夠添加任意的其餘數據。
這個例子的請求數據爲空。
POST 請求例子,使用 Charles 抓取的 request:
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
- 第一部分:請求行,第一行說明是 POST 請求,以及 HTTP 1.1 版本
- 第二部分:請求頭部,第二行至第六行
- 第三部分:空行,第七行是空行
- 第四部分:請求數據,第八行
2.1.1 請求方式
- GET:請求獲取由 URI 所指定的資源。這個資源一般包含在響應消息的實體中返回給請求者。
- HEAD:此方法和 GET 方法相似,只不過服務器不能在響應消息裏包含資源內容,只返回頭信息。
- POST:請求源服務器將請求消息中包含的實體做爲請求資源的一個從屬物。POST 能夠完成如下功能:
- 對服務器上已存在的資源進行註釋;
- 發佈消息給一個公告板、新聞組、郵件列表、或者類似的文章組;
- 提供一個數據塊,如提交一個表單給一個數據處理過程;
- 經過追加操做來擴展數據庫。
- PUT:請求服務器把請求裏的實體存儲爲 URI 所標的資源。若是 URI 所指定的資源已經在源服務器上存在,那麼此請求裏的實體內容應該是此 URI 所指定資源的修改版本;若是請求 URI 指定的資源不存在,源服務器根據請求裏的實體內容建立一個使用此 URI 所標識的資源。
- DELETE:請求源服務器刪除 URI 指定的資源。此方法可能會在源服務器上被人爲干涉,因此服務器返回客戶端的狀態碼不必定成功。
- TRACE:用於觸發遠程的、應用層的請求響應迴路。這個方法一般讓客戶端測試其連到服務器的網絡通路,收到請求的每個代理服務器和網關服務器不斷轉發請求,同時向客戶端發出響應消息,直到最後的接收者。TRACE 請求不能包含實體。
- CONNECT:用於一個代理服務器,使其提供隧道服務。
2.2 HTTP 之響應消息 Response
通常狀況下,服務器接收並處理客戶端發過來的請求後會返回一個 HTTP 的響應消息。
HTTP 響應也由 四個部分組成,分別是:狀態行、消息報頭、空行和響應正文。
例子:
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8
<html>
<head></head>
<body>
<!--body goes here-->
</body>
</html>
- 第一部分:狀態行,由 HTTP 協議版本號,狀態碼,狀態消息 三部分組成。
第一行爲狀態行,(HTTP/1.1) 代表 HTTP 版本爲 1.1 版本,狀態碼爲 200,狀態消息爲 (OK)
- 第二部分:消息報頭,用來講明客戶端要使用的一些附加信息。
第二行和第三行爲消息報頭,Data:生成響應的日期和時間;Content-Type:制定了 MIME 類型和 HTML(text/html),編碼類型是 UTF-8
空行後面的 html 部分爲響應正文。
2.2.1 狀態碼
- 1xx:指示信息 -- 表示請求已接收,繼續處理。
- 2xx:成功 -- 表示請求已被成功接收、理解、接受。
- 3xx:重定向 -- 要完成請求必須進行更進一步的操做。
- 4xx:客戶端錯誤 -- 請求有語法錯誤或請求沒法實現。
- 5xx:服務器端錯誤 -- 服務器未能實現合法的請求。
典型的狀態號及其含義以下:
100 |
Continue |
客戶端必須繼續發出請求 |
200 |
OK |
客戶端請求成功 |
202 |
Accepted |
接受和正在處理,但處理未完成 |
203 |
None-Authoritative Information |
返回的信息不肯定或不完整 |
206 |
Partial Content |
客戶端發送了帶 Range 的 GET 請求,服務器端正確地返回了此範圍內的數據 |
301 |
Moved Permanently |
請求的數據已永久刪除或永久地轉移至其餘地方 |
302 |
Found |
指出被請求的文檔已經臨時移動到別處,此文檔的新 URL 在 Location 響應頭中給出 |
304 |
Not Modified |
被緩存的版本是最新的,能夠繼續使用 |
400 |
Bad Request |
客戶端請求語法有錯誤,不能被服務器理解 |
401 |
Unauthorized |
表示客戶端訪問的資源受用戶名和密碼的保護,提示客戶端應從新發出一個帶有 Authorization 頭的請求信息 |
403 |
Forbidden |
服務器拒絕提供服務 |
404 |
Not Found |
請求的資源不存在 |
500 |
Internal Server Error |
服務器內部發生錯誤 |
502 |
Bad Gateway |
網關錯誤 |
503 |
Server Unavailable |
服務器當前不能處理請求,一段時間後可恢復正常 |
2.3 HTTP 之頭部
HTTP 的頭部分類大體有 4 種:通用頭,請求頭,實體頭以及響應頭。
2.3.1 通用頭
通用頭不是應用於請求消息中的特定實體,而是應用於整個請求消息,一般既適用於請求消息,也適用於響應消息。
通用頭有 Connection,Connection 中的 "Keep-Alive" 代表了 TCP 鏈接是一個持續鏈接。
典型的通用頭以下:
- Connection:指示客戶端與服務器在進行 HTTP 通訊時如何處理 TCP 鏈接,若是 Connection 的值爲 close,則表示本次 HTTP 請求響應後結束 TCP 鏈接;若是 Connection 的值爲 Keep-Alive(HTTP 1.1 下爲默認),則表示 TCP 鏈接一直有效。
- Date:Date 通用頭域代表消息產生的日期和具體時間。
- Pragma:被用於包含特定執行指令,這些指令可能被應用於請求和響應消息傳遞過程當中的任何接收者。最經常使用的爲
Pragma: no-cache
,表示對請求的實體內容不予緩存。
- Transfer-Encoding:指示整個消息主體的傳輸編碼方式,主要是爲了實如今接收端和發送端之間進行安全的數據傳輸。好比
Transfer-Encoding: chunked
表示消息主體採用塊編碼的方式。
- Upgrade:客戶端能夠經過它表示本身但願進行協議轉換(好比從 HTTP 一個版本轉換到另外一個版本),若是服務器贊成的話會切換到這個指定的協議,這個協議通常是指應用層協議。
- Via:Via 用來指明請求和響應消息在客戶端和服務器之間傳遞時所通過的代理和網關以及相關的中間協議。好比 HTTP 1.0 的請求消息發送給代理 A,A 使用 HTTP 1.1 將消息轉發給網關 B,B 再發送給源服務器,這時源服務器看到 Via 頭域爲
Via: 1.0 A, 1.1 B
。
- Warning:攜帶相關警告信息,好比能夠被代理和網關用來警告客戶端所接收內容的過時狀態以及警告客戶端實體內容的編碼格式發生了變化等。
2.3.2 請求頭
請求頭主要包含本請求的附加信息以及客戶端的附加信息。
典型的請求頭以下:
- Accept:用於指定本請求所指望的服務器返回響應的媒體類型。好比
Accept: audio/*; q=0.2, audio/basic
代表用戶客戶端但願接收到 audio/basic 的媒體,但也能夠接受其餘任何 audio 類型(audio/* 表示),但偏好程度只有 audio/basic 的 20%(這裏的 q 是一個表示喜歡程度的質量參數)。
- Accept-Charset:用來指定客戶端能接受什麼樣的字符集響應。好比
Accept-Charset: iso-8859-5
。
- Accept-Encoding:和 Accept 頭類似,但 Accept-Encoding 限定的是客戶端能夠從服務器接收的內容編碼。好比
Accept-Encoding: compress, gzip
。
- Accept-Language:和 Accept 頭類似,但 Accept-Language 限定的是客戶端能夠從服務器接收的天然語言。好比
Accept-Language: en-us
。
- Accept-Range:指示客戶端但願從服務器收到的內容的字節範圍。
- Authorization:客戶端的某些訪問要求服務器受權,一般客戶端會先在服務器的響應消息中收到包含有受權證書的 WWW-Authenticate 頭,而後在須要受權的請求消息裏包含一個帶有這個受權證書的 Authorization 請求頭。
- From:包含客戶端當前操做用戶的 E-mail 地址,表明的是具體的用戶,而不是發出請求的主機。
- Host:標識請求資源的網絡主機和端口號,Host 頭的值表明源服務器或網關的命名受權,通常會在用戶訪問的 URL 中標明。好比對
http://www.netitv.com/i_movie/movie.shtml
的請求在 HTTP 消息裏經過如下形式表示:
- GET netitv.com/i_movie/movie.shtml HTTP/1.1
- Host: www.netitv.com
- 其中 www.neitv.com 就是主機名
- If-Match:與 ETag 一塊兒用來判斷已緩存的內容是否被修改過。好比,客戶端在獲取內容時會獲取一個與內容相關的實體標籤 ETag(內容變化會使 ETag 變化),下次再請求一樣內容時,會在請求頭的 If-Match 中包含這個 ETag,而後發給可能存有更新內容的服務器。服務器將收到的 ETag 與本地目前的 ETag 進行比較,若是匹配返回所請求內容。這種方法在斷點續傳的時候使用較多。
- If-None-Match:與 If-Match 用法相似,結果相反。若是 If-None-Match 中包含了 ETag 的值,服務器在進行比較後發現若是不匹配,則返回所請求的內容,不然不返回相關內容。這種方法在網頁刷新的時候使用較多。
- If-Modified-Since:當客戶端請求服務器判斷本身緩存的內容是否變化時,能夠設置 If-Modified-Since 頭,若是服務器上的內容修改時間比這個頭的時間值還要新,那麼將返回新的內容,不然不返回。這個與 If-Unmodified-Since 相似,是用來判斷資源變化的另外一種方式。
- If-Unmodified-Since:與 If-Modified-Since 正好相反,若是服務器上的內容修改時間比這個頭時間的值還要新,則不返回新的內容,不然返回所請求內容。
- If-Range:通常結合 Range 頭一塊兒使用。If-Range 的值能夠是 ETag,也能夠是具體的時間值。若是收到含有 If-Range 頭的服務器發現所請求內容沒有改變,則根據 Range 頭指示的字節範圍進行續傳,不然返回整個文檔內容。
- Max-Forwards:指示此 HTTP 請求能夠途徑的代理服務器或網關個數。每通過一個代理服務器或網關,這個值就會被減 1。若是減到 0,則代理服務器或網關將停止繼續發送。
- Proxy-Authorization:與 Authorization 相似,只不過是須要代理服務器進行受權時才使用。
- Range:客戶端通知服務器只需返回部份內容,以及部份內容的範圍。這對於較大文檔的斷電續傳是頗有幫助的。若是客戶機在一次請求中,只收到了服務器返回的部份內容,則客戶端能夠再發出一個帶 Range 頭的請求,這時服務器將會返回 Range 頭值規定的那部份內容。
- Referer:告訴服務器此次請求是經過點擊哪一個網頁上的超連接轉向過來的。因爲可使用 Telnet 來仿造 HTTP 請求,因此 Referer 是不可靠的。"Referer" 是因爲 HTTP 的做者拼寫錯誤,在實際應用中沿襲下來,不能夠寫成正確的拼寫方式 Referrer。
- User-Agent:用於指定瀏覽器的類型和名字,好比 Mozilla/4.0。
2.3.3 響應頭
響應頭包含響應的附加信息,給出了有關服務器的信息以及請求 URI 所指定資源的訪問機制。
經常使用的響應頭以下:
- Accept-Range:指明服務器對用戶請求範圍的接受程度。好比
Accept-Range: 100-599
。表示服務器只接受請求範圍的第 100 字節到 599 個字節。
- Age:當服務器使用緩存的內容去響應請求時,用該頭部代表該內容從產生到如今通過多長時間。
- ETag:對應實體內容的一個實體標籤,與實體內容緊密相關,實體內容發生任何變化都會使這個頭的值發生變化。
- Location:當客戶端向服務器請求一個內容,但請求消息中 URI 所標識的內容發生了轉移,那麼接收者能將訪問重定向於 Location 指示的 URI,如
Location: http://www.netitv.com/netitv/movie_1.shtml
。
- Proxy-Authenticate:此頭必須被包含在 407 響應(代理認證)裏。此頭域值由一個 challenge 和 parameters 組成,chanllenge 指明瞭認證機制,而 parameters 是一些與此代理相關的參數。
- Retry-After:能夠與 503 (服務不可用)響應一塊兒使用,服務器用它來告知請求端服務不可用的時長。也可與 3xx(重定向)響應一塊兒使用,服務器用它來告知客戶端發送重定向請求以前須要等待的最小時長,好比
Retry-After: 60
。
- Server:包含了源服務器處理請求的軟件信息,好比
Server: Apache
。
- Vary:指定了一些請求頭,這些請求頭可被服務器用來決定緩存的沒有過時的內容可否被容許去響應後續相同的請求,好比請求消息發送到代理服務器,其中 Accept-Encoding 頭是 "gzip",代理服務器向源服務器轉發請求,源服務器給代理服務器返回響應消息,其中 Vary 頭爲
Vary: Accept-Encoding
,此時代理服務器將響應內容與 gzip 一塊兒緩存。若是後續用戶再向代理服務器發送請求時,而且 Accept-Encoding 頭的值是 gzip,代理服務器則能夠直接使用未過時的緩存內容來響應,若是 Accept-Encoding 頭的值是 deflate 或者其餘,則須要從新從源服務器獲取。
- WWW-Authenticate:必須包含在 401(沒有被認證)響應消息中,這個響應頭應至少包含一個 challenge 值來標識認證方案以及一些與所請求的 URI 相關的參數。
2.3.4 實體頭
實體頭包含了與實體內容相關的元數據信息。
典型的實體頭以下:
- Allow:指示可使用的請求方式。好比
Allow: GET, HEAD, PUT
。
- Content-Encoding:指示實體內容以哪一種方式編碼。好比
Content-Encoding: gzip
。
- Content-Language:實體內容的國家語言,好比
Content-Language: zh-ch
表示簡體中文。
- Content-Length:實體內容的大小,好比
Content-Length: 3495
。
- Content-Location:當實體內容的真正 URI 和請求 URI 不一樣時,在消息裏提供這個真正的位置信息。
- Content-MD5:實體內容的 MD5 摘要算法 Base-64 值,以提供實體內容的完整性校驗。服務器能夠經過對實體內容進行 MD5 摘要算法與此頭的值是否相同來肯定接收的請求是否沒有錯誤與改變。
- Content-Range:表示返回的內容是整個實體內容的哪一個部分。好比
Content-Range: 2351-4767/8568
,代表本次響應是實體內容的第 2351 字節到第 4767 字節,8565 是實體內容的總大小。
- Content-Type:服務器在返回內容時須要告訴瀏覽器本響應的內容是什麼類型的。HTTP 中把這種不一樣媒體類型的格式稱爲多媒體文件格式(MIME),而本實體頭指出所傳輸實體內容的 MIME。因爲 Web 服務器不知道所返回的內容文件是哪一種 MIME,因此須要經過對 Web 服務器進行設置,使文件擴展名與 MIME 之間進行映射。好比
Content-Type: text/html; charset=ISO-8859-4
。
- Expires:指示當前內容在什麼時候以後被認爲過時,緩存在爲客戶端請求提供服務時,若是緩存內容已通過期,則不會使用此緩存內容來直接提供服務。好比
Expires: Tue. 17 Jul 2011 18:06:45 GMT
。
- Last-Modified:指定所訪問內容的最後更新時間。