超文本傳輸協議

超文本傳輸協定（HyperText Transfer Protocol，縮寫：HTTP）是一種用於分佈式、協作式和超媒體資訊系統的應用層協議。HTTP是全球資訊網的數據通信的基礎。

設計HTTP最初的目的是為了提供一種發布和接收HTML頁面的方法。通過HTTP或者HTTPS協議請求的資源由統一資源標識符（Uniform Resource Identifiers，URI）來標識。

HTTP的發展是由提姆·柏內茲-李於1989年在歐洲核子研究組織（CERN）所發起。HTTP的標準制定由全球資訊網協會（World Wide Web Consortium，W3C）和網際網路工程任務組（Internet Engineering Task Force，IETF）進行協調，最終發布了一系列的RFC，其中最著名的是1999年6月公佈的 RFC 2616，定義了HTTP協議中現今廣泛使用的一個版本——HTTP 1.1。

2014年12月，網際網路工程任務組（IETF）的Hypertext Transfer Protocol Bis（httpbis）工作小組將HTTP/2標準提議遞交至IESG進行討論，於2015年2月17日被批准。HTTP/2標準於2015年5月以RFC 7540正式發表，取代HTTP 1.1成為HTTP的實現標準。

## 協議概述

HTTP是一個客戶端（使用者）和服務端（網站）之間請求和應答的標準，通常使用TCP協議。通過使用網頁瀏覽器、網路爬蟲或者其它的工具，客戶端發起一個HTTP請求到伺服器上指定埠（默認埠為80）。我們稱這個客戶端為使用者代理程式（user agent）。應答的伺服器上存儲著一些資源，比如HTML文件和圖像。我們稱這個應答伺服器為源伺服器（origin server）。在使用者代理和源伺服器中間可能存在多個「中間層」，比如代理伺服器、網關或者隧道（tunnel）。

儘管TCP/IP協議是網際網路上最流行的應用，但是在HTTP協議中並沒有規定它必須使用或它支持的層。事實上HTTP可以在任何網際網路協議或其他網路上實現。HTTP假定其下層協議提供可靠的傳輸。因此，任何能夠提供這種保證的協議都可以被其使用，所以其在TCP/IP協議族使用TCP作為其傳輸層。

通常，由HTTP客戶端發起一個請求，建立一個到伺服器指定埠（默認是80埠）的TCP連接。HTTP伺服器則在那個埠監聽客戶端的請求。一旦收到請求，伺服器會向客戶端返回一個狀態，比如"HTTP/1.1 200 OK"，以及返回的內容，如請求的文件、錯誤消息、或者其它資訊。

## 請求方法

HTTP/1.1協議中共定義了八種方法（也叫「動作」）來以不同方式操作指定的資源：

GET：向指定的資源發出「顯示」請求。使用GET方法應該只用在讀取資料，而不應當被用於產生「副作用」的操作中，例如在網路應用程式中。其中一個原因是GET可能會被網路爬蟲等隨意訪問。參見安全方法。瀏覽器直接發出的GET只能由一個url觸發。GET上要在url之外帶一些參數就只能依靠url上附帶querystring。

HEAD：與GET方法一樣，都是向伺服器發出指定資源的請求。只不過伺服器將不傳回資源的本文部份。它的好處在於，使用這個方法可以在不必傳輸全部內容的情況下，就可以獲取其中「關於該資源的元資訊（或稱元資料）」。

POST：向指定資源提交數據，請求伺服器進行處理（例如提交表單或者上傳檔案）。數據被包含在請求本文中。這個請求可能會建立新的資源或修改現有資源，或二者皆有。每次提交，表單的數據被瀏覽器用編碼到HTTP請求的body里。瀏覽器發出的POST請求的body主要有兩種格式，一種是application/x-www-form-urlencoded用來傳輸簡單的數據，大概就是"key1=value1&key2=value2"這樣的格式。另外一種是傳文件，會採用multipart/form-data格式。採用後者是因為application/x-www-form-urlencoded的編碼方式對於文件這種二進位的數據非常低效。

PUT：向指定資源位置上傳其最新內容。

DELETE：請求伺服器刪除Request-URI所標識的資源。

TRACE：回顯伺服器收到的請求，主要用於測試或診斷。

OPTIONS：這個方法可使伺服器傳回該資源所支持的所有HTTP請求方法。用'*'來代替資源名稱，向Web伺服器發送OPTIONS請求，可以測試伺服器功能是否正常運作。

CONNECT：HTTP/1.1協議中預留給能夠將連接改為隧道方式的代理伺服器。通常用於SSL加密伺服器的連結（經由非加密的HTTP代理伺服器）。

方法名稱是區分大小寫的。當某個請求所針對的資源不支持對應的請求方法的時候，伺服器應當返回狀態碼405（Method Not Allowed），當伺服器不認識或者不支持對應的請求方法的時候，應當返回狀態碼501（Not Implemented）。

HTTP伺服器至少應該實現GET和HEAD方法，其他方法都是可選的。當然，所有的方法支持的實現都應當符合下述的方法各自的語義定義。

此外，特定的HTTP伺服器還能夠擴展自定義的方法。例如：

PATCH（由 RFC 5789 指定的方法）：用於將局部修改應用到資源。

### 安全方法

對於GET和HEAD方法而言，除了進行獲取資源資訊外，這些請求不應當再有其他意義。也就是說，這些方法應當被認為是「安全的」。客戶端可能會使用其他「非安全」方法，例如POST，PUT及DELETE，應該以特殊的方式（通常是按鈕而不是超連結）告知客戶可能的後果（例如一個按鈕控制的資金交易），或請求的操作可能是不安全的（例如某個文件將被上傳或刪除）。

但是，不能想當然地認為伺服器在處理某個GET請求時不會產生任何副作用。事實上，很多動態資源會把這作為其特性。這裡重要的區別在於使用者並沒有請求這一副作用，因此不應由使用者為這些副作用承擔責任。

### 副作用

假如在不考慮諸如錯誤或者過期等問題的情況下，若干次請求的副作用與單次請求相同或者根本沒有副作用，那麼這些請求方法就能夠被視作「冪等(idempotence)」的。GET，HEAD，PUT和DELETE方法都有這樣的冪等屬性，同樣由於根據協議，OPTIONS，TRACE都不應有副作用，因此也理所當然也是冪等的。

假如一個由若干請求組成的請求序列產生的結果，在重複執行這個請求序列或者其中任何一個或多個請求後仍沒有發生變化，則這個請求序列便是「冪等」的。但是，可能出現一個由若干請求組成的請求序列是「非冪等」的，即使這個請求序列中所有執行的請求方法都是冪等的。例如，這個請求序列的結果依賴於某個會在下次執行這個序列的過程中被修改的變量。

### 對照表

請求方法｜RFC｜請求有payload body｜response有payload body｜安全的｜冪等的｜可快取的

GET｜是｜是｜是｜是

HEAD｜否｜是｜是｜是

POST｜是｜是｜否｜否｜是

PUT｜是｜是｜否｜是｜否

DELETE｜是｜否｜是｜否

CONNECT｜是｜否｜否｜否

OPTIONS｜是｜是｜是｜否

TRACE｜否｜是｜是｜是｜否

PATCH｜是｜是｜否｜否｜否

## 版本

超文本傳輸協議已經演化出了很多版本，它們中的大部分都是向下兼容的。在RFC 2145中描述了HTTP版本號的用法。客戶端在請求的開始告訴伺服器它採用的協議版本號，而後者則在響應中採用相同或者更早的協議版本。

### HTTP/0.9

已過時。只接受GET一種請求方法，沒有在通訊中指定版本號，且不支持請求頭。由於該版本不支持POST方法，因此客戶端無法向伺服器傳遞太多資訊。

### HTTP/1.0

這是第一個在通訊中指定版本號的HTTP協議版本。

### HTTP/1.1

默認採用持續連接（Connection: keep-alive），能很好地配合代理伺服器工作。還支持以管道方式在同時發送多個請求，以便降低線路負載，提高傳輸速度。

HTTP/1.1相較於HTTP/1.0協議的區別主要體現在：

- 緩存處理
- 帶寬優化及網路連接的使用
- 錯誤通知的管理
- 消息在網路中的發送
- 網際網路地址的維護
- 安全性及完整性

### HTTP/2

於2015年5月作為網際網路標準正式發布。

### HTTP/3

最新版本，於2022年6月6日標準化為RFC9114。不依賴TCP，採用基於UDP的傳輸協議QUIC來承載應用層數據。

## 狀態碼

所有HTTP響應的第一行都是狀態行，依次是當前HTTP版本號，3位數字組成的狀態代碼，以及描述狀態的短語，彼此由空格分隔。

狀態代碼的第一個數字代表當前響應的類型：

- 1xx消息——請求已被伺服器接收，繼續處理
- 2xx成功——請求已成功被伺服器接收、理解、並接受
- 3xx重定向——需要後續操作才能完成這一請求
- 4xx請求錯誤——請求含有詞法錯誤或者無法被執行
- 5xx伺服器錯誤——伺服器在處理某個正確請求時發生錯誤

雖然 RFC 2616 中已經推薦了描述狀態的短語，例如"200 OK"，"404 Not Found"，但是WEB開發者仍然能夠自行決定採用何種短語，用以顯示本地化的狀態描述或者自定義資訊。

## 持續連線

<image>

在HTTP 0.9和1.0中，TCP連線在每一次請求/回應對之後關閉。在HTTP 1.1中，引入了保持連線的機制，一個連接可以重複在多個請求/回應使用。持續連線的方式可以大大減少等待時間，因為在發出第一個請求後，雙方不需要重新執行TCP交握程序。

HTTP 1.1還改進了HTTP 1.0的頻寬。例如，HTTP 1.1引入了分塊傳輸編碼，以允許傳遞內容可以在持續連線上被串流傳輸而不必使用到緩衝器。HTTP管道允許客戶端在收到每個回應之前發送多個請求，進一步減少使用者感受到的滯後時間。協議的另一個補充是字節服務，允許客戶端請求資源的某一部份，伺服器僅回應某資源的指明部分。

## 協議例子

下面是一個HTTP客戶端與伺服器之間會話的例子，運行於www.google.com，埠80

### 請求資訊

發出的請求資訊（message request）包括以下幾個:

- 請求行（例如GET /images/logo.gif HTTP/1.1，表示從/images目錄下請求logo.gif這個文件）
- 請求頭（例如Accept-Language: en）
- 空行
- 其他消息體

請求行和標題必須以作為結尾。空行內必須只有而無其他空格。在HTTP/1.1協議中，所有的請求頭，除Host外，都是可選的。

### 客戶端請求

```http
GET / HTTP/1.1
Host: www.google.com
```

（末尾有一個空行。第一行指定方法、資源路徑、協議版本；第二行是在1.1版里必帶的一個header作用於指定主機）

### 伺服器應答

```http
HTTP/1.1 200 OK
Content-Length: 3059
Server: GWS/2.0
Date: Sat, 11 Jan 2003 02:44:04 GMT
Content-Type: text/html
Cache-control: private
Set-Cookie: PREF=ID=73d4aef52e57bae9:TM=1042253044:LM=1042253044:S=SMCc_HRPCQiqy
X9j; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Connection: keep-alive
```

（緊跟著一個空行，並且由HTML格式的文本組成了Google的主頁）

在HTTP1.0，單一TCP連接內僅執行一個「客戶端發送請求—伺服器發送應答」周期，之後釋放TCP連接。在HTTP1.1優化支持持續活躍連接：客戶端連續多次發送請求、接收應答；批次多請求時，同一TCP連接在活躍（Keep-Live）間期內復用，避免重複TCP初始握手活動，減少網路負荷和響應周期。此外支持應答到達前繼續發送請求（通常是兩個），稱為「流線化」（stream）。

## 類似協議

Gopher是1990年代早期被HTTP取代的內容傳遞協議。SPDY是Google開發的HTTP的替代方案，它被新版本的HTTP協議HTTP/2所取代。