閱讀手札 | 手把手帶你探索『圖解 HTTP』

前言

本文已經收錄到我的 Github 個人部落格,歡迎大佬們光臨寒舍:

我的 Github 部落格

學習清單:

一、網路基礎 TCP/IP

通常使用的網路(包括互聯網)是在 TCP/IP 協議族的基礎上運作,而 HTTP 屬於它內部的一個子集

1.1 層次劃分

  • 應用層: 決定了向用戶提供應用服務時通訊的活動,比如 FTPDNSHTTP

易記:應用層,顧名思義,是提供給應用服務的活動,然後現在最火的應用是微信(通訊功能),所以就是:向用戶提供應用服務時通訊

  • 傳輸層: 對上層應用層提供處於網路連接中的兩台電腦之間的數據傳輸,比如 TCPUDP

易記:傳輸層,顧名思義,提供電腦之間的數據傳輸

  • 網路層: 用來處理在網路上流動的數據包,該層規定了通過怎樣的路徑到達對方電腦,並把數據包傳送給對方;與對方電腦之間通過多台電腦或網路設備進行傳輸時,網路層所起的作用就是在眾多的選項內選擇一條傳輸路線

易記:網路層,顧名思義,處理在網路上流動的數據包,規定通過什麼路徑

  • 數據鏈路層: 用來處理連接網路的硬體部分

易記:數據鏈路層,顧名思義,鏈路偏硬體的東西,而數據是偏軟體層面的東西,自然可以想到是起到連接作用

1.2 通訊的過程

  1. 首先作為發送端的客戶端在應用層HTTP 協議)發出獲取 Web 頁面的 HTTP 請求
  2. 接著,為了傳輸方便,在傳輸層TCP 協議)把從應用層處收到的數據(HTTP 請求報文)進行分割,並在各個報文上打上標記序號及埠號後轉發給網路層
  3. 網路層IP 協議),增加作為通訊目的地MAC 地址後轉發給鏈路層。這樣一來,發往網路的通訊請求就準備齊全了
  4. 接收端的伺服器在鏈路層接收到數據,按序往上層發送,一直到應用層。當傳輸到應用層,才能算真正接收到由客戶端發送過來的 HTTP 請求
image-20200707164153058
image-20200707164153058

1.3 三次握手

之前已經筆者已經寫了,因此在這裡就不再贅述,點擊鏈接即可跳轉:TCP 連接管理

1.4 各協議與 HTTP 協議的關係

image-20200707164806629
image-20200707164806629

1.5 URI 和 URL

Q1:URLURI 的區別

  • URI 用字元串標識某一互聯網資源
  • URL 表示資源的地點

由此可見, URLURI 的子集

Q2:URI 的各部分結構

image-20200707181219904
image-20200707181219904

二、簡單的 HTTP 協議

2.1 HTTP 方法

  • GET 獲取資源: 用來請求訪問已被 URI 識別的資源,指定的資源經伺服器端解析後返迴響應內容
  • POST 傳輸實體主體: 用來傳輸實體的主體 雖然用 GET 方法也可以傳輸實體的主體,但一般不用 GET 方法進行傳輸,而是用 POST 方法
  • PUT 傳輸文件: 在請求報文的主體中包含文件內容,然後保存到請求 URI 指定的位置 鑒於 HTTP1.1PUT 方法自身不帶驗證機制,任何人都可以上傳文件,存在安全性問題,因此一般不使用該方法
  • HEAD 獲得報文首部:GET 方法一樣,只是不返回報文主體部分。 用於確認 URI 的有效性及資源更新的日期時間等
  • DELETE 刪除文件: 用來刪除文件,是與 PUT 相反的方法。DELETE 方法按請求 URI 刪除指定的資源。 不帶驗證機制,所以一般不使用 DELETE 方法

put 相對應,兩者都不具備驗證機制

  • OPTIONS 詢問支援的方法: 用來查詢針對請求 URI 指定的資源支援的方法(了解即可)
  • TRACE 追蹤路徑:Web 伺服器端將之前的請求通訊返回給客戶端的方法。 但 TRACE 方法本來就不怎麼常用,再加上它容易引發 XST攻擊,通常就更不會用到了(了解即可)
  • CONNECT 要求用隧道協議連接代理: 要求在與代理伺服器通訊時建立隧道,實現用隧道協議進行 TCP 通訊。 主要使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協議把通訊內容加密後經網路隧道傳輸。

2.2 持久連接節省通訊量

2.2.1 持久鏈接

持久連接的特點是,只要任意一端沒有明確提出斷開連接,則保持 TCP 連接狀態

持久連接的好處:

  • 減少了 TCP 連接的重複建立和斷開所造成的額外開銷,減輕了伺服器端的負載

感覺有點類似於連接池的作用

  • 減少開銷的那部分時間,使 HTTP 請求和響應能夠更早地結束,這樣 Web 頁面的顯示速度也就相應提高了

2.2.2 管線化

管線化技術出現後,不用等待響應亦可直接發送下一個請求

這樣就能夠做到同時並行發送多個請求,而不需要一個接一個地等待響應了

用持久連接可以讓請求更快結束。而管線化技術則比持久連接還要快。請求數越多,時間差就越明顯。

2.4 使用 Cookie 的狀態管理

狀態管理其實還有很多種,比如 Session ,token ,這裡僅介紹 cookie

HTTP 是無狀態協議,它不對之前發生過的請求和響應的狀態進行管理。

Cookie 技術通過在請求和響應報文中寫入 Cookie 資訊來控制客戶端的狀態。Cookie 會根據從伺服器端發送的響應報文內的一個叫做 Set-Cookie 的首部欄位資訊,通知客戶端保存 Cookie。當下次客戶端再往該伺服器發送請求時,客戶端會自動在請求報文中加入 Cookie 值後發送出去

三、HTTP 報文內的 HTTP 資訊

3.1 壓縮傳輸的內容編碼

內容編碼指明應用在實體內容上的編碼格式,並保持實體資訊原樣壓縮

常用的內容編碼有:

  • gzip
  • compress
  • deflate
  • identity

四、返回結果的 HTTP 狀態碼

4.1 狀態碼告知從伺服器端返回的請求結果

數字中的第一位指定了響應類別,後兩位無分類

類別 原因短語
1XX Informational 接收的請求正在處理
2XX Success 請求正常處理完畢
3XX Redirection 需要進行附加操作以完成請求
4XX Client Error 客戶端無法處理請求
5XX Server Error 伺服器處理請求出錯

4.2 2xx 成功

2xx 成功
2xx 成功

4.3 3xx 重定向

4.4 4XX 客戶端錯誤

image-20200711224935405
image-20200711224935405

PS:注意區分 403 和 404,一個是被拒絕(一般是許可權問題),另一個是無法找到

4.5 5XX 伺服器錯誤

五、Web 伺服器

5.1 用單台虛擬主機實現多個域名

HTTP1.1 規範允許一個伺服器搭建多個 Web 站點,這是虛擬主機功能。

Q1:為啥 Host 首部內完整指定主機名或域名URI

因為虛擬主機可以寄存多個不同主機名和域名Web 網站

5.2 通訊數據轉發程式

這些應用程式和伺服器可以將請求轉發給通訊線路上的下一站伺服器,並且能接收從那台伺服器發送的響應再轉發給客戶端。

  1. 代理:接收客戶端發送的請求後轉發給其他伺服器;代理不改變請求 URI,會直接發送給前方持有資源的目標伺服器。
  • 快取代理:預先將資源快取保存在代理伺服器上,當代理再次接收到對相同資源的請求時,就可以直接將之前快取的資源作為響應返回
  • 透明代理:轉發請求或響應時,不對報文做任何加工被稱為透明代理,對報文內容進行加工的稱為非透明代理。
image-20200712195432972
image-20200712195432972

2.網關:轉發其他伺服器通訊數據的伺服器,接收從客戶端發送來的請求時,它就像自己擁有資源的源伺服器一樣對請求進行處理。

image-20200712195459045
image-20200712195459045

3.隧道: 按要求建立起一條與其他伺服器的通訊線路,屆時使用 SSL 等加密手段進行通訊,在通訊雙方斷開連接時結束。隧道的目的是確保客戶端能與伺服器進行安全的通訊。

5.3 保存資源的快取

客戶端的快取: 瀏覽器快取如果有效,不必再向伺服器請求,而直接從本地讀取。當判定快取過期後,會向源伺服器確認資源的有效性。若判斷瀏覽器快取失效,瀏覽器會再次請求新資源。

image-20200712172523006
image-20200712172523006

六、HTTP 首部

HTTP 協議的請求和響應報文中必定包含 HTTP 首部,請求報文和響應報文結構如下

image-20200713143253306
image-20200713143253306
image-20200713143234364
image-20200713143234364

6.1 HTTP 首部欄位

HTTP 首部欄位將定義成快取代理非快取代理的行為,分成 2 種類型。

  1. 端到端首部: 分在此類別中的首部會轉發給請求 / 響應對應的最終接收目標,且必須保存在由快取生成的響應中,另外規定它必須被轉發
  2. 逐跳首部: 分在此類別中的首部只對單次轉發有效,會因通過快取或代理而不再轉發。HTTP1.1 和之後版本中,如果要使用 hop-by-hop 首部,需提供 Connection 首部欄位。

6.1.1 通用首部欄位

請求報文和響應報文兩方都會使用的首部。

首部欄位名 說明
Cache-Control 控制快取的行為
Connection 逐跳首部、連接的管理
Date 創建報文的日期時間
Pragma 報文指令
Trailer 報文末端的首部一覽
Transfer-Encoding 指定報文主體的傳輸編碼方式
Upgrade 升級為其他協議
Via 代理伺服器的相關資訊
Warning 錯誤通知

6.1.2 請求首部欄位

從客戶端向伺服器端發送請求報文時使用的首部。補充了請求的附加內容、客戶端資訊、響應內容相關優先順序等資訊。

首部欄位名 說明
Accept 用戶代理可處理的媒體類型
Accept-Charset 優先的字符集
Accept-Encoding 優先的內容編碼
Accept-Language 優先的語言(自然語言)
Authorization Web認證資訊
Expect 期待伺服器的特定行為
From 用戶的電子郵箱地址
Host 請求資源所在伺服器
If-Match 比較實體標記(ETag)
If-Modified-Since 比較資源的更新時間
If-None-Match 比較實體標記(與 If-Match 相反)
If-Range 資源未更新時發送實體 Byte 的範圍請求
If-Unmodified-Since 比較資源的更新時間(與If-Modified-Since相反)
Max-Forwards 最大傳輸逐跳數
Proxy-Authorization 代理伺服器要求客戶端的認證資訊
Range 實體的位元組範圍請求
Referer 對請求中 URI 的原始獲取方
TE 傳輸編碼的優先順序
User-Agent HTTP 客戶端程式的資訊

6.1.3 響應首部欄位

從伺服器端向客戶端返迴響應報文時使用的首部。補充了響應的附加內容,也會要求客戶端附加額外的內容資訊。

首部欄位名 說明
Accept-Ranges 是否接受位元組範圍請求
Age 推算資源創建經過時間
ETag 資源的匹配資訊
Location 令客戶端重定向至指定URI
Proxy-Authenticate 代理伺服器對客戶端的認證資訊
Retry-After 對再次發起請求的時機要求
Server HTTP伺服器的安裝資訊
Vary 代理伺服器快取的管理資訊
WWW-Authenticate 伺服器對客戶端的認證資訊

6.1.4 實體首部欄位

針對請求報文和響應報文的實體部分使用的首部。補充了資源內容更新時間等與實體有關的資訊。

首部欄位名 說明
Allow 資源可支援的HTTP方法
Content-Encoding 實體主體適用的編碼方式
Content-Language 實體主體的自然語言
Content-Length 實體主體的大小(單位:位元組)
Content-Location 替代對應資源的URI
Content-MD5 實體主體的報文摘要
Content-Range 實體主體的位置範圍
Content-Type 實體主體的媒體類型
Expires 實體主體過期的日期時間
Last-Modified 資源的最後修改日期時間

6.2 HTTP1.1 通用首部欄位

通用首部欄位是指請求報文和響應報文都會使用的首部。

6.2.1 Cache-Control

  1. no-cache: 防止從快取中返回過期的資源。客戶端請求如果包含 no-cache,表示客戶端將不會接收快取過的響應,快取伺服器必須把客戶端請求轉發給源伺服器。伺服器響應中包含 no-cache,那麼快取伺服器不能對資源進行快取,源伺服器以後也將不再對快取伺服器請求中提出的資源有效性進行確認,且禁止其對響應資源進行快取操作。
  2. no-store: 快取不能在本地存儲請求或響應的任一部分。

從字面意思上很容易把 no-cache 誤解成為不快取,但 no-cache 代表不快取過期的資源,快取會向源伺服器進行有效期確認後處理資源,no-store 才是真正地不進行快取

6.2.2 Connection

1.控制不再轉發給代理的首部欄位: 在客戶端發送請求和伺服器返迴響應內,使用 Connection 首部欄位,可控制不再轉發給代理的首部欄位(即 Hop-by-hop 逐跳首部)。

2.管理持久連接: HTTP1.1 默認持久連接,客戶端會在持久連接上連續發送請求。伺服器端想斷開連接時,則設置 Connection 首部欄位為 CloseHTTP1.1 之前默認都是非持久連接。為此,如果想在舊版本 HTTP 協議上持續連接,則需設置 Connection 首部欄位為 Keep-Alive

6.2.3 Date

表明創建 HTTP 報文的日期和時間。

6.2.4 Upgrade

用於檢測 HTTP 協議及其他協議是否可使用更高的版本進行通訊,其參數值可以用來指定一個完全不同的通訊協議。

6.3 請求首部欄位

從客戶端往伺服器端發送請求報文中所使用的欄位,用於補充請求的附加資訊、客戶端資訊、對響應內容相關的優先順序等內容。

6.3.1 Accept

通知伺服器,用戶代理能夠處理的媒體類型媒體類型的相對優先順序。可使用 type/subtype 這種形式,一次指定多種媒體類型。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

6.3.2 Host

告知伺服器,請求的資源所處的互聯網主機名和埠號。Host 首部欄位在 HTTP1.1 規範內是唯一一個必須被包含在請求內的首部欄位。

6.3.3 If-Match

形如 If-xxx 這種,都可稱為條件請求。伺服器接收到後,只有判斷指定條件為真時,才會執行請求

6.3.4 If-None-Match

If-Match 相反

6.3.5 If-Modified-Since

如果在 If-Modified-Since 欄位指定的日期時間後資源發生了更新,伺服器會接受請求。

6.3.6 If-Unmodified-Since

If-Modified-Since 的作用相反

6.3.7 If-Range

欄位如果跟 ETag 值或更新的日期時間一致,那麼就作為範圍請求處理。反之,則返回全體資源。

6.4 響應首部欄位

由伺服器端向客戶端返迴響應報文中所使用的欄位,用於補充響應的附加資訊伺服器資訊,以及對客戶端的附加要求等資訊。

6.4.1 ETag

實體標識,將資源以字元串形式做唯一性標識的方式。伺服器會為每份資源分配對應的 ETag 值。當資源更新時,ETag 值也需要更新。

若在下載過程中出現連接中斷、再連接的情況,都會依照 ETag 值來指定資源。

6.5 實體首部欄位

包含在請求報文和響應報文中的實體部分所使用的首部,用於補充內容的更新時間等與實體相關的資訊。

6.5.1 Allow

通知客戶端能夠支援的所有 HTTP 方法。當伺服器接收到不支援的 HTTP 方法時,會以狀態碼 405 Method Not Allowed 作為響應返回。與此同時,還會把所有能支援的 HTTP 方法寫入首部欄位 Allow 後返回。

6.5.2 Content-Encoding

告知客戶端伺服器對實體的主體部分選用的內容編碼方式。內容編碼是指在不丟失實體資訊的前提下所進行的壓縮。

主要有:gzipcompressdeflateidentity

6.5.3 Content-Type

說明了實體主體內對象的媒體類型,用 type/subtype 形式賦值。

6.5.4 Expires

Expires 會將資源失效的日期告知客戶端。快取伺服器在收到有 Expires 的響應後,會以快取來應答請求,在 Expires 欄位值指定的時間之前,響應的副本會一直被保存。當超過指定的時間後,快取伺服器在請求發送過來時,會轉向源伺服器請求資源。

6.5.5 Last-Modified

包含源頭伺服器認定的資源做出修改的日期及時間

6.6 為 Cookie 服務的首部欄位

首部欄位名 說明 首部類型
Set-Cookie 開始狀態管理所使用的Cookie資訊 響應首部欄位
Cookie 伺服器接收到的Cookie資訊 請求首部欄位

6.7 其他首部欄位

6.7.1 X-XSS-Protection

是針對跨站腳本攻擊(XSS)的一種對策,用於控制瀏覽器 XSS 防護機制的開關,可指定的欄位值如下

  • 0:將 XSS 過濾設置成無效狀態
  • 1:將 XSS 過濾設置成有效狀態

七、 HTTPS

HTTP 協議中有可能存在資訊竊聽或身份偽裝等安全問題,怎麼解決呢?HTTPS 了解一下

7.1 HTTP 的缺點是啥?

  • 通訊使用明文(不加密),內容可能會被竊聽
  • 不驗證通訊方的身份,因此有可能遭遇偽裝
  • 無法證明報文的完整性,所以有可能已遭篡改

7.2 HTTPS 是啥 ?

簡單來說,就是:HTTP+ 加密 + 認證 + 完整性保護

把添加了加密及認證機制的 HTTP 稱為 HTTPS

HTTPS 並非是應用層的一種新協議,只是 HTTP 通訊介面部分用 SSL(Secure Socket Layer)和 TLS(Transport Layer Security)協議代替而已。

image-20200714132749462
image-20200714132749462

HTTPS 採用共享密鑰加密(對稱加密)和公開密鑰加密(非對稱加密)兩者並用的混合加密機制。若密鑰能夠實現安全交換,那麼有可能會考慮僅使用公開密鑰加密來通訊。但是公開密鑰加密與共享密鑰加密相比,其處理速度要慢。

所以取長補短,在交換密鑰環節使用公開密鑰加密方式,之後的建立通訊交換報文階段則使用共享密鑰加密方式。

數字證書認證機構(CA,Certificate Authority)和其相關機關頒發的公開密鑰證書就是認證的可以信賴的公開密鑰,伺服器會將這份由數字證書認證機構頒發的公鑰證書發送給客戶端,以進行公開密鑰加密方式通訊。公鑰證書也可叫做數字證書或直接稱為證書。

image-20200714133015217
image-20200714133015217

7.2.1 SSL 速度慢嗎

當使用 SSL 時,它的處理速度會變慢。它慢分兩種:

  • 一種是指通訊慢

還必須進行 SSL 通訊,所以慢

  • 另一種是指由於大量消耗 CPU 及記憶體等資源,導致處理速度變慢

伺服器和客戶端都需要進行加解密處理

針對速度變慢這一問題,並沒有根本性的解決方案,一般會使用 SSL 加速器這種(專用伺服器)硬體。

7.2.2 為啥沒使用 HTTPS ?

  • 加密通訊會消耗更多的 CPU 及記憶體資源
  • 如果是非敏感資訊則使用 HTTP 通訊,只有在包含個人資訊等敏感數據時,才利用 HTTPS 加密通訊。可以僅在那些需要資訊隱藏時才加密,以節約資源
  • 節約購買證書的開銷

八、確認訪問用戶身份的認證

一些頁面只想讓特定的人瀏覽,這就引入了認證功能。

HTTP1.1 常用的認證方式:

  1. BASIC 認證(基本認證)
  2. DIGEST 認證(摘要認證)
  3. SSL 客戶端認證
  4. FormBase 認證(基於表單認證)

九、基於 HTTP 的功能追加協議

9.1 WebSocket

連接的發起方仍是客戶端,一旦確立 WebSocket 通訊連接,伺服器與客戶端任意一方都可向對方發送報文

  1. 推送功能: 支援由伺服器向客戶端推送數據的推送功能。這樣,伺服器可直接發送數據,而不必等待客戶端的請求。
  2. 減少通訊量:HTTP 相比,不但每次連接時的開銷減少,且由於首部資訊很小,通訊量也減少了。

通訊的建立:

1.首先使用 HTTPUpgrade 首部欄位,告知伺服器通訊協議發生改變,進行握手。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: //example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

Sec-WebSocket-Key 欄位內記錄著握手過程中必不可少的鍵值。Sec-WebSocket-Protocol 欄位內記錄使用的子協議。

2.之前的請求將會被返回 101 Switching Protocols 響應

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

成功握手建立 WebSocket 連接之後,通訊時不再使用 HTTP 的數據幀,而採用 WebSocket 獨立的數據幀

9.2 HTTP/2.0

HTTP/2.0 的目標是改善用戶在使用 Web 時的速度體驗。特點:

  1. HTTP/2.0 採用二進位格式而非文本格式(二進位分幀
  2. HTTP/2.0 是完全多路復用的,而非有序並阻塞的——只需一個連接即可實現並行
  3. 使用報頭壓縮,HTTP/2.0 降低了開銷(頭部壓縮
  4. HTTP/2.0 讓伺服器可以將響應**主動「推送」**到客戶端快取中

如果文章對您有一點幫助的話,希望您能點一下贊,您的點贊,是我前進的動力

本文參考鏈接:

本文使用 mdnice 排版