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:
(1-3) 統一介面 (Uniform Interface) 介紹 HTTP 介面 的主要目標,
並提及背後的 設計原則 與 指導架構風格 — REST,
使您擺脫『 REST = CRUD + URL 』的 錯誤迷思,不再瞎子摸象。
二、資源、表示、URI
要上網時,你可能會先開啟一瀏覽器:
此時空空如也,我們得找尋、訪問 感興趣的 頁面 (資源),
而 網址 便是一種 (2-1) 統一資源識別符 (URI) (i.e., 辨識資源的方法)。
資源可能是一個檔案、資料庫的查詢結果、另一群資源的集合、
抽象的服務、『非虛擬』的物件(ex: 人)…,
任何能被命名的資訊,都是 — (2-2) 資源 (resource)。
決定了 請求目標 後,HTTP 透過可靠的 (reliable) 傳輸/會話層 (e.g., TCP),
進行連線 (connection) 以 交換訊息 (Exchange Message)。
然而,(2-3) URI 設計 是給人看的,本身無法連線,
必須 透過 名稱解析服務 (ex: DNS),
找到 Server (或 代理、閘道、負載平衡器) 的 IP 位址,並藉此訪問:
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),
標題與系列文皆沿用早期翻譯習慣 (傳輸),但心中仍得有把尺 。
四、請求/回應 (Request/Response)
那麼,除了在 網址列 中輸入 URI,
還有什麼方式送出 HTTP 請求呢?
Ans:
可以用 JavaScript 的 XHR、jQuery、Fetch 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 個請求:
另外,除了普遍的 GET、POST 請求,
還有常用於 API 的 (4-3) HEAD、PUT、DELETE …等請求方法,
需依不同 (4-1) 請求方法特性 決定最佳使用時機。
五、分層系統 (Layered System)
如文初所述,連線並非總是單純的 雙向連接 (bidirectional connection),
(5-1) 訊息路由 說明了當具有 中介 (Intermediary) 時,
請求/回應 如何在各節點間傳遞。
(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 則留言
感謝您的分享
解說的很詳細
而且排版 讓人看得很舒服
感謝支持! 排版我還在摸索中 😂
這種鬆散的行距與斷行,感覺會被國文老師罵死 www
感謝深入淺出的說明!
雖然以前也看過不少教學blog,
不過還是第一次就這樣把整個系列文章都看過。
希望有機會能看到後續章節。
謝謝您的耐心閱讀 😭
會有後續章節的 敬請期待 (可能得半年 😂
若有任何建議再麻煩告訴我囉
感謝分享 詳細系列文
謝謝 😃
感謝分享!!
網路上充斥一堆模稜兩可的文章
就這系列最扎實
GET 與 POST 的區別也相當專業
不像這篇超級唬爛的 “99%的人都理解错了HTTP中GET与POST的区别”
https://zhuanlan.zhihu.com/p/22536382
感謝支持! 😭 有任何建議再麻煩告知
話說,我不喜歡抨擊別人
但那篇真的超唬爛 😂
好文!
寫得很詳細,尤其對我剛從別領域轉換過來的新手,觀念講解的很清楚,大感謝
謝謝您!任何問題都歡迎詢問喔 😃
写的逻辑性真好,而且涉及的非常全面,正在学习中。
感謝!喜歡的話 再麻煩幫分享囉 😆
學習中 很有幫助 謝謝你
感謝分享,學習到很多,很多配圖讀起來覺得有趣!
非常感謝!謝謝您不嫌棄我的劣圖 😂
寫得好~
寫得好~
非常感謝!😆
寫的hen棒R
寫的很詳細,現在喜歡研究底層技術的人愈來愈少了,我自己寫 Socket, IOCP 相關的程式超過十年的時間,最近有一些計劃,看看鄭兄有沒有興趣聊一聊呢?