一、HTTP協(xié)議是什么?
-
HTTP(Hyper Text Transfer Protocol)
譯為超文本傳輸協(xié)議,是一種應(yīng)用層協(xié)議
,如下圖所示,目前有HTTP1.0、HTTP2.0、HTTP3.0
三個(gè)版本,HTTP3.0
也叫HTTP over QUIC
HTTP協(xié)議
-
2.HTTP的標(biāo)準(zhǔn)由
萬維網(wǎng)協(xié)會(huì)(W3C)、互聯(lián)網(wǎng)工程任務(wù)組(IETF)
協(xié)調(diào)制定,最終發(fā)布了一系列的RFC(RFC全稱是Request For Comments
,可以譯為:請(qǐng)求意見稿 )-
- HTTP的歷史如下所示:
? 1996年,
HTTP/1.0
發(fā)布,HTTP1.0支持POST、HEAD
等請(qǐng)求方法,支持請(qǐng)求頭、響應(yīng)頭等,支持更多種數(shù)據(jù)類型(不再局限于文本數(shù)據(jù)) ,瀏覽器的每次請(qǐng)求都需要與服務(wù)器建立一個(gè)TCP連接,請(qǐng)求處理完成后立即斷開TCP連接? 1997年,
HTTP/1.1
發(fā)布(最經(jīng)典、使用最廣泛的版本) ,支持PUT、DELETE
等請(qǐng)求方法,采用持久連接(Connection: keep-alive)
,多個(gè)請(qǐng)求可以共用同一個(gè)TCP連接
? 2015年5月,
HTTP/2.0標(biāo)準(zhǔn)
以RFC 7540
正式發(fā)表,HTTP/2.0
增加了二進(jìn)制傳輸、多路復(fù)用、頭部壓縮、服務(wù)器推送、優(yōu)先級(jí)
等特性? 2022年6月6日,IETF QUIC和HTTP工作組成員Robin Mark在推特上宣布,歷時(shí)5年,
HTTP/3
終于被標(biāo)準(zhǔn)化為 RFC 9114,這是HTTP超文本傳輸協(xié)議的第三個(gè)主要版本
二、HTTP協(xié)議的報(bào)文格式
- 其中,
start-line
代表是請(qǐng)求行或者響應(yīng)行,header-filed
代表請(qǐng)求頭或者響應(yīng)頭,*
代表0個(gè)或多個(gè),CRLF
代表換行,messgae-body
代表請(qǐng)求體或者響應(yīng)體,想了解start-line、header-field
的具體格式,可以去RFC7230查看
image.png
- 其中,
- 舉一個(gè)例子,來說明一下HTTP的報(bào)文格式,如下所示,第一行是一個(gè)
start-line
,后面是多個(gè)header-field
,接下來是CRLF
,這里沒有message-body
HTTP報(bào)文格式
- 舉一個(gè)例子,來說明一下HTTP的報(bào)文格式,如下所示,第一行是一個(gè)
三、HTTP的請(qǐng)求方法和字段
-
-
start-line
中需要明確HTTP的請(qǐng)求方法,在RFC 7231, section 4: Request methods中描述了8種請(qǐng)求方法,分別是GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE
,這些請(qǐng)求方法的含義如下所示:
? GET:常用于讀取的操作,請(qǐng)求參數(shù)直接拼接在URL的后面(瀏覽器對(duì)URL是有長(zhǎng)度限制的)
? POST:常用于添加、修改、刪除的操作,請(qǐng)求參數(shù)可以放到請(qǐng)求體中(沒有大小限制)
? HEAD:請(qǐng)求得到與GET請(qǐng)求相同的響應(yīng),但沒有響應(yīng)體
?使用場(chǎng)景舉例:在下載一個(gè)大文件前,先獲取其大小,再?zèng)Q定是否要下載。以此可以節(jié)約帶寬資源? DELETE:用于刪除指定的資源
? TRACE:請(qǐng)求服務(wù)器回顯其收到的請(qǐng)求信息,主要用于HTTP請(qǐng)求的測(cè)試或診斷
? CONNECT:可以開啟一個(gè)客戶端與所請(qǐng)求資源之間的雙向溝通的通道,它可以用來創(chuàng)建隧道(tunnel) ,可以用來訪問采用了 SSL (HTTPS) 協(xié)議的站點(diǎn)
-
-
header-filed
頭部字段有四種類型,主要就是描述請(qǐng)求/響應(yīng)的信息,具體每個(gè)字段的含義,可以去這里查詢HTTP/Headers,我們這里說需要注意的幾個(gè)字段,如下所示:
請(qǐng)求頭字段.png
響應(yīng)頭字段.png
-
-
- HTTP 的
Cookie
和Session
(1). 當(dāng)客戶端第一次請(qǐng)求服務(wù)器的時(shí)候,服務(wù)器生成一份
session
保存在服務(wù)端,該session的id就是cookie,服務(wù)器會(huì)返回Set-Cookie
的響應(yīng)體給客戶端,讓客戶端存儲(chǔ)cookie,這樣以后客戶端只需要在請(qǐng)求頭中設(shè)置Cookie
字段,服務(wù)器就可以辨認(rèn)出客戶端的身份啦(2).cookie存儲(chǔ)在客戶端,session存儲(chǔ)在服務(wù)器端,使用cookie可以幫助服務(wù)器辨別客戶端,以便它們之間更好地通信
- HTTP 的
-
- HTTP 的
Content-Type
字段,可以讓我們知道請(qǐng)求的內(nèi)容是什么,進(jìn)而用對(duì)應(yīng)的方式解析,常見的Content-Type
有以下幾種:
(1).
application/x-www-form-urlencoded
,HTTP會(huì)將請(qǐng)求參數(shù)用key1=val1&key2=val2的方式進(jìn)行組織,并放到請(qǐng)求實(shí)體里面,注意如果是中文或特殊字符如"/"、","、“:" 等會(huì)自動(dòng)進(jìn)行URL轉(zhuǎn)碼。不支持文件,一般用于表單提交,例如html中的form標(biāo)簽,默認(rèn)就采用application/x-www-form-urlencoded
-
(2).
multipart/form-data
,與application/x-www-form-urlencoded
不同,這是一個(gè)多部分多媒體類型,一般用于上傳多個(gè)文件,首先生成了一個(gè)boundary
用于分割不同的字段,在請(qǐng)求實(shí)體里每個(gè)參數(shù)以------boundary
開始,然后是附加信息和參數(shù)名,然后是空行,最后是參數(shù)內(nèi)容;多個(gè)參數(shù)將會(huì)有多個(gè)boundary塊,如果參數(shù)是文件會(huì)有特別的文件域
最后以
------boundary--
為結(jié)束標(biāo)識(shí)需要注意的是:上傳文件的content-type必須使用
multipart/form-data
,如下所示:
- HTTP 的
NSString *boundary = @"PIUSDUFIASDFUPAUskfa";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[networkRequest setValue:contentType forHTTPHeaderField: @"Content-Type"];
- (3).
application/json
,JSON 是一種輕量級(jí)的數(shù)據(jù)格式,以“鍵-值”對(duì)
的方式組織的數(shù)據(jù),需要注意的是,想用這種類型需要保證參數(shù)本身就是json格式的數(shù)據(jù)(因?yàn)閰?shù)會(huì)被直接放到請(qǐng)求體里,不會(huì)進(jìn)行任何處理)
四、HTTP的緩存機(jī)制
1.HTTP有一大堆字段來控制緩存,例如
Pragma、Expires、Cache-Control、Last-Modified、ETag、If-None-Match、If-Modified-Since
,那么這些字段是如何工作的呢?我們先來了解下這些字段的含義,再來說整個(gè)控制流程-
首先是關(guān)于緩存控制的字段,優(yōu)先級(jí):
Pragma > Cache-Control > Expires
?Pragma:作用類似于Cache-Control,HTTP/1.0的產(chǎn)物
?Expires:緩存的過期時(shí)間(GMT格式時(shí)間),HTTP/1.0的產(chǎn)物
?Cache-Control:設(shè)置緩存策略,有五個(gè)值可供選擇,如下所示:
-
?no-storage:不緩存數(shù)據(jù)到本地
?public:允許用戶、代理服務(wù)器緩存數(shù)據(jù)到本地
?private:只允許用戶緩存數(shù)據(jù)到本地
?max-age:緩存的有效時(shí)間(多長(zhǎng)時(shí)間不過期),單位秒
?no-cache:每次需要發(fā)請(qǐng)求給服務(wù)器詢問緩存是否有變化,再來決定如何使用緩存
-
- 然后是標(biāo)識(shí)資源的字段,優(yōu)先級(jí):
ETag > Last-Modified
? Last-Modified:資源的最后一次修改時(shí)間
? ETag:資源的唯一標(biāo)識(shí)(根據(jù)文件內(nèi)容計(jì)算出來的摘要值)
- 然后是標(biāo)識(shí)資源的字段,優(yōu)先級(jí):
4.
If-None-Match 和 If-Modified-Since
字段
? If-None-Match
,如果上一次的響應(yīng)頭中有ETag
,就會(huì)將ETag
的值作為請(qǐng)求頭的值 ;如果服務(wù)器發(fā)現(xiàn)資源的最新摘要值跟If-None-Match
不匹配,就會(huì)返回新的資源(200 OK) ;否則,就不會(huì)返回資源的具體數(shù)據(jù)(304 Not Modified)
? If-Modified-Since
,如果上一次的響應(yīng)頭中沒有ETag,有Last-Modified
,就會(huì)將Last-Modified的值作為請(qǐng)求頭的值 ;如果服務(wù)器發(fā)現(xiàn)資源的最后一次修改時(shí)間晚于If-Modified-Since
,就會(huì)返回新的資源(200 OK) ;否則,就不會(huì)返回資源的具體數(shù)據(jù)(304 Not Modified)
- HTTP控制緩存的整個(gè)流程,如下圖所示: