HTTP拾技雜談
簡單聊聊HTTP中的那些東西
文章目錄
- HTTP拾技雜談
- 前言
- HTTP協議
- 1.請求從客戶端到服務器端的4個步驟
- 一般客戶端請求如下:
- 服務端響應如下
- 2.Keep-Alive
- HTTP方法
- Cookie
- 總結
前言
超文本傳輸協議(Hypertext Transfer Protocol ,HTTP)是一個標準,定義了Web客戶端如何與服務器對話,以及數據如何從服務器傳回客戶端。盡管通常任務HTTP是一種傳輸HTML文件以及文件中內嵌圖片的方法,但實際上HTTP是一個數據格式。——《java網絡編程》
HTTP協議
HTTP連接使用TCP/IP來傳輸數據。
1.請求從客戶端到服務器端的4個步驟
- 默認情況下,客戶端在80端口與服務器打開一個TCP連接,URL可以指定其他端口
- 客戶端向服務器發送消息,請求指定路徑上的資源。請求分為首部、可選地址、請求數據。
- 服務器向客戶端回復響應。以響應碼開頭,后面是包含元數據的首部、一個空行、所請求的文檔(數據)或錯誤消息。
- 服務器關閉連接。
以上就是基本HTTP1.0過程,在HTTP1.1及以后版本中,可以復用TCP連接實現發送多個請求。在1.1中請求和響應可以分為多個塊發送。
一般客戶端請求如下:
POST /api/data HTTP/1.1 # 請求行(方法 + URI + HTTP版本)
Host: www.example.com # 目標主機(必需首部)
User-Agent: Mozilla/5.0 # 客戶端標識
Content-Type: application/json # 消息體格式說明
Content-Length: 27 # 消息體字節長度(必需首部)
Accept: application/json # 期望的響應格式
Authorization: Bearer abc123 # 認證令牌
Connection: keep-alive # 連接控制#注意這里的空一行是標準
{"key": "value", "num": 42} # 消息體(實際傳輸的數據)
第一行為請求行,包括方法、從服務器獲取資源路徑以及HTTP版本。
其他則是以 Key:Value組成的信息。
像User-Agent代表瀏覽器版本,host服務器名,Accept,告訴服務器,客戶端可以處理什么樣的數據(定義服務器返回格式)。
這些類型統稱為MIME類型,分為兩級:類型和子類型。例如:application/json
text/*
image/*
application/*
...等
當然也可以自定義非標準的定制類型和子類型,只要以x-開頭。例如flash文件,使用application/x-shockwave-flash類型。
最后以空行,或者空行+數據體
服務端響應如下
HTTP/1.1 200 OK # 狀態行(協議版本 + 狀態碼 + 原因短語)
Server: nginx/1.18.0 # 服務器軟件及版本
Date: Fri, 13 Oct 2023 05:30:15 GMT # 響應生成時間
Content-Type: text/html; charset=UTF-8 # 消息體的格式和編碼
Content-Length: 1234 # 消息體的字節長度
Connection: keep-alive # 連接控制(保持活躍)
Cache-Control: max-age=3600 # 緩存策略(有效期1小時)
ETag: "abc123xyz" # 資源版本標識符
Last-Modified: Mon, 09 Oct 2023 12:00:00 GMT # 資源最后修改時間<!DOCTYPE html> # 空行(分隔首部和消息體)
<html> # 消息體(實際返回的內容)<head><title>Example Page</title></head><body><h1>Hello World</h1></body>
</html>
第一行表示服務器使用的協議HTTP1.1,緊跟一個響應碼。其他首部行則指出請求的日期、消息體字節長度等
2.Keep-Alive
在HTTP請求的首部中大家是否注意到Keep-Alive,他表示可以重用一個socket:
Connection:Keep-Alice。
在HTTP1.0會為每個請求打開一個新的連接,而這樣打開和關閉消耗的資源遠遠大于實際傳輸數據的開銷。所以在HTTP1.1以后就默認支持,復用socket連接,如果需要關閉則使用上述key-value顯示控制。
- 在java中可以通過http.keepAlive控制true/false,來控制socket復用
- http.maxConnections可以表示希望同時打開的socket的數量,來保證服務器不會被大量連接沖崩潰。
HTTP方法
HTTP服務器的遵循請求-響應模式:無狀態請求+無狀態響應。
HTTP的方法主要有4個:
POST、GET、PUT、DELETE
對于這些方法的使用,再談談幾點容易被忽略的細節:
- GET方法獲取一個資源,它沒有副作用,如果失敗可以反復執行,而不用擔心有什么問題
- GET輸出可能會被緩存,可以通過首部取消緩存進行禁用
- PUT方法表示將資源上傳到服務器,但它具有冪等性。重復該方法也不用擔心是否失敗,兩次將同一個文檔放在同一個位置并不影響。
- DELETE與PUT一樣具有冪等性,重復執行,也只會將資源刪除一次。
- POST是最常用的方法,POST要用于不能重復的不安全的操作,如完成一個交易。
Cookie
很多網站使用一些小文本串在連接之間存儲持久的客戶端狀態,這些稱為cookie。
cookie在請求和響應的HTTP首部中,由服務器傳遞到客戶端,再從客戶端傳回服務器。
cookie可以是標識會話ID、購物車、登錄憑據等信息,也可以存無意義的值。
要在瀏覽器設置一個cookie,則需要服務器端在響應中使用Set-Cookie首部行:
HTTP/1.1 200 OK # 狀態行(協議版本 + 狀態碼 + 原因短語)
Content-Type: text/html; charset=UTF-8 # 消息體的格式和編碼
Set-Cookie: xxx=dsahjfkeqyowqlf # 設置cookie
而后,客戶端再向同一個服務發送請求:
GET /index.html HTTP/1.1 # 請求行(方法 + URI + HTTP版本)
Host: www.example.com # 目標主機(必需首部)
Cookie:cart = dsahjfkeqyowqlf #cookie要與服務器給的一致
當然服務器可以設置不止一個cookie,可以有多個Set-Cookie,用于控制過期時間、路徑、端口、值等信息。
默認情況下,cookie來自哪個服務器則應用于哪個服務器。網站也可以指示一個cookie用于整個子域,例如從www.foo.example.com響應的:
Set-Cookie:user = elharo;Domain=.foo.example.com
表示瀏覽器除了可以用cookie返回最初的www.foo.example.com,還可發送給*.foo.example.com
當然還可以縮小它的使用域
例如:Set-Cookie: user=elharo; Path=/restricted,表示請求服務器上子樹/restricted,可以。而相同網站的其他目錄中就不能使用這個cookie。
在Set-Cookie中使用expires = Wdy, DD-Mon-YYYY HH:MM:SS GMT 可以設置cookie的過期時間。
設置Max-Age = 3600 ,則表示3600秒后過期,此時瀏覽器會從緩存中刪除這些cookie。
總結
本章節介紹了HTTP協議是現代Web通信的核心,其設計簡潔高效,支持多種請求方法和數據格式,并通過Cookie機制實現了客戶端狀態的持久化。隨著HTTP版本的演進,連接復用等優化機制進一步提升了通信性能。本文詳細介紹了HTTP協議的基本原理、請求響應格式、方法特性以及Cookie機制。