本文是作者原創文章,歡迎轉載,請注明出處 from:@Eric_Lai
reference: 《圖解HTTP》(日) 上野宣
HTTP協議,中文名稱為超文本傳輸協議(HyperText Transfer Protocol),是互聯網上應用最為廣泛的一種網絡協議。在TCP/IP協議族中,普遍認為HTTP協議位于最上層,即第七層(應用層)。因為其位于應用層,所以HTTP協議不涉及數據包(packet)傳遞,其主要的作用是規定網絡上兩臺需要通信的計算機(即服務器和客戶端)的通信格式,HTTP協議默認使用80端口(如果沒有明文指明其他端口,但是80端口出于安全原因操作系統通常會默認禁止用戶自己的程序使用)。
ps:上圖來自維基百科
HTTP發展到今天一共出現了以下幾個版本(按照時間出現先后排序):
- HTTP0.9,1990年問世,目前已過時,僅僅支持GET方法;
- HTTP/1.0,1996年5月發布,至今仍被廣泛使用,第一個在通訊中制定版本號的HTTP協議版本;
- HTTP/1.1,1997年1月發布比1.0版本晚大約半年發布,持久連接默認被采用,能夠很好配合代理服務器工作;
- HTTP/2,在谷歌自行研發的SPDY協議的基礎上發展而來,2015年5月作為互聯網標準正式發布;
- HTTP/3,未來版本,正在完善當中;
準備知識
網絡通信流程
如果不像文中一開始的圖那么精細的劃分網絡協議層,我們可以將其粗略地劃分為四層:
- 應用層,決定向用戶提供應用服務時通信的活動;
- 傳輸層,提供處于網絡連接中兩臺計算機的數據傳輸,著名的TCP/UDP協議都在這一層;
- 網絡層,處理流動的網絡數據包,規定數據包經什么路徑從出發點到達目的地;
- 鏈路層,處理網絡連接相關硬件工作;
當一個HTTP請求被發起時,應用層把數據交給傳輸層,傳輸層收到數據后將數據分割打上標記序號和端口號后將數據交給網絡層,網絡層增加通信目的地的MAC地址后發給鏈路層,鏈路層將其發送出去;同理,服務端接收到數據后,逐層向上傳遞,解除每一層的部首信息,將報文拼接成原始的樣子后進行處理。
ps:上圖來自《圖解HTTP》(日)上野宣
與HTTP關系密切的協議
在TCP/IP協議族當中,有3個協議與HTTP有非常密切的關系:
- IP協議,位于網絡層,負責數據包的投遞。主要依靠IP、MAC以及ARP協議;
- TCP協議,提供可靠的字節流服務,主要用于分割數據,并確保數據投遞到目的地。該協議有著名的“三次握手”策略;
- DNS服務,位于應用層,提供域名到IP地址的解析服務(MAC地址需要靠IP地址進行反查得到);
簡單的HTTP協議
Note:下文主要基于HTTP/1.1進行敘述
首先明確以下三點基礎知識:
- 兩臺計算機在使用HTTP協議進行通信時,一端必須為服務器(server),一端必須為客戶端(client);
- HTTP協議規定請求(request)由客戶端發起,服務器負責響應(response)并返回;
- HTTP協議是無狀態協議,需要由Cookie技術實現狀態保持;
一個示例請求可以如下:
一個示例響應可以如下:
ps:在chrome或者Firefox等現代瀏覽器上,可以使用開發者工具查看這些信息。
HTTP方法
在HTTP/1.1當中,提供了若干種不同的方法對應不同的需求,下面簡要介紹一下(重點需要了解GET和POST方法,其他比較少用):
- GET方法,獲取資源。請求參數附在地址欄后面,可見的;
- POST方法,傳輸實體主體。一般用于提交表單等操作,且表單的內容在地址欄是不可見的;
- PUT方法,傳輸文件。自身不帶驗證機制,任何人都可以上傳,存在安全問題;
- HEAD方法,獲得報文部首。和GET類似,但是服務器不返回報文主體;
- DELETE方法,刪除文件。和PUT相反,同樣不帶驗證機制;
- OPTIONS方法,查詢支持方法。查詢服務器開放了哪些HTTP方法;
- TRACE方法,追蹤路徑。可以查詢發送出去的請求是怎樣被加工修改的,容易引發XST攻擊,通常不會使用;
- CONNECT方法,要求使用隧道協議連接代理。主要使用SSL和TLS協議加密信息后傳輸;
Cookie技術
HTTP是無狀態協議,也就是說它不對之前的請求和響應進行管理,即無法根據之前的狀態對本次請求進行處理。假設一個需要登錄的網站,在這種情況下,每次刷新頁面都得重新登錄。但是實際我們并不需要這么做,這就得益于Cookie技術了:
- 第一次請求:客戶端向服務器發起請求,服務器生成cookie用于記住該客戶端,將cookie在響應當中返回給客戶端,客戶端保存該cookie;
- 第二次以后請求:客戶端在請求上主動加上cookie,服務器根據該cookie就可以判斷該客戶端的身份;
ps:上圖來自《圖解HTTP》(日) 上野宣
HTTP報文內的HTTP信息
用于HTTP協議交互的信息被稱為HTTP報文。客戶端的HTTP報文叫做請求報文,服務器的HTTP報文叫做響應報文。HTTP報文是由多行數據構成的字符串文本(用CR+LF(\r\n,回車換行符)表示換行),報文大致可以分為:報文部首(必須有的)、報文主體(不一定非要有)。
理解報文主體和實體主體,首先明確以下兩個概念:
- 報文(message):HTTP通信的基本單位,由8位組字節流組成;
- 實體(entity):作為請求或者響應的有效載荷數據被傳輸,由實體部首和實體主體組成;
HTTP報文主體用于傳輸請求或者響應的實體主體。通常,報文主體和實體主體是一樣的,只有當在傳輸過程中進行了編碼操作(編碼可以提升傳輸速率,但是需要消耗CPU資源)時,實體主體的內容會發生變化,從而導致這兩者不一樣。
狀態碼
相信大部分人在使用web的時候都遇到過著名的“404”頁面,404就是一個HTTP狀態碼。對于程序員來說,相信大部分人喜歡200多過404了。
HTTP狀態碼的類別如下:
狀態碼 | 類別 | 原因短語 |
---|---|---|
1XX | 信息狀態碼(informational) | 接收到的請求正在處理 |
2XX | 成功狀態碼(Success) | 請求正常處理完畢 |
3XX | 重定向狀態碼(Redirection) | 需要進行附加的操作完成請求 |
4XX | 客戶端錯誤狀態碼(Client Error) | 服務器無法處理請求 |
5XX | 服務器錯誤狀態碼(Server Error) | 服務器處理請求出錯 |
HTTP首部
HTTP報文部
一個完整的HTTP報文應該有以下結構:
- (HTTP)報文首部;
- 空行(CR + LF);
- (HTTP)報文主體;
HTTP報文首部由幾個字段組成,分別是:請求行(狀態行)、請求(響應)首部字段、通用首部字段、實體首部字段和其他。其中,以”首部字段“四字結尾的幾個字段合稱為HTTP首部字段。
HTTP首部字段
HTTP 首部字段是構成 HTTP 報文的要素之一。在客戶端與服務器之間以 HTTP 協議進行通信的過程中,無論是請求還是響應都會使用首部字段,它能起到傳遞額外重要信息的作用。使用首部字段是為了給瀏覽器和服務器提供報文主體大小、所使用的語言、認證信息等內容。
摘自:《圖解HTTP》 — 〔日〕上野宣
首部字段的結構如下所示:
首部字段名稱:字段值
// example
Content-Type: text/html
Keep-Alive: timeout=15, max=100
如果一個HTTP報文當中含有兩個名字一樣但是字段值不相同的首部字段,根據不同的瀏覽器可能會出現不同的結果,需要謹慎注意。
上文也提到了,首部字段總共分為四類:
- 通用首部字段(General Header Fields),請求和響應報文都會使用的首部;
- 請求首部字段(Request Header Fields),客戶端使用的首部,補充請求的附加信息;
- 響應首部字段(Response Header Fields),服務器使用的首部,補充響應的附加信息;
- 實體首部字段(Entity Header Fields),針對報文實體使用的首部,補充資源內容更新等于實體有關信息;
HTTP協議具體的字段列表,可以參見維基百科傳送門。
為Cookie服務的首部字段
由于HTTP協議是無狀態協議,在實際的開發中,往往我們又需要保存用戶的狀態信息。這時候就要用到Cookie,所以單獨列一小節探究一下與其相關的首部字段。主要就是以下兩個字段:
首部字段名 | 說明 | 首部類型 |
---|---|---|
Set-Cookie | 開始狀態管理所使用的Cookie信息 | 響應首部字段 |
Cookie | 服務器收到的Cookie信息 | 請求首部字段 |
Set-Cookie
該字段有以下幾個屬性:
上圖摘自:《圖解HTTP》 — 〔日〕上野宣
比較需要注意的是expires這個屬性,它指定了瀏覽器可以發送Cookie的有效期。當該屬性省略是,有效期默認為瀏覽器會話(session)時間段內。另外,一旦Cookie被發送到客戶端,服務端就不存在修改它的方法。但是可以通過覆蓋已過期的Cookie,實現對客戶端Cookie的實質性刪除操作。
Cookie
Cookie: status=enable
當客戶端想要獲得狀態管理支持時,就會在請求中包含從服務器接收到的Cookie。接收到多個Cookie時,同樣可以以多個Cookie的形式發送。
結語
HTTP協議博大精深,遠遠不是一篇文章可以講完的。如果需要深入學習,推薦該領域的名著《HTTP》權威指南(英文原著名稱:HTTP: The Definitive Guide)。