之前的文章提過了 HTTP 封包 request line 中的 request method 和 URI,知道了怎麼透過不同的方法請求伺服器,還有怎麼找到資源的位置。現在要進一步來看看 HTTP 協定的不同版本,從最早的 HTTP/0.9 到最新的 HTTP/3,各個版本間經歷了哪些變化~
上圖來自維基百科
在 1991 年被定義,並預設使用埠號 80。當時的功能非常簡單,使用者端只能從伺服器獲取資料,無法將任何其他資訊傳送到伺服器。這個版本透過 TCP/IP 建立連接,並且在文件傳輸結束後,連線會自動關閉。
請求格式:
請求的內容只有一行,由唯一的 GET 方法、空格以及 URL 所組成,就如以下範例:
GET /index.html
甚至不需要包括完整的 URL,例如:http://example.com:80/index.html
,因為協定、網域名稱以及埠號在建立連接的時候已經被使用了,不需要在每次請求中都重複指定,除非請求是透過 gateway 發送的,才會需要提供完整的 URL,因為需要完整的資訊來轉發請求並確保它能夠找到正確的目標資源。
回應格式:
回應也十分簡單,就只包含文件本身,例如以下:
<html>
Hello world!
</html>
在遇到錯誤時,沒有所謂狀態碼(status code)的概念,此時回應的就只會是特別的 HTML 檔,透過文件內容記載錯誤訊息,同時伺服器也無法透過回應的結構來提供相對應的錯誤處理方式。
在 1996 年時, RFC 1945 定義了新一代的 HTTP 協定 HTTP/1.0
,擴充了一些功能,使得 HTTP 在更廣泛使用的場景中能夠有更好的靈活性:
對於請求以及回應的訊息格式有了明確的定義
正式定義了請求行的結構,由請求方法、URI 以及協定版本組成,如以下結構:
GET /index.html HTTP/1.0
雖然有了正式定義,不過在 HTTP/1.0中並未強制要求加入協定版本,在未指定協定版本時,接收方將預設為HTTP/0.9。直到在HTTP/1.1中對於協定版本的加入才有強制要求。
狀態行:加入了狀態碼(status code)的概念,讓伺服器能夠清楚告知客戶端請求的結果。狀態碼允許客戶端根據回應的狀態進行不同的處理,大幅提升了協定的靈活性。
新增了 POST、HEAD 兩種請求方法。
透過 Content-Type 標頭可以傳輸 HTML 文件以外的格式檔案,如圖片等。
支援快取機制:允許伺服器通過 Expires 標頭告知使用者端某些資源可以被快取,減少不必要的重複請求,提升效能。
每個請求都需要建立單獨的 TCP 連接:HTTP/1.0 在每次請求時都需要重新建立一個 TCP 連接,並在回應結束之後立即斷開。這導致了網絡資源的浪費,對於頻繁的資源請求來說,性能顯著下降。
HTTP/0.9 的禁用:由於不支援標頭,無法支援任何透過 Host 標頭實現的 Name-based virtual hosts(網址名稱對應的虛擬主機),因此只要是基於這個技術的網站都必須停用 HTTP/0.9。不知道什麼是 Name-based virtual hosts 可以參考這個網站
HTTP/1.0 逐漸被HTTP/1.1 和更新的協定(如 HTTP/2 和 HTTP/3)所取代:因為每個請求都需要建立一個新的 TCP 連接,並在回應結束之後立即斷開。這導致了效率低下,尤其是對於現代應用的頻繁資源請求,性能會顯著下降。而在 HTTP/1.1 引入了持久連接(Persistent Connections),讓多個請求可以在同一個 TCP 連接中完成,大大提高了網絡性能和效率。
今天介紹了HTTP/0.9 與 HTTP/1.0 兩個版本,雖然現在幾乎都已經被取代了,不過對於現在網路的發展也是奠定了很重要的基礎,也是需要了解一下。明天的文章會繼續介紹其他的 HTTP 協定版本,那就明天見~
MDN
RFC 1945
RFC 9112
RFC 9113
RFC 9114
The Original HTTP as defined in 1991