HTTP 協議徹底解析

HTTP 的全稱是 HyperText Transfer Protocol (超文本傳輸協議)的縮寫,是一種創建在 TCP 上的無狀態鏈接。HTTP 是互聯網的基礎協議,用於客戶端與服務器之間的通訊,它規定了客戶端和服務器之間的通訊格式,包括請求與響應的格式。html

基本的工做流程是客戶端發送一個 HTTP 請求,服務端收到請求開始處理,處理結束返回給客戶端結果,客戶端對結果進行處理並展現。node

如今最流行的 HTTP 版本仍是 1997 年發佈的 HTTP/1.1。 git

目錄

  • HTTP 的工做方式
  • HTTP 的報文格式
  • HTTP 起始行
  • HTTP 請求方法
  • HTTP 響應碼
  • HTTP Headers

1、 HTTP 的工做方式

1.1 請求過程

客戶端向服務端發送一段請求報文,服務端收到後,返回響應報文,客戶端對響應內容進行展現。github

一個 HTTP 的請求一定是由客戶端發起,服務器端回覆響應。服務器在沒有接收到請求以前不會發送響應。web

名詞解釋算法

客戶端:請求訪問文本或圖像等資源的一端。json

服務端:提供資源響應的一端。api

資源:網絡上的一切內容都是資源,不管是圖片文字仍是動態代碼。瀏覽器

1.2 請求方式

web 瀏覽器請求:

請求過程以下 ⬇️緩存

  1. 用戶輸入地址後回車或點擊連接
  2. 瀏覽器拼裝 HTTP 報文併發送請求給服務器
  3. 服務器處理請求後,發送響應報文給瀏覽器
  4. 瀏覽器解析響應報文並使用渲染引擎顯示到界面

APP 客戶端請求:

請求過程以下 ⬇️

  1. 用戶點擊或界面自動觸發聯網需求
  2. Android 代碼調用拼裝 HTTP 報文併發送請求到服務器
  3. 服務器處理請求後發送響應報文給手機
  4. Android 代碼處理響應報文並做出相應處理(如儲存數據、加工數據、顯示數據到界面)

1.3 報文是什麼

報文是在 HTTP 應用程序之間發送的數據塊。這些數據塊以一些文本的元信息 (meta 標籤中的信息) 開頭,描述了報文的內容及含義。

每條報文都包含一條來自於客戶端的請求,或者一條來自於服務端的響應

它由 3 部分組成:對報文進行描述的「起始行」、包含屬性的「首部(Header)」以及可選的、包含數據的「主體(body)

2、HTTP 的報文格式

2.1 請求報文的格式

<method> <path> <HTTP version>
<headers>

<entity-body>
複製代碼

2.2 響應報文的格式

(注意,只有起始行的語法與請求報文有所不一樣)

<HTTP version> <status code> <reason-phrase>
<headers>

<entity-body>
複製代碼

下面是對各部分的簡要描述,後面會詳細介紹。

  • 方法 (method) 客戶端但願服務器對資源執行的動做,常見的方法有 Get、Post、HEAD 等。
  • 請求路徑 (path) 請求的 URL 描述了要對哪一個資源執行這個方法,是給服務器看的。
  • HTTP 版本(HTTP version)
  • 狀態碼(status code) 不一樣狀態碼對應不一樣的響應狀態
  • 緣由短句(reason-phrase) 對狀態碼進行簡單的描述。
  • 首部(headers) 包含許多鍵值對,是對響應數據的一些格式信息。

3、 Method(請求方法)

最多見的請求方法就是 GETPOST了。除此以外還有 PUTDELETEHEAD 等。

GET

  • 最多見的請求方式
  • 指定請求路徑,向服務器請求資源
  • 只獲取資源,不對服務器數據進行修改
  • 不發送 body
GET  /users/1  HTTP/1.1
Host: api.github.com
複製代碼

對應的 Retrofit 的代碼:

@GET("/users/{id}")
Call<User> getUser(@Path("id") String id, @Query("gender") String gender);
複製代碼

Post

  • 用戶增長或者修改資源
  • 包含 body,發送給服務器的內容寫在 body 裏面
POST  /users  HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
複製代碼

對應的 Retrofit 的代碼:

@FormUrlEncoded
@POST("/users")
Call<User> addUser(@Field("name") String name, @Field("gender") String
gender);
複製代碼

PUT

  • 用於修改資源
  • 包含 body,發送給服務器的內容寫在 body 裏面
PUT  /users/1  HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
複製代碼

對應的 Retrofit 的代碼:

@FormUrlEncoded
@PUT("/users/{id}")
Call<User> updateGender(@Path("id") String id, @Field("gender") String
gender);
複製代碼

DELETE

  • 用於刪除資源
  • 不發送 body
DELETE  /users/1  HTTP/1.1
Host: api.github.com
複製代碼

對應的 Retrofit 的代碼:

@DELETE("/users/{id}")
Call<User> getUser(@Path("id") String id, @Query("gender") String gender);
複製代碼

HEAD

  • HEADGET 的使用方式徹底相同。
  • 區別在於,HEAD 請求的返回響應中沒有 Body
  • 用途:好比下載需求,返回的 Headers 中有下載內容的大小,能夠用於顯示進度。

小知識點

GETPUTDELETE 都是冪等操做,就是說,請求一次和請求屢次的結果是同樣的。 好比,GET 請求一個數據,請求一次和請求十次返回的結果是同樣的,PUT 一樣修改一個數據,修改一次和修改十次,結果也都是同樣的。

4、狀態碼(status code)

狀態碼是對結果進行類型化的描述的,好比「請求成功」、「內容未找到」等 主要分爲 5 類。

1xx:臨時性消息。

100:繼續發送
101:正在切換協議
複製代碼

2xx:成功。

200:OK (最多見) 
201:建立成功
複製代碼

3xx:重定向。

301:域名永久移動
302:暫時移動
304:內容未改變,請求被重定向到客戶端本地緩存
複製代碼

4xx:客戶端錯誤

400:客戶端請求錯誤,服務器不理解請求的語法。
401:未受權,要求進行身份驗證。
403:被禁止,服務器拒絕請求。
404:找不到內容,服務器找不到請求的網頁。(最多見)
複製代碼

5xx:服務器錯誤

500:服務器內部錯誤 (最多見)
503:服務不可用
複製代碼

5、首部(Headers)

首部包含多個請求頭,是用來描述消息的元數據(meta data)。

首部字段有不少,主要分爲如下幾類:

  • 通用首部 => 提供了與報文相關的最基本的信息
  • 請求首部 => 只在請求報文中有意義的首部
  • 響應首部 => 只在響應報文中有意義的首部
  • body 首部 => 描述 body 的首部

下面咱們就說一些比較經常使用的。

5.1 通用首部

Date

提供日期和時間標誌,說明報文是在什麼時間建立的。

Date: Tue, 12 Feb 2019 07:32:07 GMT
複製代碼

Connection

容許客戶端和服務器指定與請求/響應鏈接有關的選項。

Connection: keep-alive
複製代碼

其餘通用首部

Via : 顯示報文通過的中間節點(代理、網關)。

via: cache25.l2ot7-1[0,304-0,H], cache25.l2ot7-1[1,0], cache5.us14[342,200-0,H]
複製代碼

Transfer-Encoding : 告知接收端爲了保證報文的可靠傳輸,對報文采用了什麼編碼方式。

Transfer-Encoding: chunked
複製代碼

Cache-Control : 指定緩存的控制方式。

cache-control: no-store, no-cache, must-revalidate, proxy-revalidate
複製代碼

5.2 請求首部

Host

給出了接收請求的服務器的主機名和端口。(注意:不是在網絡上用於尋址的,⽽是在目標服務器上定位子服務器。)

Host: api.github.com
複製代碼

Accept

用來告訴服務端客戶端會接受的媒體類型,包括客戶端須要什麼,可使用什麼,以及不想要什麼。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

'*' 用來表示通配符。
;q= (q-factor weighting)
值表明優先順序,用相對質量價值表示,又稱爲權重。
複製代碼

Accept-Charset

用來告知服務器,客戶端能夠處理的字符集類型。

Accept-Charset: utf-8, iso-8859-1;q=0.5
複製代碼

Accept-Encoding

用來將客戶端可以理解的內容編碼方式告知服務器,服務端會選擇一個客戶端提議的方式。

Accept-Encoding: gzip, deflate, br

gzip:表示採用 Lempel-Ziv coding (LZ77) 壓縮算法,以及32位CRC校驗的編碼方式。
compress:採用 Lempel-Ziv-Welch (LZW) 壓縮算法。
deflate:採用 zlib 結構和 deflate 壓縮算法。
br:表示採用 Brotli 算法的編碼方式。
identity:用於指代自身(例如:未通過壓縮和修改)。除非特別指明,這個標記始終能夠被接受。
複製代碼

Accept-Language

用來告訴服務器,客戶端可以理解哪些語言

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
複製代碼

Range

告訴服務器,客戶端要獲取哪段數據。 主要用於:斷點續傳多線程下載

語法:
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
<unit>:範圍所採用的單位,一般是字節(bytes)。
<range-start>:一個整數,表示在特定單位下,範圍的起始值。
<range-end>:一個整數,表示在特定單位下,範圍的結束值。這個值是可選的,若是不存在,表示此範圍一直延伸到文檔結束。

Range: bytes=200-1000, 2000-6576, 19000-
複製代碼

From

提供了客戶端用戶的 E-mail 地址, 用處:好比你有一個爬蟲程序,那麼 Form 首部應該隨請求一塊兒發送,這樣的話,在服務器遇到問題的時候,例如爬蟲發送了過量的、不但願收到的或者不合法的請求時,站點管理員能夠聯繫到你。

5.3 響應首部

Server

包含了處理請求的源頭服務器所用到的軟件相關信息

Server: Apache-Coyote/1.1
複製代碼

Set-Cookie

用來由服務器端向客戶端發送 cookie。

會話期 cookies 將會在客戶端關閉時被移除。 
會話期 cookie 不設置 Expires 或 Max-Age 指令
Set-Cookie: sessionid=38afes7a8; HttpOnly; Path=/

持久化 Cookie 不會在客戶端關閉時失效,而是在特定的日期(Expires)或者通過一段特定的時間以後(Max-Age)纔會失效。

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
複製代碼

Accept-Ranges

響應中出現,表示服務器支持按字節來取範圍數據

語法:
Accept-Ranges: bytes
Accept-Ranges: none
none:不支持任何範圍請求單位,因爲其等同於沒有返回此頭部,所以不多使用。
bytes:範圍請求的單位是 bytes (字節)。

Accept-Ranges: bytes
複製代碼

5.4 Body 首部

因爲請求與響應中均可以包含 body部分,因此在請求報文與響應報文中均可以出現這部分字段。

Location

指定的是須要將頁面從新定向至的地址。通常在響應碼爲 3xx 的響應中才會有意義。

Location: /index.html
複製代碼

Content-Type

告訴客戶端實際返回的內容的內容類型。 主要分爲 4 類。

  • text/html

請求 Web ⻚面時返回響應的類型,Body 中返回 html 文本。

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 853
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
複製代碼
  • x-www-form-urlencoded

Web ⻚面純⽂本表單的提交方式

POST  /users  HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 27
name=xxtlant&gender=male
複製代碼
  • multitype/form-data

Web ⻚面含有⼆制⽂件時的提交方式。

POST  /users  HTTP/1.1
Host: hencoder.com
Content-Type: multipart/form-data; boundary=----
WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Length: 2382
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="name"
rengwuxian
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="avatar"; filename="avatar.jpg"
Content-Type: image/jpeg
JFIFHHvOwX9jximQrWa......
------WebKitFormBoundary7MA4YWxkTrZu0gW--
複製代碼
  • application/json , image/jpeg , application/zip ...

單項內容(⽂本或非⽂本均可以),用於 Web Api 的響應或者 POST / PUT 的請求。

請求中提交 JSON

POST /users HTTP/1.1
Host: api.github.com
Content-Type: application/json; charset=utf-8
Content-Length: 38
{"name":"xxtlant","gender":"male"}
複製代碼

響應中返回 JSON

Date: Tue, 12 Feb 2019 08:04:14 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Server: GitHub.com
Status: 200 OK

{"login": "xxtlant",
"id": 18342980,
"node_id": "MDQ6VXNlcjE4MzQyOTgw",
"avatar_url": "https://avatars2.githubusercontent.com/u/18342980?v=4",
"gravatar_id": "",
....
複製代碼

請求中提交⼆進制內容

POST /user/1/avatar HTTP/1.1
Host: hencoder.com
Content-Type: image/jpeg
Content-Length: 1575
JFIFHH9......
複製代碼

相應中返回⼆進制內容

HTTP/1.1 200 OK
content-type: image/jpeg
content-length: 1575
JFIFHH9......
複製代碼

Content-length

用來指明發送給接收方的消息主體的大小。

Content-Length: <length>
複製代碼

Content-Encoding

用於對特定媒體類型的數據進行壓縮。 這個消息用來告知客戶端應該怎樣解碼才能獲取在 Content-Type 中的媒體類型內容。

Content-Encoding: gzip

其值受 Accept-Encoding 影響
複製代碼

與此對應,Content-Language 也與 Accept-Language 對應。

6、參考連接

相關文章
相關標籤/搜索