重識HTTP基礎
不忘初心 砥礪前行, Tomorrow Is Another Day !
本文概要:
- Http簡介
- 報文結構
- Http的請求方法及狀態碼
- 常用的Header
前言:
宣告:掌握好HTTP非常重要,具體理由本文最後再揭曉!
一. Http簡介
HyperText Transfer Protocol 超文字傳輸協議
- URL 格式 : 協議型別 + 主機名 + 路徑
示例
- http : 協議型別
- api.github.com : 主機名
- /users?key1=value1&key2=value2 : 路徑
二. 報文結構
- 請求報文結構

HTTP請求報文結構
示例
GET /users HTTP/1.1 Host: api.github.com Content-Type: text/html Content-Length: 110 bodybodybody假裝我是一個Body bodybodybodybodybodybody 複製程式碼
-
響應報文結構
響應報文和請求報文大同小異,只是將請求行換成了狀態行.

響應報文狀態行結構
示例
HTTP/1.1 200 OK content-type: application/json; charset=utf-8 cache-control: public, max-age=60, s-maxage=60 content-encoding: gzip bodybodybody假裝我是一個Body bodybodybodybodybodybody 複製程式碼
三. 請求方式及狀態碼
3.1 狀態碼
status code | 類別 | 原因短語 | 示例 |
---|---|---|---|
1XX | Informational(臨時資訊) | 接收的請求正在處理 | 100(繼續傳送) |
2XX | Success | 請求正常處理完畢 | 200(OK) |
3XX | Redirection(重定向) | 需要進行附加操作以完成請求 | 301(永久移動)、304(內容未改變) |
4XX | Client Error | 伺服器無法處理請求 | 400(客戶端請求錯誤)、404(內容找不到) |
5XX | Server Error | 伺服器處理請求出錯 | 500(伺服器內部錯誤) |
更多資訊,可以檢視HTTP狀態碼詳解
3.2 請求方式
Method | description |
---|---|
GET | 1. 獲取資源 2. 不傳送Body |
POST | 1. 增加或者修改資源 2. 傳送Body |
PUT | 1.修改資源 2. 傳送Body |
DELETE | 1.刪除資源 2. 不傳送Body |
HEAD | 與GET基本一致 , 區別在於返回響應無Body |
四. 常見的Header
HTTP的元資料,傳遞一些附加資訊.
格式: 鍵: 值,注意 冒號後面有一個空格 !
由於Header過多,這裡只列舉了個人覺得比較重要且常用的Header
4.1 通用的Header
欄位名 | 內容說明 |
---|---|
Content-Type | 內容型別(下一節詳細講解) |
Content-Length | 內容長度,單位位元組 |
Content-Encoding | 壓縮編碼格式,如gzip |
Last-Modified | 資源的最後修改日期時間 |
Cache-Control | 控制快取的行為,取值為一般為no-cache或max-age=XX |
4.2 請求Header
欄位名 | 內容說明 |
---|---|
Host | 請求的主機和埠號 |
User-Agent | 使用者代理,僅用於找到目標主機後確認主機域名和埠 |
Accept | 接受的媒體型別,可以多個值,用,(半形逗號)分開.如text/html, |
Accept-Charset | 接受的字符集,如UTF-8 |
Accept-Encoding | 接受的壓縮編碼型別,如gzip |
--- | ------------------------------------------ |
Last-Modified | 值,用於確認某個資源是否被更改過,沒有更改過(304)就從快取中讀取 |
If-Modified-Since | 比較資源的更新時間;值為上一次伺服器返回的 |
If-Match | 比較實體標記(ETag) |
If-None-Match | 比較實體標記(與 If-Match 相反);值為上一次伺服器返回的 ETag 值,一般會和If-Modified-Since一起出現 |
--- | ------------------------------------------ |
Cookie | 已有的Cookie |
Authorization | 用於設定身份認證資訊 |
4.3 響應Header
欄位名 | 內容說明 |
---|---|
Location | 令客戶端重定向至指定URI |
Transfer-Encoding | 分塊傳輸,如Transfer-Encoding: chunked |
Accept-Range | 如Accept-Range: bytes,表示伺服器支援按位元組獲取資料 |
Content-Range | 如Content-Range:-/total,表示傳送的是哪段資料 |
----------- | ------------------------------ |
ETag | 資源的匹配標識,和Last-Modified、If-None-Match、If-Modified-Since配合,用於快取控制 |
Set-Cookie | 設定Cookie |
最後著重學習下Content-Type,這是實際開發中最經常使用的.
-
Content-Type
指定Body的型別
- text/html 一般用於響應時,返回html頁面.
示例
HTTP/1.1 200 OK content-type: text/html; charset=utf-8 Content-Length: 666 <!DOCTYPE html> <html> <head> ...... </head> <body> ...... <body> </html> 複製程式碼
-
application/x-www-form-urlencoded
普通表單,提交純文字.
示例
POST /users HTTP/1.1 Host: api.github.com Content-Type: application/x-www-form-urlencoded Content-Length: 33 userName=jasonhww&password=123456 複製程式碼
對應Retrofit程式碼
@FormUrlEncoded @POST("/users") Observable<User> login(@Field("userName") String userName, @Field("password") String password); 複製程式碼
- multipart/form-data; boundary={boundary} 帶檔案的表單
將body分成多個部分,每部分都被boundary分成單獨的段;
- 每段以 -- 加 boundary開頭,
- 然後是該段的conten-disposition,
- 空行,
- 傳入的value,
- 最後請求結束的標識為boundary後面加--
示例
POST /users/photo HTTP/1.1 Host: api.github.com Content-Length: 3698 請求頭Content-Type: multipart/form-data;boundary={boundary的值} 空行 請求體part1 --{boundary的值} conten-disposition: form-data; name="userName" \r\n jasonhww 請求體part2 --{boundary的值} conten-disposition: form-data; pwd="password" \r\n 123456 請求體part3 --{boundary的值} conten-disposition: form-data; name="photo"; filename="檔名.txt"; Content-Type: image/jpeg \r\n sdsdsdfqfvfvsvadvavdavakvkakvadvanvnav afdfafaiewfre482ekdsji21dnefrgoonwncvewnfefeowkkr假設我是一個檔案ddsrrogkrn2n3934 請求體結束---boundary的值-- 複製程式碼
其中Content-Disposition中的 filename 是區分是否當成檔案;因為檔案有不同的型別,所以還要使用 Content-Type 指示檔案的型別;如果不知道是什麼型別取值可以為 application/octet-stream 表示該檔案是個二進位制檔案.
對應Retrofit程式碼
@Multipart @POST("/users/photo") Observable<User> uploadPhoto(@Part("userName") RequestBody userName, @Part("password") RequestBody password, @Part("photo") RequestBody photo); RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"), nameStr); RequestBody pwdPart = RequestBody.create(MediaType.parse("text/plain"), nameStr); RequestBody avatarPart = RequestBody.create(MediaType.parse("image/jpeg"), avatarFile); api.addUser(namePart, avatarPart); 複製程式碼
-
application/json , image/jpeg
單內容,實際開發使用較少.
示例-提交json
POST /users HTTP/1.1 Host: api.github.com Content-Type: application/json Content-Length: 41 {"userName":"jasonhww","password":123456} 複製程式碼
這樣請求body中直接為json字串了
對應Retrofit程式碼
@POST("/users") Observable<User> addUser(@Body("user") User user); 複製程式碼
示例-提交檔案
POST /users/photo HTTP/1.1 Host: api.github.com Content-Type: image/jpeg Content-Length: 6666 dsfdsfncwowncnowncodwcw...假設是個檔案資料 複製程式碼
這樣請求body中直接為檔案資料了
對應Retrofit程式碼
@POST("/users/photo") Observable<User> updatePhoto(@Body RequestBody avatar); 複製程式碼
最後順便提下restFul,其實 RestFul風格就是指規範的使用HTTP,但是國內大多數公司一般都不遵從.比如請求方式,實際就只會用到GET與POST.
理由就是除錯介面時,與後臺互懟的強力保障,再也不要擔心他們忽悠客戶端了.O(∩_∩)O
不過新時代社會主義還是和諧為主,儘量少互懟,合作共贏才是正道!
由於本人技術有限,如有錯誤的地方,麻煩大家給我提出來,本人不勝感激,大家一起學習進步.
參考連結: