超文本傳輸協定

適用於分佈式協作超媒體信息系統的應用協議

超文本傳輸協定(英語:HyperText Transfer Protocol,縮寫:HTTP)是一種用於分佈式、協作式和超媒體訊息系統的應用層協定[1]。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英語Internet Engineering Steering Group進行討論[2],於2015年2月17日被批准。[3] HTTP/2標準於2015年5月以RFC 7540正式發表,取代HTTP 1.1成為HTTP的實作標準。[4]

協定概述

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 RFC 9110 選擇性
HEAD RFC 9110 選擇性
POST RFC 9110
PUT RFC 9110
DELETE RFC 9110 選擇性
CONNECT RFC 9110 選擇性
OPTIONS RFC 9110 選擇性
TRACE RFC 9110
PATCH RFC 5789

版本

超文本傳輸協定已經演化出了很多版本,它們中的大部分都是向下相容的。在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月作為網際網路標準正式發布。[5]

HTTP/3

最新版本,於2022年6月6日標準化為RFC9114。[6]會拋棄使用TCP,透過UDP上使用QUIC來承載應用層資料。

狀態碼

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

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

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

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

持續連線

 

在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)
  • 空行
  • 其他訊息體

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

客戶端請求

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

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

伺服器應答

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取代的內容傳遞協定。SPDYGoogle開發的HTTP的替代方案,它被新版本的HTTP協定HTTP/2所取代。

參見

參考

  1. ^ Fielding, Roy T.; Gettys, James; Mogul, Jeffrey C.; Nielsen, Henrik Frystyk; Masinter, Larry; Leach, Paul J.; Berners-Lee, Tim. Hypertext Transfer Protocol – HTTP/1.1. IETF. June 1999. RFC 2616. 
  2. ^ Raymor, Brian. Wait for it – HTTP/2 begins Working Group Last Call!. Microsoft Open Technologies. 2014-08-07 [2014-09-08]. (原始內容存檔於2014-10-06). 
  3. ^ Mark Nottingham. HTTP/2 Approved. www.ietf.org. Internet Engineering Task Force. 2015-02-18 [2017-01-04]. (原始內容存檔於2015-02-20). 
  4. ^ RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2). IETF. May 2015 [14 May 2015]. (原始內容存檔於2015-06-23). 
  5. ^ RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2). IETF. May 2015 [14 May 2015]. (原始內容存檔於2015-06-23). 
  6. ^ HTTP/3. [2022-06-07]. (原始內容存檔於2022-06-06). 

外部連結