HTTP請求報文與響應(yīng)報文格式
請求報文包含四部分:
a、請求行:包含請求方法、URI、HTTP版本信息 b、請求首部字段 c、請求內(nèi)容實體 d、空行
響應(yīng)報文包含四部分:
a、狀態(tài)行:包含HTTP版本、狀態(tài)碼、狀態(tài)碼的原因短語 b、響應(yīng)首部字段 c、響應(yīng)內(nèi)容實體 d、空行
一. 請求報文

二. 響應(yīng)報文

三. HTTP1.1下4種首部字段
1. 請求首部字段
| 字段名 | 描述 |
|---|---|
| Accept | 用戶代理可處理的媒體類型 |
| Accept-Charset | 優(yōu)先的字符集 |
| Accept-Encoding | 優(yōu)先的內(nèi)容編碼 |
| Accept-Language | 優(yōu)先的語言 |
| Authorization | Web認證信息 |
| Proxy-Authorization | 代理服務(wù)器要求的認證信息 |
| Expect | 期待服務(wù)器的特定行為 |
| From | 用戶的電子郵箱地址 |
| Host | 請求資源所在服務(wù)器 |
| Referer | 對請求中 URI 的原始獲取方 |
| If-Match | 比較實體標記(ETag) |
| If-None-Match | 與 If-Match 相反 |
| If-Modified-Since | 比較資源的更新時間 |
| If-Unmodified-Since | 與If-Modified-Since相反 |
| If-Range | 資源未更新時發(fā)送實體 Byte 的范圍請求 |
| Range | 實體的字節(jié)范圍請求 |
| Max-Forwards | 最大傳輸逐跳數(shù) |
| TE | 傳輸編碼的優(yōu)先級 |
| User-Agent | HTTP 客戶端程序的信息 |
2. 響應(yīng)首部字段
| 字段名 | 描述 |
|---|---|
| Accept-Ranges | 是否接受字節(jié)范圍請求 |
| Age | 推算資源創(chuàng)建經(jīng)過時間 |
| ETag | 資源標志 |
| Location | 令客戶端重定向至指定URI |
| Proxy-Authenticate | 代理服務(wù)器對客戶端的認證信息 |
| Retry-After | 對再次發(fā)起請求的時機要求 |
| Server | HTTP服務(wù)器的安裝信息 |
| Vary | 代理服務(wù)器緩存的管理信息 |
| WWW-Authenticate | 服務(wù)器對客戶端的認證信息 |
3. 通用首部字段
| 字段名 | 描述 |
|---|---|
| Cache-Control | 控制緩存 |
| Connection | 逐跳首部、連接的管理 |
| Date | 創(chuàng)建報文的日期時間 |
| Pragma | 報文指令 |
| Trailer | 報文末端的首部一覽 |
| Transfer-Encoding | 指定報文主體的傳輸編碼方式 |
| Upgrade | 升級為其他協(xié)議 |
| Via | 代理服務(wù)器的相關(guān)信息 |
| Warning | 錯誤通知 |
4. 實體首部字段
| 字段名 | 描述 |
|---|---|
| Allow | 支持的HTTP方法 |
| Content-Encoding | 實體主體適用的編碼方式 |
| Content-Language | 實體主體的自然語言 |
| Content-Length | 實體主體的大?。▎挝唬鹤止?jié)) |
| Content-Location | 替代對應(yīng)資源的URI |
| Content-MD5 | 實體主體的報文摘要 |
| Content-Range | 實體主體的位置范圍 |
| Content-Type | 實體主體的媒體類型 |
| Expires | 資源有效時間 |
| Last-Modified | 資源的最后修改日期時間 |
5. 其他字段(非HTTP1.1定義)
| 字段名 | 描述 |
|---|---|
| Cookie | 請求首部 |
| Set-Cookie | 響應(yīng)首部 |
| Access-Control-Allow-Origin | 響應(yīng)首部 |
| Access-Control-Allow-Headers | 響應(yīng)首部 |
| Access-Control-Allow-Methods | 響應(yīng)首部 |
一、HTTP協(xié)議的主要特點
- 簡單快速:每個資源URI都是固定的
- 靈活:頭部有數(shù)據(jù)類型,可以完成不同類型傳輸
- 無連接:傳輸完成即斷開
- 無狀態(tài):建立連接 完成傳輸 下一次客戶端傳輸 是不知道兩次連接者的身份的
- 應(yīng)用層協(xié)議
其他協(xié)議:SOAP是一種簡單基于XML的輕量協(xié)議
二、HTTP報文的組成部分
- 請求報文
- 請求行(首行):HTTP方法、頁面地址(/表示首頁)、HTTP協(xié)議/版本
- 請求頭:HTTP協(xié)議告訴服務(wù)端要哪些內(nèi)容(key/value值)
- 空行:告訴服務(wù)端,請求頭部分結(jié)束
- 請求體
- 響應(yīng)報文
- 狀態(tài)行:HTTP協(xié)議、狀態(tài)碼
- 響應(yīng)頭
- 空行
- 響應(yīng)體
2.1 瀏覽器輸入一個url后關(guān)于HTTP請求發(fā)生了什么

2.3 數(shù)據(jù)協(xié)商 - HTTP請求頭
| Header | 解釋 | 示例 |
|---|---|---|
| Accept | 指定客戶端能夠接收的內(nèi)容類型 | Accept: text/plain, text/html |
| Accept-Charset | 瀏覽器可以接受的字符編碼集。 | Accept-Charset: iso-8859-5 |
| Accept-Encoding | 指定瀏覽器可以支持的web服務(wù)器返回數(shù)據(jù)壓縮編碼類型。 | Accept-Encoding: compress, gzip |
| Accept-Language | 瀏覽器可接受的語言 | Accept-Language: en,zh |
| Accept-Ranges | 可以請求網(wǎng)頁實體的一個或者多個子范圍字段 | Accept-Ranges: bytes |
| Authorization | HTTP授權(quán)的授權(quán)證書 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
| Cache-Control | 指定請求和響應(yīng)遵循的緩存機制 | Cache-Control: no-cache |
| Connection | 表示是否需要持久連接。(HTTP 1.1默認進行持久連接) | Connection: keep-alive |
| Cookie | HTTP請求發(fā)送時,會把保存在該請求域名下的所有cookie值一起發(fā)送給web服務(wù)器。 | Cookie: $Version=1; Skin=new; |
| Content-Length | 請求的內(nèi)容長度 | Content-Length: 348 |
| Content-Type | 請求的與實體對應(yīng)的MIME信息 | Content-Type: application/x-www-form-urlencoded |
| Date | 請求發(fā)送的日期和時間 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
| Expect | 請求的特定的服務(wù)器行為 | Expect: 100-continue |
| From | 發(fā)出請求的用戶的Email | From: user@email.com |
| Host | 指定請求的服務(wù)器的域名和端口號 | Host: www.baidu.com |
| If-Match | 只有請求內(nèi)容與實體相匹配才有效 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
| If-Modified-Since | 如果請求的部分在指定時間之后被修改則請求成功,未被修改則返回304代碼 | If-Modified-Since: Wed, 31 Oct 2018 05:10:43 GMT |
| If-None-Match | 如果內(nèi)容未改變返回304代碼,參數(shù)為服務(wù)器先前發(fā)送的Etag,與服務(wù)器回應(yīng)的Etag比較判斷是否改變 | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
| If-Range | 如果實體未改變,服務(wù)器發(fā)送客戶端丟失的部分,否則發(fā)送整個實體。參數(shù)也為Etag | If-Range: “737060cd8c284d8af7ad3082f209582d” |
| If-Unmodified-Since | 只在實體在指定時間之后未被修改才請求成功 | If-Unmodified-Since: Wed, 31 Oct 2018 05:10:43 GMT |
| Max-Forwards | 限制信息通過代理和網(wǎng)關(guān)傳送的時間 | Max-Forwards: 10 |
| Pragma | 用來包含實現(xiàn)特定的指令 | Pragma: no-cache |
| Proxy-Authorization | 連接到代理的授權(quán)證書 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
| Range | 只請求實體的一部分,指定范圍 | Range: bytes=500-999 |
| Referer | 先前網(wǎng)頁的地址,當前請求網(wǎng)頁緊隨其后,即來路 | Referer: https://www.baidu.com/ |
| TE | 客戶端愿意接受的傳輸編碼,并通知服務(wù)器接受接受尾加頭信息 | TE: trailers,deflate;q=0.5 |
| Upgrade | 向服務(wù)器指定某種傳輸協(xié)議以便服務(wù)器進行轉(zhuǎn)換(如果支持) | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
| User-Agent | User-Agent的內(nèi)容包含發(fā)出請求的用戶信息(判斷返回PC端的頁面還是移動端的頁面) | User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36 |
| Via | 通知中間網(wǎng)關(guān)或代理服務(wù)器地址,通信協(xié)議 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
| Warning | 關(guān)于消息實體的警告信息 | Warn: 199 Miscellaneous warning |
2.4 數(shù)據(jù)協(xié)商 - HTTP響應(yīng)頭
| Header | 解釋 | 示例 |
|---|---|---|
| Accept-Ranges | 表明服務(wù)器是否支持指定范圍請求及哪種類型的分段請求 | Accept-Ranges: bytes |
| Age | 從原始服務(wù)器到代理緩存形成的估算時間(以秒計,非負) | Age: 12 |
| Allow | 對某網(wǎng)絡(luò)資源的有效的請求行為,不允許則返回405 | Allow: GET, HEAD |
| Cache-Control | 告訴所有的緩存機制是否可以緩存及哪種類型 | Cache-Control: private |
| Content-Encoding | web服務(wù)器支持的返回內(nèi)容壓縮編碼類型。 | Content-Encoding: gzip |
| Content-Language | 響應(yīng)體的語言 | Content-Language: en,zh |
| Content-Length | 響應(yīng)體的長度 | Content-Length: 348 |
| Content-MD5 | 返回資源的MD5校驗值 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
| Content-Range | 在整個返回體中本部分的字節(jié)位置 | Content-Range: bytes 21010-47021/47022 |
| Content-Type | 返回內(nèi)容的MIME類型 | Content-Type: application/x-www-form-urlencoded; charset=utf-8 |
| Date | 原始服務(wù)器消息發(fā)出的時間 | Date: Wed, 31 Oct 2018 05:10:43 GMT |
| etag | 請求變量的實體標簽的當前值 | etag: W/"847a3c5130b6c83cd331dee376e0d0a3" |
| Expires | 響應(yīng)過期的日期和時間 | Expires: Wed, 31 Oct 2018 05:10:43 GMT |
| Last-Modified | 請求資源的最后修改時間 | Last-Modified: Wed, 31 Oct 2018 05:10:43 GMT |
| Location | 用來重定向接收方到非請求URL的位置來完成請求或標識新的資源(301/302) | Location: https://www.hao123.com/ |
| Pragma | 包括實現(xiàn)特定的指令,它可應(yīng)用到響應(yīng)鏈上的任何接收方 | Pragma: no-cache |
| Proxy-Authenticate | 它指出認證方案和可應(yīng)用到代理的該URL上的參數(shù) | Proxy-Authenticate: Basic |
| refresh | 應(yīng)用于重定向或一個新的資源被創(chuàng)造,在5秒之后重定向(由網(wǎng)景提出,被大部分瀏覽器支持) | Refresh: 5; url=https://www.hao123.com/ |
| Retry-After | 如果實體暫時不可取,通知客戶端在指定時間之后再次嘗試 | Retry-After: 120 |
| Server | web服務(wù)器軟件名稱 | Server: BWS/1.0 |
| Set-Cookie | 設(shè)置Http Cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
| Trailer | 指出頭域在分塊傳輸編碼的尾部存在 | Trailer: Max-Forwards |
| Transfer-Encoding | 文件傳輸編碼 | Transfer-Encoding:chunked |
| Vary | 告訴下游代理是使用緩存響應(yīng)還是從原始服務(wù)器請求 | Vary: * |
| Via | 告知代理客戶端響應(yīng)是通過哪里發(fā)送的 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
| Warning | 警告實體可能存在的問題 | Warning: 199 Miscellaneous warning |
| WWW-Authenticate | 表明客戶端請求實體應(yīng)該使用的授權(quán)方案 | WWW-Authenticate: Basic |
三、HTTP協(xié)議的發(fā)展歷史
HTTP/0.9:
- 只有一個命令GET
- 沒有 header 等描述數(shù)據(jù)的信息
- 服務(wù)器發(fā)送完畢,就關(guān)閉TCP連接
HTTP/1.0:
- 增加了很多命令
- 增加了status code 和 header
- 多字符集支持、多部分發(fā)送、權(quán)限和緩存等
HTTP/1.1:
- 持久連接
- pipeline
- 增加 host (可以在一個集群上同時跑多個web服務(wù),通過host字段來判斷使用node還是Java服務(wù),提高物理服務(wù)的使用效率)和其他一些命令
HTTP/2.0:
- 分幀傳輸:所有數(shù)據(jù)以二進制(幀)傳輸,之前都是用字符串
- 多路復用(信道復用):同一個連接中發(fā)送多個請求,不再需要按照順序來
- 頭信息壓縮(之前都是完整發(fā)送和返回,占用帶寬的量比較大)以及推送(支持server push,即服務(wù)端可以主動發(fā)送數(shù)據(jù)傳輸)等提高效率的功能
場景:web頁面有html、css等文件,有根據(jù)請求的url才能解析出html等文件的路徑。這里就會包含執(zhí)行順序的問題,使用HTTP/2.0之前的協(xié)議首先要先請求、解析之后才能獲取html、css、js,而且瀏覽器的并發(fā)請求數(shù)目是一定的,即對同一域名下的請求有一定數(shù)量限制(一般為6-10個),超過限制數(shù)目的請求會被阻塞。而HTTP/2.0 中只創(chuàng)建一個HTTP連接,數(shù)據(jù)傳輸和請求的發(fā)送是并行的,會改善效率、減少握手開銷。
四、TCP 三次握手和四次揮手
4.1 三次握手
類比:
客戶:在嗎?我想跟你聊天。(發(fā)送SYN請求同步報文)
服務(wù):好的,我聽著呢。(發(fā)送SYN請求同步報文,確認同步)你說吧。(發(fā)送ACK確認報文,即可以開始吐槽了)
客戶:好的。(發(fā)送ACK確認報文)今天...(開始吐槽)
圖例:

-
第一次握手(SYN=1, seq=J):
客戶端發(fā)送一個 TCP 的 SYN 標志位置1的包,指明客戶端打算連接的服務(wù)器的端口,以及初始序號 J,保存在包頭的序列號(Sequence Number)字段里。
發(fā)送完畢后,客戶端進入
SYN_SEND狀態(tài)。 -
第二次握手(SYN=1, ACK=1, seq=K, ACKnum=J+1):
服務(wù)器發(fā)回確認包(ACK)應(yīng)答。即 SYN 標志位和 ACK 標志位均為1。服務(wù)器端選擇自己 ISN 序列號,放到 Seq 域里,同時將確認序號(Acknowledgement Number)設(shè)置為客戶的 ISN 加1,即J+1。 發(fā)送完畢后,服務(wù)器端進入
SYN_RCVD狀態(tài)。 -
第三次握手(ACK=1,ACKnum=K+1)
客戶端再次發(fā)送確認包(ACK),SYN 標志位為0,ACK 標志位為1,并且把服務(wù)器發(fā)來 ACK 的序號字段+1,放在確定字段中發(fā)送給對方,并且在數(shù)據(jù)段放寫ISN的+1
發(fā)送完畢后,客戶端進入
ESTABLISHED狀態(tài),當服務(wù)器端接收到這個包時,也進入ESTABLISHED狀態(tài),TCP 握手結(jié)束。
為什么要三次握手:防止無用連接,規(guī)避網(wǎng)絡(luò)延遲等原因造成的網(wǎng)絡(luò)開銷浪費的問題。
4.2 四次揮手
類比:
客戶:我有事兒要掛電話了。(發(fā)送FIN結(jié)束報文,1次揮手)
服務(wù):好吧(發(fā)送ACK確認報文,2次揮手),對了,還有個事兒要跟你說。
......
服務(wù):說完了,掛了吧。(發(fā)送FIN結(jié)束報文,3次揮手)
客戶:好的,拜拜。(發(fā)送ACK確認報文,4次揮手)
服務(wù)掛斷電話.....
2MSL后......
客戶:我知道了。
啪?。ㄟ@才斷開連接)
圖例:

- 第一次揮手(FIN=1,seq=M)
? 假設(shè)客戶端想要關(guān)閉連接,客戶端發(fā)送一個 FIN 標志位置為1的包,表示自己已經(jīng)沒有數(shù)據(jù)可以發(fā)送了,但是仍然可以接受數(shù)據(jù)。發(fā)送完畢后,客戶端進入 FIN_WAIT_1 狀態(tài)。
- 第二次揮手(ACK=1,ACKnum=M+1)
? 服務(wù)器端確認客戶端的 FIN 包,發(fā)送一個確認包,表明自己接受到了客戶端關(guān)閉連接的請求,但還沒有準備好關(guān)閉連接。發(fā)送完畢后,服務(wù)器端進入 CLOSE_WAIT 狀態(tài),客戶端接收到這個確認包之后,進入 FIN_WAIT_2 狀態(tài),等待服務(wù)器端關(guān)閉連接。
- 第三次揮手(FIN=1,seq=K)
? 服務(wù)器端準備好關(guān)閉連接時,向客戶端發(fā)送結(jié)束連接請求,F(xiàn)IN 置為1。發(fā)送完畢后,服務(wù)器端進入 LAST_ACK 狀態(tài),等待來自客戶端的最后一個ACK。
- 第四次揮手(ACK=1,ACKnum=K+1)
? 客戶端接收到來自服務(wù)器端的關(guān)閉請求,發(fā)送一個確認包,并進入 TIME_WAIT狀態(tài),等待可能出現(xiàn)的要求重傳的 ACK 包。服務(wù)器端接收到這個確認包之后,關(guān)閉連接,進入 CLOSED 狀態(tài)??蛻舳说却四硞€固定時間(兩個最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,沒有收到服務(wù)器端的 ACK ,認為服務(wù)器端已經(jīng)正常關(guān)閉連接,于是自己也關(guān)閉連接,進入 CLOSED 狀態(tài)。
五、TCP、UDP對比
| TCP | UDP | |
|---|---|---|
| 可靠性 | 可靠 | 不可靠 |
| 連接性 | 面向連接 | 無連接 |
| 報文 | 面向字節(jié)流 | 面向報文 |
| 效率 | 傳輸效率低 | 傳輸效率高 |
| 雙工性 | 全雙工 | 一對一、一對多、多對一、多對多 |
| 流量控制 | 有(滑動窗口) | 無 |
| 擁塞控制 | 有(慢開始、擁塞避免、快重傳、快恢復) | 無 |
六、HTTP方法
HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
| HTTP方法名 | 作用 |
|---|---|
| GET | 獲取資源 |
| POST | 傳輸資源 |
| PUT | 更新/修改資源 |
| DELETE | 刪除資源 |
| HEAD | 獲得報文首部 |
| CONNECT | HTTP/1.1協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器 |
| OPTIONS | 返回服務(wù)器針對特定資源所支持的HTTP請求方法,允許客戶端發(fā)送'*'查看服務(wù)器的性能 |
| TRACE | 回顯服務(wù)器收到的請求,主要用于測試或診斷 |
推薦:同一個url通過不同的方法來實現(xiàn),設(shè)計符合RESTful風格的接口。
七、POST和GET區(qū)別
| 場景 | GET | POST |
|---|---|---|
| 瀏覽器回退 | 無害的 | 會重復提交請求 |
| 產(chǎn)生的URL地址 | 可以被收藏 | 不可以 |
| 瀏覽器緩存 | 主動緩存 | 不會自動緩存,除非手動設(shè)置 |
| 編碼方式 | 只能進行URL編碼 | 支持多種編碼方式 |
| 瀏覽器歷史記錄中的請求參數(shù) | 完整保留 | 不會保留 |
| URL中傳遞的參數(shù)長度 | 2KB左右,不同瀏覽器限制不同。故參數(shù)不要太長,容易被瀏覽器截斷。 | 沒有限制 |
| 參數(shù)的數(shù)據(jù)類型 | ASCII字符 | 沒有限制 |
| 安全性 | 參數(shù)直接暴露在URL上,還可能造成CSRF攻擊(以?分割URL和傳輸數(shù)據(jù),多個參數(shù)用&連接) | 可以傳遞敏感信息 |
| 參數(shù)傳遞 | URL傳遞 | Request body中 |
八、HTTP CODE
一個好的HTTP服務(wù)可以通過CODE判斷結(jié)果
1XX:指示信息 - 表示請求已接收,繼續(xù)處理
2XX:成功 - 表示請求已被成功接收
- 200 OK:客戶端請求成功
- 201 Created:請求成功并且服務(wù)器創(chuàng)建了新的資源
- 202 Accepted:服務(wù)器已接受請求,但尚未處理
- 206 Partial Content:客戶端發(fā)送了一個帶有Range頭的GET請求,服務(wù)器完成了它
場景:video播放視頻地址/audio播放音頻地址,如果文件過大,則一般會返回206
3XX:重定向 - 要完成請求必須進行更進一步的操作
- 301 Moved Permanently:所請求的頁面已經(jīng)永久轉(zhuǎn)移至新的URL(永久重定向)
- 302 Found:所請求的頁面已經(jīng)臨時轉(zhuǎn)移至新的URL(臨時重定向)
- 303 See Other:臨時性重定向,且總是使用 GET 請求新的 URI
- 304 Not Modified:客戶端有緩沖的文檔并發(fā)出一個條件性的請求,服務(wù)器告訴客戶原來緩存的文檔還可以繼續(xù)使用
- 307 Temporary Redirect:臨時性重定向,除GET、HEAD方法外,其他的請求方法必須等客戶確認才能跳轉(zhuǎn)
4XX:客戶端錯誤 - 請求有語法錯誤或請求無法實現(xiàn)
- 400 Bad Request:客戶端有語法錯誤,不能被服務(wù)器所理解
- 401 Unauthorized:請求未經(jīng)授權(quán),這個狀態(tài)碼必須和WWW-Authenticate報頭域一起使用
- 403 Forbidden:對被請求頁面的訪問被禁止
- 404 Not Found:請求資源不存在
5XX:服務(wù)器錯誤 - 服務(wù)器未能實現(xiàn)合法的請求
- 500 Internal Server Error:服務(wù)器發(fā)生不可預(yù)期的錯誤原來緩沖的文檔還可以繼續(xù)使用。一般來說,這個問題都會在服務(wù)器端的源代碼出現(xiàn)錯誤時出現(xiàn)
- 502 Bad Gateway:從上游服務(wù)器接收到無效的響應(yīng)
- 503 Server Unavailable:請求未完成,服務(wù)器臨時過載或宕機(可能是過載或正在維護),一段時間后可能恢復正常??碦etry-After頭,可以預(yù)計延遲時間,如果沒給出Retry-After頭,那么客戶端應(yīng)當以處理500響應(yīng)的方式處理它
- 504 Gateway Timeout:網(wǎng)頁請求超時
場景:訪問大流量或者內(nèi)容數(shù)據(jù)量較多的網(wǎng)站。根據(jù)我們掌握的服務(wù)器性能狀況及網(wǎng)絡(luò)流量情況,合理的對nginx.conf中的字句進行合理正確的設(shè)置。
九、持久連接 - TCP connection
HTTP1.0:采用“請求-應(yīng)答”模式,每個請求/應(yīng)答客戶和服務(wù)器都要新建一個連接,完成后立即斷開連接。
HTTP1.1:
- 當使用普通模式,即非Keep-Alive模式時,同HTTP1.0.
- 當使用
Keep-Alive模式(又稱持久連接、連接重用)時,Keep-Alive功能使客戶端到服務(wù)器端的連接持續(xù)有效,當出現(xiàn)對服務(wù)器的后繼請求時,Keep-Alive功能避免了建立或重新建立連接(減少三次握手的開銷)。
HTTP2.0:支持信道復用,即HTTP請求支持并發(fā)。同一個用戶對同一個服務(wù)器發(fā)起網(wǎng)頁請求的時候(同域),只需要一個HTTP連接。
十、管線化
在使用持久連接的情況下,某個連接上消息的傳遞類似于:
請求1 -> 響應(yīng)1-> 請求2 -> 響應(yīng)2 - > 請求3 -> 響應(yīng)3
管線化之后,某個連接上的消息變成了類似這樣:
請求1 -> 請求2 -> 請求3 -> 響應(yīng)1 -> 響應(yīng)2 -> 響應(yīng)3
管線化的特點
- 管線化機制通過持久連接完成,僅HTTP/1.1支持此技術(shù)
- 只有GET和HEAD請求可以進行管線化,而POST則有所限制
- 初次創(chuàng)建連接時不建議啟動管線機制,因為服務(wù)器不一定支持HTTP/1.1版本的協(xié)議
- 管線化不會影響響應(yīng)到來的順序,響應(yīng)返回的順序并未改變
- HTTP/1.1要求服務(wù)端必須支持管線化,但并不是要求服務(wù)器也對響應(yīng)進行管線化處理,只是要求對于管線化的請求不失敗即可
- 由于上面提到的服務(wù)器端問題,開啟管線化很可能并不會帶來大幅度的性能提升,而且很多服務(wù)器端和代理程序?qū)芫€化的支持并不好,因此現(xiàn)代瀏覽器如Chrome和Firefox默認并未開啟管線化支持。
十一、創(chuàng)建一個web服務(wù)(基于node.js)
const http = require('http')
http.createServer(function (request, response) {
console.log('request come', request.url)
response.end('OK')
}).listen(8888)
console.log('server is listening... ')
十二、跨域通信
瀏覽器有同源策略。協(xié)議、域名、端口有一個不同就算跨域。跨域請求,雖然會成功,但是由于同源安全策略限制不會返回相應(yīng)的資源。
主要限制以下幾個方面:
- Cookie、LocalStorage 和 IndexDB 無法讀取
- DOM 無法獲得
- AJAX 請求不能發(fā)送
同源策略:限制從一個源加載的文檔或腳本和來自另一個源的資源進行交互。這是用于隔離潛在的惡意文件的關(guān)鍵的安全機制。
前后端如何通信:
- AJAX
- WebSocket
- CORS
...
跨域通信幾種解決方案
- JSONP
- CORS(可以理解成支持跨域通信的AJAX)
- Hash
- window.name/window.postMessage(HTML5)
- WebSocket
- Proxy
12.1 JSONP
JSONP:由于同源策略的限制,XMLHttpRequest只允許請求當前源的資源。而<script src="...">...</script>,<img>,<link>標簽沒有同源限制,所以JSONP通過聲明動態(tài)<script>標簽,實現(xiàn)異步加載,為src指定一個跨域url。繞過同源策略的限制,拿到數(shù)據(jù)。
JSONP由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù)。
回調(diào)函數(shù):當響應(yīng)到來時應(yīng)該在頁面中調(diào)用的函數(shù),而數(shù)據(jù)就是傳入回調(diào)函數(shù)中的JSON數(shù)據(jù)(注意圓括號和大括號的書寫)。利用回調(diào)函數(shù)處理JSON數(shù)據(jù)。
優(yōu)點:
- 兼容性好
缺點:
- 只支持GET請求,不支持 POST 和其他請求
- 只支持跨域HTTP請求,不能解決不同域的兩個頁面之間如何進行JavaScript調(diào)用的問題。
簡述原理與過程:首先在客戶端注冊一個 callback, 然后把callback的名字傳給服務(wù)器。此時,服務(wù)器先生成一個function , function 名字就是傳遞上來的參數(shù)。最后將 json 數(shù)據(jù)直接以入?yún)⒌姆绞?,放置?function 中,這樣就生成了一段 JS 語法的文檔,返回給客戶端??蛻舳藶g覽器解析script標簽,并執(zhí)行返回的 JS 文檔,此時數(shù)據(jù)作為參數(shù),傳入客戶端預(yù)先定義好的callback 函數(shù)里。
12.2 CORS
CORS:通過設(shè)置Access-Control-Allow-Origin:'*'來允許跨域。
*表示所有的服務(wù)都接受允許跨域,這里最好設(shè)置成特定的域名。如:'http://100.79.238.34:8888'。
注:此屬性只能設(shè)置一個值,但是可以動態(tài)判斷服務(wù)允不允許跨域,允許就寫進去。
優(yōu)點:
- 可用Ajax發(fā)請求獲取數(shù)據(jù)
缺點:
- 兼容性沒有JSONP好(需要瀏覽器支持XHR2)
12.2.1 CORS 預(yù)請求
CORS 限制:
- 默認只支持GET、POST、HEAD請求
- 允許的Content-Type:
text/plain、multipart/form-data、application/x-www-form-urlencoded - 請求頭限制
- XMLHttpRequestUpload 均沒有注冊任何事件監(jiān)聽器
- 請求中沒有使用 ReadableStream 對象
詳細限制請看官方文檔。
使用CORS預(yù)請求(preflight),突破跨域限制
CORS預(yù)請求:就是在發(fā)生CORS請求時,瀏覽器檢測到跨域請求,會自動發(fā)出一個OPTIONS請求來檢測本次請求是否被服務(wù)器接受。
一個OPTIONS請求一般會攜帶下面兩個與CORS相關(guān)的頭:
- Access-Control-Request-Method : 本次預(yù)檢請求的請求方法。
- Access-Control-Request-Headers:本次請求所攜帶的自定義首部字段。
這些字段是導致產(chǎn)生OPTIONS請求的一個原因。
這樣,服務(wù)端收到該預(yù)檢請求后,會返回與CORS相關(guān)的響應(yīng)頭。主要會包括下面幾個,但可能還會有其他的有關(guān)CORS字段:
- Access-Control-Allow-Origin: 服務(wù)器允許的跨域請求源
- Access-Control-Allow-Methods: 服務(wù)器允許的請求方法
- Access-Control-Allow-Headers: 服務(wù)器允許的自定義的請求首部字段
- Access-Control-Allow-Max-Age:指定本次預(yù)檢請求的有效期,單位為秒
- Access-Control-Allow-Credentials:接收跨域的Cookie
12.3 跨域相關(guān)拓展:
- 通過
NODE發(fā)起請求可以避免 瀏覽器 的同源策略。 - nginx 設(shè)置反向代理
server {
listen 80;
server_name www.a.com;
access_log logs/test.access.log;
# 匹配以/apis/開頭的請求
location ^~ /apis/ {
proxy_pass http://www.b.com/; #注意域名后有一個/
}
location / {
root html/a;
index index.html index.htm;
}
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
還有Proxy、window.name、window.postMessage 等跨域方式,感興趣可以查閱相關(guān)資料。
十三、緩存優(yōu)化
13.1 協(xié)議層面
- 強緩存:強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發(fā)請求到服務(wù)器。
強緩存主要是采用響應(yīng)頭中的
Cache-Control和Expires兩個字段進行控制的。其中Expires是HTTP 1.0中定義的,它指定了一個絕對的過期時期。而Cache-Control是HTTP 1.1時出現(xiàn)的緩存控制字段。Cache-Control:max-age定義了一個最大使用期,就是從第一次生成文檔到緩存不再生效的合法生存日期。由于Expires是HTTP1.0時代的產(chǎn)物,因此設(shè)計之初就存在著一些缺陷,如果本地時間和服務(wù)器時間相差太大,就會導致緩存錯亂。這兩個字段同時使用的時候Cache-Control的優(yōu)先級給更高一點。 這兩個字段的效果是類似的,客戶端都會通過對比本地時間和服務(wù)器生存時間來檢測緩存是否可用。如果緩存沒有超出它的生存時間內(nèi),客戶端就會直接采用本地的緩存。如果生存日期已經(jīng)過了,這個緩存也就宣告失效。接著客戶端將再次與服務(wù)器進行通信來驗證這個緩存是否需要更新。
- 協(xié)商緩存:當強緩存沒有命中的時候,瀏覽器一定會發(fā)送一個請求到服務(wù)器,通過服務(wù)器端依據(jù)資源的另外一些
http header驗證這個資源是否命中協(xié)商緩存,如果協(xié)商緩存命中,服務(wù)器會將這個請求返回(304),若未命中請求,則將資源返回客戶端,并更新本地緩存數(shù)據(jù)(200)。
強緩存機制如果檢測到緩存失效,就需要進行服務(wù)器再驗證。這種緩存機制也稱作協(xié)商緩存。瀏覽器在第一次獲取請求的時候,就會在響應(yīng)頭中攜帶上資源的上次服務(wù)器修改日期(Last-Modified)或者資源的標簽(Etag)。后續(xù)的請求服務(wù)器會根據(jù)請求頭上的If-Modified-Since(對應(yīng)Last-Modified)和(If-None-Match)字段來判斷資源是否失效,一旦資源過期,則服務(wù)器會重新發(fā)送新的資源到客戶端上,從而保證資源的有效性。
另外一種協(xié)商緩存的校驗方式的通過校驗碼而不是時間,這樣就保證了在文件內(nèi)容不變的情況下不會重復占用網(wǎng)絡(luò)資源。響應(yīng)頭中Etag字段是服務(wù)器給資源打上的一個標記,利用這個標記就可以實現(xiàn)緩存的更新。后續(xù)發(fā)起的請求,會在請求頭上附帶上If-None-Match字段,其值就是這個標記的值。
需要注意的是當響應(yīng)頭中同時存在Etag和Last-Modified的時候,會先對Etag進行比對,隨后才是Last-Modified。
13.1.1 Cache-control
可緩存性
- public:任何地方
- private:只有發(fā)起請求的瀏覽器
- no-cache:任何節(jié)點都不可以
到期
- max-age=<seconds>:瀏覽器默認讀取
- s-maxage=<seconds>:代理服務(wù)器優(yōu)先讀取
- max-stale=<seconds>:如果有此設(shè)置,即便過期了也還可以使用緩存(在發(fā)起端設(shè)置生效)
重新驗證
- must-revalidate
- proxy-revalidate
其他
- no-store:希望代理服務(wù)器,去服務(wù)器端拿新的
- no-transform :希望代理服務(wù)器不要改返回的內(nèi)容
代理服務(wù)器如:Nginx
13.1.2 HTTP頭信息控制緩存
Expires(強緩存)+ 過期時間 :
Expires是HTTP1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間。
Cache-control(強緩存):
描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷。管理更有效,安全一些。如:Cache-Control: max-age=3600
服務(wù)端返回頭Last-Modified/客戶端請求頭If-Modified-Since(協(xié)商緩存):
標示這個響應(yīng)資源的最后修改時間。Last-Modified是服務(wù)器相應(yīng)給客戶端的,If-Modified-Sinces是客戶端發(fā)給服務(wù)器,服務(wù)器判斷這個緩存時間是否是最新的,是的話拿緩存。
服務(wù)端返回頭Etag/客戶端請求頭If-None-Match(協(xié)商緩存):
etag和last-modified類似,用來發(fā)送一個字符串來標識版本。
強緩存不請求服務(wù)器,客戶端判斷協(xié)商緩存要請求服務(wù)器。
注:有時需要將靜態(tài)資源強制更新,通用的方法是給靜態(tài)資源文件添加hash(md5)后綴
13.2 瀏覽器層面
13.2.1 WebStorage
WebStorage是HTML5中新增的本地存儲(存儲在客戶端)的解決方案之一。
WebStorage提供兩種類型的API:localStorage和sessionStorage。
為保證使用
localStorage.setItem等API不報錯,使用時盡量加入到try-catch中,因為某些瀏覽器是禁用這個 API 的。
localstorage(常用)
?localStorage一般用來存儲應(yīng)用數(shù)據(jù)(不重要但是不經(jīng)常設(shè)置的信息),也可以利用其存儲js和css等靜態(tài)資源。作為一種性能優(yōu)化的方案,這種方法也曾被大量應(yīng)用于移動端的網(wǎng)頁中。不過缺點也很明顯,由于localStorage是保存在本地中的,所以很容易導致 XSS 注入攻擊。如果要使用這種方案,一定要做好對應(yīng)的安全措施。
特點:
- 永久有效
- 存儲量增大到 5MB
- 瀏覽器端(客戶端)緩存,不參與和服務(wù)器的通信(不會帶到 HTTP 請求中)
- API 適用于數(shù)據(jù)存儲
localStorage.setItem(key, value)localStorage.getItem(key)
sessionStorage
存放一些需要及時失效的重要信息
特點:
- 僅在當前會話下有效,關(guān)閉頁面或瀏覽器后被清除
- 存儲量增大到 5MB
13.2.2 Cookie
讀取、添加和更新文檔所關(guān)聯(lián)的 cookie :document.cookie = ....
缺點:
- 存放數(shù)據(jù)大?。?KB左右(cookie的長度和數(shù)量有所限制。每個domain最多只能有20條cookie,每個cookie長度不能超過4KB。否則會被截掉。)
- 個數(shù)限制:不超過20個
- 每次都會攜帶在HTTP頭中,使用cookie保存過多數(shù)據(jù)會帶來性能問題
- 需要自己封裝,原生的接口不友好
- 安全性問題
注意事項:
- 通過良好的編程,控制保存在cookie中的session對象的大小。
- 通過加密和安全傳輸技術(shù),減少cookie被破解的可能性。
- 在cookie中存放不敏感的數(shù)據(jù),即使被盜取也不會有很大的損失。
- 控制cookie的生命期,使之不會永遠有效。這樣的話偷盜者很可能拿到的是一個過期的cookie。
- 有些狀態(tài)不可以保存在客戶端。例如,為了防止重復提交表單,我們需要在服務(wù)端保存一個計數(shù)器。若把計數(shù)器保存在客戶端,則起不到什么作用。
13.2.3 IndexedDB
通俗地說,IndexedDB 就是瀏覽器提供的本地數(shù)據(jù)庫,它可以被網(wǎng)頁腳本創(chuàng)建和操作。IndexedDB 允許儲存大量數(shù)據(jù),提供查找接口,還能建立索引。這些都是 LocalStorage 所不具備的。就數(shù)據(jù)庫類型而言,IndexedDB 不屬于關(guān)系型數(shù)據(jù)庫(不支持 SQL 查詢語句),更接近 NoSQL 數(shù)據(jù)庫。
IndexedDB 具有以下特點。
(1)鍵值對儲存。 IndexedDB 內(nèi)部采用對象倉庫(object store)存放數(shù)據(jù)。所有類型的數(shù)據(jù)都可以直接存入,包括 JavaScript 對象。對象倉庫中,數(shù)據(jù)以"鍵值對"的形式保存,每一個數(shù)據(jù)記錄都有對應(yīng)的主鍵,主鍵是獨一無二的,不能有重復,否則會拋出一個錯誤。
(2)異步。 IndexedDB 操作時不會鎖死瀏覽器,用戶依然可以進行其他操作,這與 LocalStorage 形成對比,后者的操作是同步的。異步設(shè)計是為了防止大量數(shù)據(jù)的讀寫,拖慢網(wǎng)頁的表現(xiàn)。
(3)支持事務(wù)。 IndexedDB 支持事務(wù)(transaction),這意味著一系列操作步驟之中,只要有一步失敗,整個事務(wù)就都取消,數(shù)據(jù)庫回滾到事務(wù)發(fā)生之前的狀態(tài),不存在只改寫一部分數(shù)據(jù)的情況。
(4)同源限制 IndexedDB 受到同源限制,每一個數(shù)據(jù)庫對應(yīng)創(chuàng)建它的域名。網(wǎng)頁只能訪問自身域名下的數(shù)據(jù)庫,而不能訪問跨域的數(shù)據(jù)庫。
(5)儲存空間大 IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少于 250MB,甚至沒有上限。
(6)支持二進制儲存。 IndexedDB 不僅可以儲存字符串,還可以儲存二進制數(shù)據(jù)(ArrayBuffer 對象和 Blob 對象)。
十四、Cookie和Session有什么聯(lián)系和區(qū)別
14.1 Cookie
- 通過Set-Cookie
- 下次請求就會自動帶上
- 鍵值對,可以設(shè)置多個
14.1.1 Cookie屬性
- max-age和expires:設(shè)置過期時間
- Secure:只在https的時候發(fā)送
- HttpOnly:無法通過document.cookie訪問(禁止重要數(shù)據(jù)通過JS訪問,提高安全性,防止CSRF攻擊)
14.2 Cookie 和 Session 的區(qū)別
- cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。
session會在一定時間內(nèi)保存在服務(wù)器上。當訪問增多,會比較占用服務(wù)器的性能
考慮到減輕服務(wù)器性能方面,應(yīng)當使用cookie。
- session比cookie更安全
cookie不是很安全,可以通過分析存放在本地的cookie并進行cookie欺騙。
- 一般用cookie來存儲session id
- 單個cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
建議:
- 將登錄信息等敏感信息存放為session
- 其他信息如果需要保留,可以放在cookie中
十五、內(nèi)容安全策略(CSP:Content Security Policy)
15.1 作用
- 限制資源獲取
- 報告資源獲取越權(quán)
15.2 限制方式
- default-src限制全局
- 指定資源類型 如:img-src
- report-uri: 檢測限制規(guī)則
- 建議在HTTP的Header中設(shè)置,也可以在meta標簽里設(shè)置
詳見:內(nèi)容安全策略( CSP ) - HTTP | MDN
十六、HTTPS(HyperText Transfer Protocol over Secure Socket Layer)
HTTPS:主要是HTTP下增加了SSL(安全套接層)或者TSL(傳輸層安全),在SSL或TSL在傳輸層對數(shù)據(jù)進行了加密處理。
HTTPS協(xié)議的主要作用:
- 建立一個信息安全通道,來保證數(shù)據(jù)傳輸?shù)陌踩?/li>
- 確認網(wǎng)站的真實性。
16.1 HTTP與HTTPS的區(qū)別
① HTTPS協(xié)議需要到CA申請證書,一般免費證書很少,需要付費。SSL依靠證書來驗證服務(wù)器的身份,并為瀏覽器和服務(wù)器之間的通信加密。
② HTTP是超文本傳輸協(xié)議,信息是明文傳輸,HTTPS則是具有安全性的SSL加密傳輸協(xié)議。
③ HTTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
④ HTTP的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸、身份認證的網(wǎng)絡(luò)協(xié)議,比HTTP協(xié)議安全。
16.2 HTTPS如何加密
私鑰
解密,放在服務(wù)器上
公鑰
放在互聯(lián)網(wǎng)上所有人都能拿到的加密字符串,加密

客戶端在使用HTTPS方式與Web服務(wù)器通信時有以下幾個步驟:
(1)客戶使用HTTPS的URL訪問Web服務(wù)器,要求與Web服務(wù)器建立SSL連接。
(2)Web服務(wù)器收到客戶端請求后,會將網(wǎng)站的證書信息(證書中包含公鑰)傳送一份給客戶端。
(3)客戶端的瀏覽器與Web服務(wù)器開始協(xié)商SSL連接的安全等級,也就是信息加密的等級。
(4)客戶端的瀏覽器根據(jù)雙方同意的安全等級,建立會話密鑰,然后利用網(wǎng)站的公鑰將會話密鑰加密,并傳送給網(wǎng)站。
(5)Web服務(wù)器利用自己的私鑰解密出會話密鑰(主密鑰),中間人無法解密。
(6)Web服務(wù)器利用會話密鑰加密與客戶端之間的通信。