從 curl 命令行視角來講解 HTTP 請求

發送一個 HTTP 請求有很多途徑,例如瀏覽器、curl 命令行、wget 命令行等。本文將帶你從 curl 命令行視角來講解一個 http 請求中各個不同數據字段的含義

我們先來簡單講解一下 curl 命令。

curl 是一個用來請求 Web 服務器的命令行工具,-v 代表輸出通信的整個過程,-d代表發送 一個 POST 請求並在請求正文中帶上指定數據,使用方式如下

curl -v -d 'name=hagan' http://www.hagan.zone # 使用post方式請求url並帶上數據

請求完整過程如下

hagan@hanyonggang life % curl -v -d 'name=hagan' http://www.hagan.zone 
*   Trying 42.193.104.246...
* TCP_NODELAY set
* Connected to www.hagan.zone (42.193.104.246) port 80 (#0)
> POST / HTTP/1.1
> Host: www.hagan.zone
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 10
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 10 out of 10 bytes
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0
< Date: Fri, 30 Jul 2021 01:26:20 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< Location: https://www.hagan.zone/
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
* Connection #0 to host www.hagan.zone left intact
* Closing connection 0

本文將詳細剖析以上數據

Request

Request 代表發送請求部分,示例中 Request 部分代碼如下

hagan@hanyonggang life % curl -v -d 'name=hagan' http://www.hagan.zone 
*   Trying 42.193.104.246...
* TCP_NODELAY set
* Connected to www.hagan.zone (42.193.104.246) port 80 (#0)
> POST / HTTP/1.1 # [請求類型] [請求URL] [協議版本]
> Host: www.hagan.zone # 消息報頭
> User-Agent: curl/7.64.1 # 消息報頭
> Accept: */* # 消息報頭
> Content-Length: 10 # 消息報頭
> Content-Type: application/x-www-form-urlencoded # 消息報頭
> 
* upload completely sent off: 10 out of 10 bytes

Request 包含三個部分,分別爲 請求行 消息報頭(Header) 請求正文(Body)

下面的講解請參考示例中 Request 部分代碼來理解。

  1. 請求行

請求行包含三個部分,分別爲 請求類型 請求URL 協議版本

> POST / HTTP/1.1 # [請求類型] [請求URL] [協議版本]

1. 請求類型

本次請求的請求類型爲 POST,常見的請求類型如下

2. 請求 URL

本次請求的請求 URL 爲 /

3. 協議版本

本次請求的協議版本爲 HTTP 1.1,常見的協議版本如下

  1. 消息報頭 (Header)

消息報頭有很多種字段類型,本次請求包含如下五個消息報頭

> Host: www.hagan.zone # 消息報頭
> User-Agent: curl/7.64.1 # 消息報頭
> Accept: */* # 消息報頭
> Content-Length: 10 # 消息報頭
> Content-Type: application/x-www-form-urlencoded # 消息報頭

常見的消息報頭如下

Accept

指定客戶端接受哪些類型的信息

Accept-Charset

客戶端接受的字符集

Accept-Encoding

可接受的內容編碼

Accept-Language

指定一種自然語言

Authorization

證明客戶端有權查看某個資源

Host

指定被請求資源的 Internet 主機和端口號

User-Agent

用戶代理

Content-Type

Body 編碼方式

  1. 請求正文 (Body)

請求正文有很多種編碼方式,請求正文的類型需要根據消息報頭的Content-Type字段來確定,本次請求的編碼方式爲application/x-www-form-urlencoded

> Content-Type: application/x-www-form-urlencoded # 消息報頭

常見的 Content-Type 類型如下

application/x-www-form-urlencoded

默認數據編碼方式

?name=hagan&age=22

application/json

序列化後的 JSON 字符串

text/xml

XML 作爲編碼方式的遠程調用規範

text/plain

數據以純文本形式進行編碼

multipart/form-data

允許 body 裏面包含多個模塊,每個模塊可以是不同類型,常用於文件上傳

需要規定一個用於分割模塊的分隔符 boundary

Content-Type: multipart/form-data; boundary=hagan # boundary爲分隔符

當指定分隔符爲 hagan 時請求體格式如下

--hagan
Content-Disposition: form-data;  # name爲參數名
  
haganhan # 參數值 # 規範規定參數值前面必須有兩個換行符
--hagan
Content-Disposition: form-data; 
Content-Type: image/png # 指定類型

<Buffer 00> # 參數值
--hagan-- # 請求體結束

整個請求體拼裝完成後 , 最後會以 -- 分隔符 -- 結尾 --hagan--

--分隔符(boundary)
Content-Disposition: form-data;   

參數值1
--分隔符(boundary)
Content-Disposition: form-data;   

參數值2
--分隔符(boundary)
Content-Disposition: form-data;   

參數值3
--分隔符(boundary)
Content-Disposition: form-data;   
Content-Type: 類型  

圖片文件的二進制內容1
--分隔符(boundary)
Content-Disposition: form-data;   
Content-Type: 類型  

圖片文件的二進制內容2
--分隔符(boundary)
Content-Disposition: form-data;   
Content-Type: 類型  

圖片文件的二進制內容3
--分隔符(boundary)--

application/octet-stream

只能通過的方式提交一個二進制或文件

Response

Response 代表服務端響應部分,示例中 Response 部分代碼如下

< HTTP/1.1 301 Moved Permanently # 狀態行 # [協議版本] [狀態碼] [狀態信息]
< Server: nginx/1.18.0 # 響應報頭
< Date: Fri, 30 Jul 2021 01:26:20 GMT # 響應報頭
< Content-Type: text/html # 實體報頭
< Content-Length: 169 # 實體報頭
< Connection: keep-alive # 實體報頭
< Location: https://www.hagan.zone/ # 響應報頭
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
* Connection #0 to host www.hagan.zone left intact
* Closing connection 0

Response 也包含三個部分,分別爲 狀態行 消息報頭(Header) 響應正文(Body),下面將詳細講解這三部分。

下面的講解請參考示例中 Response 部分代碼來理解。

  1. 狀態行

狀態行包含三個部分,分別爲 協議版本 狀態碼 狀態信息

< HTTP/1.1 301 Moved Permanently # 狀態行 # [協議版本] [狀態碼] [狀態信息]

1. 協議版本

本次響應的協議版本爲 HTTP/1.1,常見協議版本如下

2. 狀態碼

本次響應的狀態碼爲 301,常見狀態碼如下

1xx

指示信息,表示請求已接收,繼續處理

2xx

成功,表示請求已被成功接收、理解、接受

3xx

重定向,要完成請求必須進行更進一步的操作

4xx

客戶端錯誤。請求有語法錯誤或請求無法實現

5xx

服務端錯誤,服務端未能實現合法的請求

3. 狀態信息

本次響應的狀態信息爲 Moved Permanently,常見狀態信息如下

  1. 消息報頭 (Header)

Response 中的消息報頭主要分爲 響應報頭實體報頭

響應報頭

本次響應中的響應報頭包含如下三個

< Server: nginx/1.18.0 # 響應報頭
< Date: Fri, 30 Jul 2021 01:26:20 GMT # 響應報頭
< Location: https://www.hagan.zone/ # 響應報頭

常見的響應報頭如下

Location

重定向接受者到一個新的位置

WWW- Authenticate

包含在 401 響應消息中,客戶端收到 401

Server

包含了服務器用來處理請求的軟件信息

Apache- Coyote/1.1

實體報頭

實體報頭也叫正文報頭,本次響應中的實體報頭包含如下三個

< Content-Type: text/html # 實體報頭
< Content-Length: 169 # 實體報頭
< Connection: keep-alive # 實體報頭

常見的實體報頭如下

Content-Encoding

編碼類型是壓縮還是非壓縮

eg: Content-Encoding: gzip

Content-Language

資源所用的自然語言,沒有設置該域則認爲實體內容將提供給所有的語言閱讀

Content-Length

正文的長度,以字節方式存儲的十進制數字表示

Content-Type

響應正文的媒體類型

Expires

響應過期的日期和時間

  1. 響應正文 (Body)

響應正文有很多種類型,響應正文的類型需要根據消息報頭的Content-Type字段來確定,本次響應的編碼方式爲text/html

< Content-Type: text/html # 實體報頭

響應正文如下

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
* Connection #0 to host www.hagan.zone left intact
* Closing connection 0

curl 命令只展示數據,不提供數據的解析,如果是瀏覽器,則會將響應正文以 text/html 的方式進行解析,此時便得到了一個 HTML 頁面

本文會在我的博客持續更新,歡迎訪問我的博客 hagan.zone ,也可點擊閱讀原文直接跳轉到文章詳情頁,裏面會包含我最新的修改。

參考資料

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/9wiLgpvFB2OpkWEHgj40hw