HTTP 概述

HTTP 是用於獲取資源(如 HTML 文件)的協議。它是網路上任何資料交換的基礎,並且是一種客戶端-伺服器協議,這意味著請求是由接收方(通常是 Web 瀏覽器)發起的。完整的文件通常由諸如文字內容、佈局指令、影像、影片、指令碼等資源構建而成。

A single Web document composed from multiple resources from different servers.

客戶端和伺服器透過交換單個訊息(而不是資料流)進行通訊。客戶端傳送的訊息稱為請求,伺服器作為答案發送的訊息稱為響應

HTTP as an application layer protocol, on top of TCP (transport layer) and IP (network layer) and below the presentation layer.

HTTP 設計於 1990 年代初期,是一個可擴充套件的協議,隨著時間的推移而不斷發展。它是一個應用層協議,透過TCPTLS 加密的 TCP 連線傳送,儘管理論上可以使用任何可靠的傳輸協議。由於其可擴充套件性,它不僅用於獲取超文字文件,還用於獲取影像和影片,或將內容釋出到伺服器,例如使用 HTML 表單結果。HTTP 還可以用於獲取文件的部分內容以按需更新網頁。

基於 HTTP 的系統的元件

HTTP 是一種客戶端-伺服器協議:請求由一個實體(使用者代理或代表它的代理)傳送。大多數情況下,使用者代理是 Web 瀏覽器,但它可以是任何東西,例如,一個爬取 Web 以填充和維護搜尋引擎索引的機器人。

每個單獨的請求都發送到一個伺服器,該伺服器處理它並提供一個稱為響應的答案。在客戶端和伺服器之間存在許多實體,統稱為代理,它們執行不同的操作並充當閘道器或快取,例如。

A HTTP request from a client forwarded by several proxies to a server and a response taking the same route back to the client.

實際上,在瀏覽器和處理請求的伺服器之間還有更多計算機:路由器、調變解調器等等。由於 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 不需要底層傳輸協議是基於連線的;它只需要它是可靠的,或者不會丟失訊息(至少在這種情況下會顯示錯誤)。在網際網路上兩種最常見的傳輸協議中,TCP 是可靠的,而 UDP 不是。因此,HTTP 依賴於基於連線的 TCP 標準。

在客戶端和伺服器可以交換 HTTP 請求/響應對之前,它們必須建立一個 TCP 連線,此過程需要多次往返。HTTP/1.0 的預設行為是為每個 HTTP 請求/響應對開啟一個單獨的 TCP 連線。當在短時間內傳送多個請求時,這不如共享單個 TCP 連線有效。

為了緩解此缺陷,HTTP/1.1 引入了管道(事實證明難以實現)和持久連線:可以使用Connection 標頭部分控制底層 TCP 連線。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 流程

當客戶端想要與伺服器(最終伺服器或中間代理)通訊時,它會執行以下步驟

  1. 建立 TCP 連線:TCP 連線用於傳送一個或多個請求並接收響應。客戶端可以開啟新的連線、重用現有連線或向伺服器開啟多個 TCP 連線。
  2. 傳送 HTTP 訊息:HTTP 訊息(在 HTTP/2 之前)是人類可讀的。在 HTTP/2 中,這些簡單的訊息被封裝在幀中,使其無法直接讀取,但原理保持不變。例如
    http
    GET / HTTP/1.1
    Host: developer.mozilla.org
    Accept-Language: fr
    
  3. 讀取伺服器傳送的響應,例如
    http
    HTTP/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)
    
  4. 關閉或重用連線以進行進一步的請求。

如果啟用了 HTTP 管道化,則可以在不等待第一個響應完全接收的情況下發送多個請求。HTTP 管道化已被證明難以在現有網路中實現,因為舊軟體與現代版本共存。HTTP/2 中的更強大的幀內多路複用請求取代了 HTTP 管道化。

HTTP 訊息

HTTP 訊息,如 HTTP/1.1 及更早版本中定義的那樣,是人類可讀的。在 HTTP/2 中,這些訊息被嵌入到二進位制結構(即 *幀*)中,從而允許進行諸如壓縮頭部和多路複用之類的最佳化。即使在此版本的 HTTP 中只發送了原始 HTTP 訊息的一部分,每個訊息的語義也保持不變,並且客戶端會(虛擬地)重建原始的 HTTP/1.1 請求。因此,以 HTTP/1.1 格式理解 HTTP/2 訊息很有用。

HTTP 訊息有兩種型別:請求和響應,每種都有自己的格式。

請求

一個 HTTP 請求示例

Overview of a HTTP GET request with headers

請求包含以下元素

  • 一個 HTTP 方法,通常是動詞,如 GETPOST,或名詞,如 OPTIONSHEAD,用於定義客戶端想要執行的操作。通常,客戶端希望獲取資源(使用 GET)或釋出 HTML 表單 的值(使用 POST),但在其他情況下可能需要更多操作。
  • 要獲取的資源的路徑;從上下文中明顯可見的元素中剝離出的資源的 URL,例如,不包括 協議 (http://)、域名(此處為 developer.mozilla.org)或 TCP (此處為 80)。
  • HTTP 協議的版本。
  • 可選的 頭部,用於向伺服器傳遞其他資訊。
  • 主體,對於某些方法(如 POST),類似於響應中的主體,其中包含傳送的資源。

響應

一個響應示例

Overview of a '200 OK' HTTP response to a GET request including response headers.

響應包含以下元素

  • 它們遵循的 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 網路監視器 進行調查和除錯。