HTTP 概述
HTTP 是一種用於獲取 HTML 文件等資源的協議。它是 Web 上任何資料交換的基礎,並且是一種客戶端-伺服器協議,這意味著請求由接收方(通常是 Web 瀏覽器)發起。一個完整的文件通常由文字內容、佈局指令、影像、影片、指令碼等資源構成。
客戶端和伺服器透過交換單個訊息(而不是資料流)進行通訊。客戶端傳送的訊息稱為請求,伺服器作為應答傳送的訊息稱為響應。
HTTP 設計於 20 世紀 90 年代初,是一種可擴充套件協議,並隨著時間的推移而發展。它是一種應用層協議,透過 TCP 或 TLS 加密的 TCP 連線傳送,儘管理論上可以使用任何可靠的傳輸協議。由於其可擴充套件性,它不僅用於獲取超文字文件,還用於獲取影像和影片,或將內容釋出到伺服器,例如 HTML 表單結果。HTTP 也可用於獲取文件的某些部分,以按需更新網頁。
基於 HTTP 的系統元件
HTTP 是一種客戶端-伺服器協議:請求由一個實體(使用者代理或代表它的代理)傳送。大多數情況下,使用者代理是 Web 瀏覽器,但它可以是任何東西,例如,爬取 Web 以填充和維護搜尋引擎索引的機器人。
每個單獨的請求都發送到伺服器,伺服器處理它並提供一個稱為響應的答案。在客戶端和伺服器之間有許多實體,統稱為代理,它們執行不同的操作,並充當閘道器或快取等。
實際上,瀏覽器和處理請求的伺服器之間還有更多的計算機:有路由器、調變解調器等等。由於 Web 的分層設計,這些都隱藏在網路和傳輸層中。HTTP 位於最頂層,即應用層。儘管對於診斷網路問題很重要,但底層層與 HTTP 的描述大多無關。
客戶端:使用者代理
使用者代理是代表使用者執行操作的任何工具。這個角色主要由 Web 瀏覽器執行,但也可以由工程師和 Web 開發人員用來除錯其應用程式的程式執行。
瀏覽器總是發起請求的實體。它從不是伺服器(儘管多年來已經添加了一些機制來模擬伺服器發起的請求)。
要顯示網頁,瀏覽器會發送原始請求以獲取代表該頁面的 HTML 文件。然後它解析此檔案,發出與執行指令碼、佈局資訊 (CSS) 和頁面中包含的子資源(通常是影像和影片)相對應的額外請求。然後,Web 瀏覽器將這些資源組合起來,呈現完整的文件,即網頁。由瀏覽器執行的指令碼可以在後續階段獲取更多資源,瀏覽器會相應地更新網頁。
網頁是一個超文字文件。這意味著顯示內容的某些部分是連結,可以透過啟用(通常透過滑鼠點選)來獲取新網頁,從而允許使用者引導其使用者代理並瀏覽 Web。瀏覽器將這些指令轉換為 HTTP 請求,並進一步解釋 HTTP 響應以向用戶呈現清晰的響應。
Web 伺服器
通訊通道的另一端是伺服器,它提供客戶端請求的文件。伺服器在虛擬上只顯示為一臺機器;但它實際上可能是一組共享負載的伺服器(負載平衡),或根據需要完全或部分生成文件的其他軟體(例如快取、資料庫伺服器或電子商務伺服器)。
伺服器不一定是一臺機器,但多個伺服器軟體例項可以託管在同一臺機器上。使用 HTTP/1.1 和 Host 頭部,它們甚至可以共享相同的 IP 地址。
代理
在 Web 瀏覽器和伺服器之間,許多計算機和機器中繼 HTTP 訊息。由於 Web 堆疊的分層結構,其中大多數在傳輸、網路或物理層執行,在 HTTP 層變得透明,並可能對效能產生顯著影響。在應用層執行的通常稱為代理。它們可以是透明的,轉發接收到的請求而不對其進行任何更改,也可以是非透明的,在這種情況下,它們會在將請求傳遞給伺服器之前對其進行某種更改。代理可以執行多種功能:
- 快取(快取可以是公共的,也可以是私有的,如瀏覽器快取)
- 過濾(如防病毒掃描或家長控制)
- 負載平衡(允許多個伺服器服務不同的請求)
- 身份驗證(控制對不同資源的訪問)
- 日誌記錄(允許儲存歷史資訊)
HTTP 的基本方面
HTTP 很簡單
HTTP 通常設計為人類可讀,即使 HTTP/2 透過將 HTTP 訊息封裝到幀中引入了額外的複雜性。HTTP 訊息可以被人類閱讀和理解,為開發人員提供更簡單的測試,並降低了新手的複雜性。
HTTP 是可擴充套件的
HTTP/1.0 中引入的 HTTP 頭部使該協議易於擴充套件和實驗。新功能甚至可以透過客戶端和伺服器之間關於新頭部語義的協議引入。
HTTP 是無狀態的,但不是無會話的
HTTP 是無狀態的:在同一連線上連續執行的兩個請求之間沒有連結。這立即帶來了使用者試圖與某些頁面連貫互動的問題,例如,使用電子商務購物車。但是,儘管 HTTP 的核心本身是無狀態的,但 HTTP Cookie 允許使用有狀態會話。透過頭部擴充套件,HTTP Cookie 被新增到工作流中,允許在每個 HTTP 請求上建立會話以共享相同的上下文或相同的狀態。
HTTP 和連線
連線在傳輸層控制,因此從根本上超出了 HTTP 的範圍。HTTP 不要求底層傳輸協議是面向連線的;它只要求它是可靠的,或者不丟失訊息(至少,在這種情況下會顯示錯誤)。在 Internet 上最常見的兩種傳輸協議中,TCP 是可靠的,UDP 不是。因此,HTTP 依賴於面向連線的 TCP 標準。
在客戶端和伺服器可以交換 HTTP 請求/響應對之前,它們必須建立 TCP 連線,這個過程需要多次往返。HTTP/1.0 的預設行為是為每個 HTTP 請求/響應對開啟一個單獨的 TCP 連線。當在短時間內傳送多個請求時,這比共享單個 TCP 連線效率低下。
為了彌補這個缺陷,HTTP/1.1 引入了流水線(事實證明難以實現)和持久連線:底層 TCP 連線可以使用 Connection 頭部進行部分控制。HTTP/2 更進一步,透過在單個連線上覆用訊息,幫助保持連線“溫暖”和更高效。
目前正在進行實驗,旨在設計更適合 HTTP 的更好的傳輸協議。例如,Google 正在試驗 QUIC,它基於 UDP 構建,以提供更可靠、更高效的傳輸協議。
HTTP 可以控制什麼
HTTP 的這種可擴充套件性隨著時間的推移,允許對 Web 進行更多的控制和功能。快取和身份驗證方法是 HTTP 歷史早期處理的功能。相比之下,放寬源限制的能力直到 2010 年代才新增。
以下是 HTTP 可控制的常見功能列表
- 快取:文件的快取方式可以透過 HTTP 控制。伺服器可以指示代理和客戶端快取什麼以及快取多長時間。客戶端可以指示中間快取代理忽略儲存的文件。
- 放寬同源限制:為了防止窺探和其他隱私侵犯,Web 瀏覽器強制網站之間嚴格分離。只有來自同源的頁面才能訪問網頁的所有資訊。儘管這種限制對伺服器來說是一種負擔,但 HTTP 頭部可以在伺服器端放寬這種嚴格的分離,允許文件成為來自不同域的資訊的拼湊;甚至可能出於安全相關的原因這樣做。
- 身份驗證:某些頁面可能受到保護,只有特定使用者才能訪問。HTTP 可以提供基本身份驗證,無論是使用
WWW-Authenticate及類似頭部,還是透過使用 HTTP Cookie 設定特定會話。 - 代理和隧道:伺服器或客戶端通常位於內網中,並對其他計算機隱藏其真實的 IP 地址。HTTP 請求然後透過代理來跨越這個網路屏障。並非所有代理都是 HTTP 代理。例如,SOCKS 協議在較低層執行。其他協議,如 ftp,可以由這些代理處理。
- 會話:使用 HTTP Cookie 可以將請求與伺服器的狀態連結起來。這會建立會話,儘管基本的 HTTP 是一個無狀態協議。這不僅對電子商務購物車有用,對任何允許使用者配置輸出的網站也很有用。
HTTP 流程
當客戶端想要與伺服器(最終伺服器或中間代理)通訊時,它會執行以下步驟:
-
開啟 TCP 連線:TCP 連線用於傳送一個或多個請求並接收一個答案。客戶端可以開啟一個新連線,重用現有連線,或開啟多個 TCP 連線到伺服器。
-
傳送 HTTP 訊息:HTTP 訊息(在 HTTP/2 之前)是人類可讀的。使用 HTTP/2,這些訊息被封裝在幀中,使其無法直接讀取,但原理保持不變。例如:
httpGET / HTTP/1.1 Host: developer.mozilla.org Accept-Language: fr -
讀取伺服器傳送的響應,例如:
httpHTTP/1.1 200 OK Date: Sat, 09 Oct 2010 14:28:02 GMT Server: Apache Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT ETag: "51142bc1-7449-479b075b2891b" Accept-Ranges: bytes Content-Length: 29769 Content-Type: text/html <!doctype html>… (here come the 29769 bytes of the requested web page) -
關閉或重用連線以進行後續請求。
如果激活了 HTTP 流水線,可以在不等待第一個響應完全接收的情況下發送多個請求。HTTP 流水線在現有網路中被證明難以實現,因為舊軟體與現代版本共存。HTTP 流水線已被 HTTP/2 中更強大的幀內多路複用請求所取代。
HTTP 訊息
HTTP/1.1 及更早版本中定義的 HTTP 訊息是人類可讀的。在 HTTP/2 中,這些訊息嵌入到二進位制結構(幀)中,允許進行頭部壓縮和多路複用等最佳化。即使在此版本的 HTTP 中只發送了原始 HTTP 訊息的一部分,每條訊息的語義也保持不變,客戶端(虛擬地)重構原始 HTTP/1.1 請求。因此,以 HTTP/1.1 格式理解 HTTP/2 訊息很有用。
HTTP 訊息有兩種型別:請求和響應,每種都有自己的格式。
請求
HTTP 請求示例
請求由以下元素組成:
響應
響應示例
響應由以下元素組成:
基於 HTTP 的 API
最常用的基於 HTTP 的 API 是 Fetch API,可用於從 JavaScript 發出 HTTP 請求。Fetch API 取代了 XMLHttpRequest API。
另一個 API,伺服器傳送事件,是一種單向服務,允許伺服器使用 HTTP 作為傳輸機制向客戶端傳送事件。使用 EventSource 介面,客戶端開啟連線並建立事件處理程式。客戶端瀏覽器自動將到達 HTTP 流上的訊息轉換為適當的 Event 物件。然後將其傳遞給已註冊的事件處理程式,以處理已知事件的 type,如果未建立特定型別的事件處理程式,則傳遞給 onmessage 事件處理程式。
總結
HTTP 是一種可擴充套件的協議,易於使用。客戶端-伺服器結構,結合新增頭部的能力,使得 HTTP 能夠隨著 Web 擴充套件能力的發展而進步。
儘管 HTTP/2 透過將 HTTP 訊息嵌入到幀中以提高效能而增加了一些複雜性,但訊息的基本結構自 HTTP/1.0 以來一直保持不變。會話流程仍然是基本的,允許使用 HTTP 網路監視器進行調查和除錯。