本文主要內容:
- HTTP請求報文格式
- HTTP響應報文格式
- Header
- 請求體的3種形式
- 推薦除錯工具
- HTTP的組成圖示
1. HTTP請求報文格式
HTTP 的請求報文分為三個部分 請求行、請求頭和請求體,格式如圖:
注:部分文章也將HTTP請求報文分為兩部分請求頭和請求體,請求頭的第一行為請求行。
1.1 請求行
請求行(Request Line)分為三個部分:請求方法、請求地址和協議及版本,以CRLF(\r\n
)結束。
HTTP/1.1 定義的請求方法有8種:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE,最常的兩種GET和POST,如果是RESTful介面的話一般會用到GET、POST、DELETE、PUT。
在瞭解請求地址之前,先了解一下URL的構成:
PATH是URL主機以後的部分,即包含了Query String,如:
URL | PATH |
---|---|
http://http://www.jianshu.com/ | / |
http://localhost:8080/index.php?id=1234 | /index.php?id=1234 |
http://weibo.com/920507888/home | /920507888/home |
請求報文示例:
2. HTTP響應報文格式
HTTP響應的格式上除狀態行(第一行)與請求的請求行不一樣以外,其它就格式而言是一樣的,但排除狀態行和請求行的區別,從Header上還是能區分出HTTP請求和HTTP響應的,怎麼區分就要看前面的常見Header啦。
狀態碼(就是上圖中的響應碼) 的詳細可以檢視 HTTP狀態碼詳解
為了更直觀的展示HTTP響應,下面的例子,自nc 1270.0.1:80 << EOF
到EOF
之間,是一個簡單的HTTP請求.
3. Header
Header可用於傳遞一些附加資訊,格式: 鍵: 值
,注意冒號後面有一個空格!如:
Content-Length: 1024
Content-Type: text/plain
3.1 請求和響應常見通用Header
名稱 | 作用 |
---|---|
Content-Type | 請求體/響應體的型別,如:text/plain、application/json |
Accept | 說明接收的型別,可以多個值,用, (半形逗號)分開 |
Content-Length | 請求體/響應體的長度,單位位元組 |
Content-Encoding | 請求體/響應體的編碼格式,如gzip,deflate |
Accept-Encoding | 告知對方我方接受的Content-Encoding |
ETag | 給當前資源的標識,和Last-Modified 、If-None-Match 、If-Modified-Since 配合,用於快取控制 |
Cache-Control | 取值為一般為no-cache 或max-age=XX ,XX為個整數,表示該資源快取有效期(秒) |
3.2 常見請求Header
名稱 | 作用 |
---|---|
Authorization | 用於設定身份認證資訊 |
User-Agent | 使用者標識,如:OS和瀏覽器的型別和版本 |
If-Modified-Since | 值為上一次伺服器返回的 Last-Modified 值,用於確認某個資源是否被更改過,沒有更改過(304)就從快取中讀取 |
If-None-Match | 值為上一次伺服器返回的 ETag 值,一般會和If-Modified-Since 一起出現 |
Cookie | 已有的Cookie |
Referer | 表示請求引用自哪個地址,比如你從頁面A跳轉到頁面B時,值為頁面A的地址 |
Host | 請求的主機和埠號 |
3.3 常見響應Header
名稱 | 作用 |
---|---|
Date | 伺服器的日期 |
Last-Modified | 該資源最後被修改時間 |
Transfer-Encoding | 取值為一般為chunked,出現在Content-Length不能確定的情況下,表示伺服器不知道響應版體的資料大小,一般同時還會出現Content-Encoding 響應頭 |
Set-Cookie | 設定Cookie |
Location | 重定向到另一個URL,如輸入瀏覽器就輸入baidu.com回車,會自動跳到 https://www.baidu.com ,就是通過這個響應頭控制的 |
Server | 後臺伺服器 |
4. 請求體的3種形式
根據應用場景的不同,HTTP請求的請求體有三種不同的形式。
第一種:
移動開發者常見的,請求體是任意型別,伺服器不會解析請求體,請求體的處理需要自己解析,如 POST JSON時候就是這類。
第二種:
第二種和第三種都有固定格式的,是伺服器端開發人員最先了解到的兩種。這裡的格式要求就是URL中Query String的格式要求:多個鍵值對之間用&
連線,鍵與值之前用=
連線,且只能用ASCII字元,非ASCII字元需使用UrlEncode
編碼。
第三種:
第三種請求體的請求體被分成為多個部分,檔案上傳時會被使用,這種格式最先應該是被用於郵件傳輸中,每個欄位/檔案都被boundary(Content-Type
中指定)分成單獨的段,每段以--
加 boundary開頭,然後是該段的描述頭,描述頭之後空一行接內容,請求結束的標製為boundary後面加--
,結構見下圖:
區分是否被當成檔案的關鍵是Content-Disposition
是否包含filename
,因為檔案有不同的型別,所以還要使用Content-Type
指示檔案的型別,如果不知道是什麼型別取值可以為application/octet-stream
表示該檔案是個二進位制檔案,如果不是檔案則Content-Type
可以省略。
下圖為一個帶有檔案的上傳的請求體原文:
注意:
第二、三種請求體需求配合特定的Content-Type請求頭,如:
第二種配合Content-Type:application/x-www-form-urlencoded
第三種配合Content-Type: multipart/form-data; boundary={boundary}
,
*上面的form-data
也可以是mixed
、alternative
、digest
、parallel
,但我只用到了form-data
如果兩者沒有相配合,那麼伺服器不會解析請求體,也就是說只會當成第一種情況!
表單或者模擬表單 指的就是第二種和第三種(multipart/form-data)
5. 推薦除錯工具
5.1 cURL
cURL 相當強大命令列工具,基本上你知道的上層協議它都支援,具體使用方法就自行發現了,下圖為發起一個HTTP GET請求並列印請求和響應的詳細內容。
5.2 bat
bat 是astaxie(謝孟軍) 用Golang開發的類似cURL的命令列API除錯工具,可以方便的列印出HTTP請求和響應,還能高亮Header、格式化JSON等功能,非常好用,API調式神器。
5.3 nc
nc 是 netcat 的簡寫,被稱為“網路工具中的瑞士軍刀”,不過我個人是把它當成Socket用,經常使用它來列印各種請求,當然它的作用可不只是這樣,你也可以用它發起各式各樣的請求,以前調式POP3也是用的它,只不過請求報文得自己寫,上面有個圖“HTTP請求和響應”就是用nc完成的。
6. HTTP的組成圖示
感覺寫得有點亂,如果按下圖的結構寫會不會更好呢?