HTTP

HTTP/1.1 — 超文本傳輸協定 (Hypertext Transfer Protocol)

HTTP (Hypertext Transfer Protocol) 超文本傳輸協定
主要是架構於 TCP/IP 之上的 應用層,為 無狀態請求-回應 通訊協定。
 

 
HTTP 由最初的 頁面、媒體傳輸,發展為今日 Web 應用的根基,
許多 APP、嵌入裝置、軟體…,皆依此取得服務,
因此,也成了大部分開發者的必備技能。
 
全系列主要以 RFC 7230 ~ RFC 7235 規範而著,
並以 HTTP/1.1 的主架構師 — Dr. Roy Thomas Fielding 所著之 著名論文 為輔,
期望給您最正確、標準的 HTTP 介紹 😃。
 


 

版本

現今 HTTP 的最新版本,為 2015 年發表的『 HTTP/2 』,
於是,許多朋友便好奇,為何還寫 『 HTTP/1.1 』這個 18 歲的老東西。
(有空應該會寫 HTTP/2 啦 😂)
 
主要原因在於:

HTTP/2 主要是對 HTTP/1.1 做效能上的優化與改良

 
例如:
引入了 表頭欄位壓縮 (header field compression),
允許在同一個連線中,做 多次並發交換 (multiple concurrent exchanges),
並且 加入了 伺服器推送 (Server Push) 功能…。
 
然而,語意上並沒有太大改變
加上處於過渡期, HTTP/1.1 仍是目前最普遍的版本。
 


 

HTTP/1.1 導覽

HTTP 系列 頁面,提供了完整的文章列表:

 
 
接著以一個簡易流程,概略介紹各章節的用途與意涵:
 
 

一、介面

在開始之前得先闡明角色術語,以利溝通 🤔,
(1-2) 角色 (Client、Server) 簡短地介紹比 Client、Server 更精確的名詞。
 
並且,得知道 通訊協定 始終是個 介面,如何實作全憑各 Client、Server:
 
DIP-electricity-ex
 
(1-3) 統一介面 (Uniform Interface) 介紹 HTTP 介面 的主要目標,
並提及背後的 設計原則 與 指導架構風格 — REST
使您擺脫『 REST = CRUD + URL 』的 錯誤迷思,不再瞎子摸象。
 
 

二、資源、表示、URI

要上網時,你可能會先開啟一瀏覽器:
empty-browser
 
此時空空如也,我們得找尋、訪問 感興趣的 頁面 (資源),
而 網址 便是一種 (2-1) 統一資源識別符 (URI) (i.e., 辨識資源的方法)。
 
 
資源可能是一個檔案、資料庫的查詢結果、另一群資源的集合、
抽象的服務、『非虛擬』的物件(ex: 人)…,
任何能被命名的資訊,都是 — (2-2) 資源 (resource)
web-resources
 
 
決定了 請求目標 後,HTTP 透過可靠的 (reliable) 傳輸/會話層 (e.g., TCP),
進行連線 (connection) 以 交換訊息 (Exchange Message)
 
然而,(2-3) URI 設計 是給人看的,本身無法連線,
必須 透過 名稱解析服務 (ex: DNS),
找到 Server (或 代理、閘道、負載平衡器) 的 IP 位址,並藉此訪問:
dns-example
 
TCP 建立連線的程序,稱為 三向交握 (Three Way Handshake)
若有興趣,可閱讀 TCP 序列號 (Sequence Number, SEQ) 暸解更多:
 

三向交握
 


 

三、訊息、表示、酬載

連線成功後,使用者代理 便將 請求訊息 轉移 (transfer) [註] 至 Server。
 
請求訊息 (request message) 範例:

GET /31/fetch-api HTTP/1.1

Host: notfalse.net User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0) Gecko/20100101 Firefox/53.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-encoding: gzip, deflate, br accept-language: zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4

 

 
關於 請求/回應 訊息 的格式、規範,
可參考 (3-1) 訊息格式 (Message Format)
 
一個資源,能擁有多種不同的 (3-2) 表示方式
例如,gzip or br 編碼,JSON or XML 格式…。
 
因此,可能得在請求訊息中 提供足夠資訊,
以與 Server 進行 (3-3) 內容協商 (Content Negotiation)
 
此外,每種 使用者代理 對請求訊息的編碼、轉移 (transfer) [註] 方式不一,
也得考量 (3-4) 酬載元資料 的設置。
 

 
 
[註]:
需注意的是,儘管 Transport 與 Transfer 皆譯為 傳輸,兩者並不相等:

Transport 有 傳輸、傳送之意,而 Transfer 譯為『 轉移 』或許更適合。

 
HTTP 並非 設計為 傳輸協定 (Transport Protocol)
而是以 訊息 (message) 反映 Web 架構語意的 轉移協定 (Transfer Protocol)
標題與系列文皆沿用早期翻譯習慣 (傳輸),但心中仍得有把尺 ruler
 


 

四、請求/回應 (Request/Response)


 
 
那麼,除了在 網址列 中輸入 URI,
還有什麼方式送出 HTTP 請求呢?
 
browser-URL
 
Ans:
可以用 JavaScript 的 XHRjQueryFetch API
或者 (4-2) GET vs. POST 介紹的 HTML 表單
還有 (4-4) 發送請求 的 Postman、Insomnia 等 GUI 工具
甚至 (4-5) 以 C Socket 實作 HTTP Client
 
 
並且,透過 (4-6) 回應狀態碼 (下方範例的 200 OK),
可以快速判斷 回應狀態 (e.g., 成功、失敗):

HTTP/1.1 200 OK

Content-Type: text/html; charset=utf-8 Date: Sat, 18 Feb 2017 00:01:57 GMT Server: nginx/1.11.8 transfer-encoding: chunked Connection: Close

 

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>echo</title> ....略

 
 
您可使用 瀏覽器 的『開發者工具』來檢視 請求/回應訊息,
快捷鍵 通常為 Ctrl+Shift+I (Windows) 或 Cmd+Opt+I (Mac) 或 F12,也能透過:

Google Chorme: 檢視 -> 開發人員選項 -> 開發人員工具
FireFox: 工具 -> 網頁開發者 -> 網頁工具箱
Safari: 開發 -> 顯示網頁檢閱器

 
(以撰文時間最新版本為主)
 
例如,這個可愛狗狗 🐶 的頁面,就送出了 6x 個請求:
stock-up-request
 
 
另外,除了普遍的 GET、POST 請求,
還有常用於 API 的 (4-3) HEAD、PUT、DELETE …等請求方法,
需依不同 (4-1) 請求方法特性 決定最佳使用時機。
 


 

五、分層系統 (Layered System)

如文初所述,連線並非總是單純的 雙向連接 (bidirectional connection),
(5-1) 訊息路由 說明了當具有 中介 (Intermediary) 時,
請求/回應 如何在各節點間傳遞。
 
中介 (Intermediaries) 示意圖
 
(5-2) 代理 (proxy)、隧道 (tunnel) 與 閘道 (gateway) 是最普遍的三種中介,
利用各自不同特性,能實作更強健的系統與功能。
 

 
例如,以 代理 做 (5-3) 流量監控 (Traffic Monitor)
甚至能用來實作手遊外掛 😂:

 
咦!? 人人都用 Proxy 隱瞞身份幹壞事怎辦?
 
(5-4) 訊息追蹤 (Message Tracing) 提供了:
源伺服器 如何在多個中介裡,取得 User Agent 的身份、IP 位址 的思路,
以及利用上個來源,防範 CSRF 攻擊 的簡易方式。
 

 
最後,以 (5-5) 虛擬主機 (Virtual Host)
示範 代理 (proxy) 與 源伺服器 連線,需做的小更動,
也帶出了 HTTP 早期的設計缺陷 😂。
 


 

六、快取 (Cache)

倘若 使用者代理 (User Agent)源伺服器 (Origin Server) 橫跨多國,網路延遲將非常可觀:

 
此時,能透過 (6-1) 快取 (Cache),消除 部分 甚至全部 的節點互動,顯著地提升效能,
最佳的情況,當然是 (6-2) 免網路請求 !! 直接使用 新鮮回應 (fresh response)。
 
但快取可能隨著時間失效,(6-3) 何時驗證快取 ? 便顯得格外重要,
(6-4) 說明了 驗證快取 及更新元資料的方式。
 


 

其他

還有太多太多 HTTP 規範 與 延伸,
例如,認證 與 授權、連線管理、Cookie、安全 HTTP (i.e., HTTPS)、HTTP/2…族繁不及備載。
 
授權 (Authorization) 方面,我推薦使用 OAuth2 (簡單好實作),
關於 OAuth2 教學,我認為無人能出其右:OAuth 2.0 筆記 (1) 世界觀
 
HTTP/1.1 連線管理 (Connection Management) 較為簡單,
推薦閱讀 阮一峰 — HTTP 協議入門 了解更多,
這部分我想等未來撰文 HTTP/2 時,才加以比較說明。
 
這系列會緩慢更新、著做下去,但因個人業務繁忙,
將停滯撰文一段時間,以此六章暫告一段落,
文中有任何問題、或需要任何補充 可再留言、Mail 給我,感恩 😇。
 
 

作者: 鄭中勝
喜愛音樂,但不知為何總在打程式 ? 期許能重新審視、整理自身所學,幫助有需要的人。

在《HTTP/1.1 — 超文本傳輸協定 (Hypertext Transfer Protocol)》中有 21 則留言

    1. 感謝支持! 排版我還在摸索中 😂
      這種鬆散的行距與斷行,感覺會被國文老師罵死 www

  1. 感謝深入淺出的說明!
    雖然以前也看過不少教學blog,
    不過還是第一次就這樣把整個系列文章都看過。
    希望有機會能看到後續章節。

    1. 謝謝您的耐心閱讀 😭
      會有後續章節的 敬請期待 (可能得半年 😂
      若有任何建議再麻煩告訴我囉

    1. 感謝支持! 😭 有任何建議再麻煩告知
      話說,我不喜歡抨擊別人
      但那篇真的超唬爛 😂

  2. 寫的很詳細,現在喜歡研究底層技術的人愈來愈少了,我自己寫 Socket, IOCP 相關的程式超過十年的時間,最近有一些計劃,看看鄭兄有沒有興趣聊一聊呢?

發表迴響