HTTP協(xié)議相關(guān)知識(shí)點(diǎn)小結(jié)

一、HTTP協(xié)議的主要特點(diǎn)

  • 簡(jiǎn)單快速:每個(gè)資源URI都是固定的
  • 靈活:頭部有數(shù)據(jù)類型,可以完成不同類型傳輸
  • 無連接:傳輸完成即斷開
  • 無狀態(tài):建立連接 完成傳輸 下一次客戶端傳輸 是不知道兩次連接者的身份的
  • 應(yīng)用層協(xié)議

其他協(xié)議:SOAP是一種簡(jiǎn)單基于XML的輕量協(xié)議

二、HTTP報(bào)文的組成部分

  1. 請(qǐng)求報(bào)文
    • 請(qǐng)求行(首行):HTTP方法、頁面地址(/表示首頁)、HTTP協(xié)議/版本
    • 請(qǐng)求頭:HTTP協(xié)議告訴服務(wù)端要哪些內(nèi)容(key/value值)
    • 空行:告訴服務(wù)端,請(qǐng)求頭部分結(jié)束
    • 請(qǐng)求體
  2. 響應(yīng)報(bào)文
    • 狀態(tài)行:HTTP協(xié)議、狀態(tài)碼
    • 響應(yīng)頭
    • 空行
    • 響應(yīng)體

2.1 瀏覽器輸入一個(gè)url后關(guān)于HTTP請(qǐng)求發(fā)生了什么

瀏覽器輸入U(xiǎn)RL后HTTP請(qǐng)求返回的完整過程

2.2 使用chrome調(diào)試工具查看HTTP請(qǐng)求

1. 選擇XHR
2. 選擇指定請(qǐng)求,查看請(qǐng)求詳情
3. 查看請(qǐng)求頭
4. 查看響應(yīng)頭

2.3 數(shù)據(jù)協(xié)商 - HTTP請(qǐng)求頭

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 可以請(qǐng)求網(wǎng)頁實(shí)體的一個(gè)或者多個(gè)子范圍字段 Accept-Ranges: bytes
Authorization HTTP授權(quán)的授權(quán)證書 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定請(qǐng)求和響應(yīng)遵循的緩存機(jī)制 Cache-Control: no-cache
Connection 表示是否需要持久連接。(HTTP 1.1默認(rèn)進(jìn)行持久連接) Connection: keep-alive
Cookie HTTP請(qǐng)求發(fā)送時(shí),會(huì)把保存在該請(qǐng)求域名下的所有cookie值一起發(fā)送給web服務(wù)器。 Cookie: $Version=1; Skin=new;
Content-Length 請(qǐng)求的內(nèi)容長(zhǎng)度 Content-Length: 348
Content-Type 請(qǐng)求的與實(shí)體對(duì)應(yīng)的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 請(qǐng)求發(fā)送的日期和時(shí)間 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 請(qǐng)求的特定的服務(wù)器行為 Expect: 100-continue
From 發(fā)出請(qǐng)求的用戶的Email From: user@email.com
Host 指定請(qǐng)求的服務(wù)器的域名和端口號(hào) Host: www.baidu.com
If-Match 只有請(qǐng)求內(nèi)容與實(shí)體相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果請(qǐng)求的部分在指定時(shí)間之后被修改則請(qǐng)求成功,未被修改則返回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 如果實(shí)體未改變,服務(wù)器發(fā)送客戶端丟失的部分,否則發(fā)送整個(gè)實(shí)體。參數(shù)也為Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在實(shí)體在指定時(shí)間之后未被修改才請(qǐng)求成功 If-Unmodified-Since: Wed, 31 Oct 2018 05:10:43 GMT
Max-Forwards 限制信息通過代理和網(wǎng)關(guān)傳送的時(shí)間 Max-Forwards: 10
Pragma 用來包含實(shí)現(xiàn)特定的指令 Pragma: no-cache
Proxy-Authorization 連接到代理的授權(quán)證書 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只請(qǐng)求實(shí)體的一部分,指定范圍 Range: bytes=500-999
Referer 先前網(wǎng)頁的地址,當(dāng)前請(qǐng)求網(wǎng)頁緊隨其后,即來路 Referer: https://www.baidu.com/
TE 客戶端愿意接受的傳輸編碼,并通知服務(wù)器接受接受尾加頭信息 TE: trailers,deflate;q=0.5
Upgrade 向服務(wù)器指定某種傳輸協(xié)議以便服務(wù)器進(jìn)行轉(zhuǎn)換(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的內(nèi)容包含發(fā)出請(qǐng)求的用戶信息(判斷返回PC端的頁面還是移動(dòng)端的頁面) 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)于消息實(shí)體的警告信息 Warn: 199 Miscellaneous warning

2.4 數(shù)據(jù)協(xié)商 - HTTP響應(yīng)頭

Header 解釋 示例
Accept-Ranges 表明服務(wù)器是否支持指定范圍請(qǐng)求及哪種類型的分段請(qǐng)求 Accept-Ranges: bytes
Age 從原始服務(wù)器到代理緩存形成的估算時(shí)間(以秒計(jì),非負(fù)) Age: 12
Allow 對(duì)某網(wǎng)絡(luò)資源的有效的請(qǐng)求行為,不允許則返回405 Allow: GET, HEAD
Cache-Control 告訴所有的緩存機(jī)制是否可以緩存及哪種類型 Cache-Control: private
Content-Encoding web服務(wù)器支持的返回內(nèi)容壓縮編碼類型。 Content-Encoding: gzip
Content-Language 響應(yīng)體的語言 Content-Language: en,zh
Content-Length 響應(yīng)體的長(zhǎng)度 Content-Length: 348
Content-MD5 返回資源的MD5校驗(yàn)值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整個(gè)返回體中本部分的字節(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ā)出的時(shí)間 Date: Wed, 31 Oct 2018 05:10:43 GMT
etag 請(qǐng)求變量的實(shí)體標(biāo)簽的當(dāng)前值 etag: W/"847a3c5130b6c83cd331dee376e0d0a3"
Expires 響應(yīng)過期的日期和時(shí)間 Expires: Wed, 31 Oct 2018 05:10:43 GMT
Last-Modified 請(qǐng)求資源的最后修改時(shí)間 Last-Modified: Wed, 31 Oct 2018 05:10:43 GMT
Location 用來重定向接收方到非請(qǐng)求URL的位置來完成請(qǐng)求或標(biāo)識(shí)新的資源(301/302) Location: https://www.hao123.com/
Pragma 包括實(shí)現(xiàn)特定的指令,它可應(yīng)用到響應(yīng)鏈上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出認(rèn)證方案和可應(yīng)用到代理的該URL上的參數(shù) Proxy-Authenticate: Basic
refresh 應(yīng)用于重定向或一個(gè)新的資源被創(chuàng)造,在5秒之后重定向(由網(wǎng)景提出,被大部分瀏覽器支持) Refresh: 5; url=https://www.hao123.com/
Retry-After 如果實(shí)體暫時(shí)不可取,通知客戶端在指定時(shí)間之后再次嘗試 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ù)器請(qǐng)求 Vary: *
Via 告知代理客戶端響應(yīng)是通過哪里發(fā)送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 警告實(shí)體可能存在的問題 Warning: 199 Miscellaneous warning
WWW-Authenticate 表明客戶端請(qǐng)求實(shí)體應(yīng)該使用的授權(quán)方案 WWW-Authenticate: Basic

三、HTTP協(xié)議的發(fā)展歷史

HTTP/0.9:

  1. 只有一個(gè)命令GET
  2. 沒有 header 等描述數(shù)據(jù)的信息
  3. 服務(wù)器發(fā)送完畢,就關(guān)閉TCP連接

HTTP/1.0:

  1. 增加了很多命令
  2. 增加了status code 和 header
  3. 多字符集支持、多部分發(fā)送、權(quán)限和緩存等

HTTP/1.1:

  1. 持久連接
  2. pipeline
  3. 增加 host (可以在一個(gè)集群上同時(shí)跑多個(gè)web服務(wù),通過host字段來判斷使用node還是Java服務(wù),提高物理服務(wù)的使用效率)和其他一些命令

HTTP/2.0:

  1. 分幀傳輸:所有數(shù)據(jù)以二進(jìn)制(幀)傳輸,之前都是用字符串
  2. 多路復(fù)用(信道復(fù)用):同一個(gè)連接中發(fā)送多個(gè)請(qǐng)求,不再需要按照順序來
  3. 頭信息壓縮(之前都是完整發(fā)送和返回,占用帶寬的量比較大)以及推送(支持server push,即服務(wù)端可以主動(dòng)發(fā)送數(shù)據(jù)傳輸)等提高效率的功能

場(chǎng)景:web頁面有html、css等文件,有根據(jù)請(qǐng)求的url才能解析出html等文件的路徑。這里就會(huì)包含執(zhí)行順序的問題,使用HTTP/2.0之前的協(xié)議首先要先請(qǐng)求、解析之后才能獲取html、css、js,而且瀏覽器的并發(fā)請(qǐng)求數(shù)目是一定的,即對(duì)同一域名下的請(qǐng)求有一定數(shù)量限制(一般為6-10個(gè)),超過限制數(shù)目的請(qǐng)求會(huì)被阻塞。而HTTP/2.0 中只創(chuàng)建一個(gè)HTTP連接,數(shù)據(jù)傳輸和請(qǐng)求的發(fā)送是并行的,會(huì)改善效率、減少握手開銷。

四、TCP 三次握手和四次揮手

4.1 三次握手

類比:
客戶:在嗎?我想跟你聊天。(發(fā)送SYN請(qǐng)求同步報(bào)文)
服務(wù):好的,我聽著呢。(發(fā)送SYN請(qǐng)求同步報(bào)文,確認(rèn)同步)你說吧。(發(fā)送ACK確認(rèn)報(bào)文,即可以開始吐槽了)
客戶:好的。(發(fā)送ACK確認(rèn)報(bào)文)今天...(開始吐槽)
圖例:


三次握手
  • 第一次握手(SYN=1, seq=J):

    客戶端發(fā)送一個(gè) TCP 的 SYN 標(biāo)志位置1的包,指明客戶端打算連接的服務(wù)器的端口,以及初始序號(hào) J,保存在包頭的序列號(hào)(Sequence Number)字段里。

    發(fā)送完畢后,客戶端進(jìn)入 SYN_SEND 狀態(tài)。

  • 第二次握手(SYN=1, ACK=1, seq=K, ACKnum=J+1):

    服務(wù)器發(fā)回確認(rèn)包(ACK)應(yīng)答。即 SYN 標(biāo)志位和 ACK 標(biāo)志位均為1。服務(wù)器端選擇自己 ISN 序列號(hào),放到 Seq 域里,同時(shí)將確認(rèn)序號(hào)(Acknowledgement Number)設(shè)置為客戶的 ISN 加1,即J+1。 發(fā)送完畢后,服務(wù)器端進(jìn)入 SYN_RCVD 狀態(tài)。

  • 第三次握手(ACK=1,ACKnum=K+1)

    客戶端再次發(fā)送確認(rèn)包(ACK),SYN 標(biāo)志位為0,ACK 標(biāo)志位為1,并且把服務(wù)器發(fā)來 ACK 的序號(hào)字段+1,放在確定字段中發(fā)送給對(duì)方,并且在數(shù)據(jù)段放寫ISN的+1

    發(fā)送完畢后,客戶端進(jìn)入 ESTABLISHED 狀態(tài),當(dāng)服務(wù)器端接收到這個(gè)包時(shí),也進(jìn)入 ESTABLISHED 狀態(tài),TCP 握手結(jié)束。

為什么要三次握手:防止無用連接,規(guī)避網(wǎng)絡(luò)延遲等原因造成的網(wǎng)絡(luò)開銷浪費(fèi)的問題。

4.2 四次揮手

類比:
客戶:我有事兒要掛電話了。(發(fā)送FIN結(jié)束報(bào)文,1次揮手)
服務(wù):好吧(發(fā)送ACK確認(rèn)報(bào)文,2次揮手),對(duì)了,還有個(gè)事兒要跟你說。
......
服務(wù):說完了,掛了吧。(發(fā)送FIN結(jié)束報(bào)文,3次揮手)
客戶:好的,拜拜。(發(fā)送ACK確認(rèn)報(bào)文,4次揮手)
服務(wù)掛斷電話.....
2MSL后......
客戶:我知道了。
啪!(這才斷開連接)
圖例:


四次揮手
  • 第一次揮手(FIN=1,seq=M)

? 假設(shè)客戶端想要關(guān)閉連接,客戶端發(fā)送一個(gè) FIN 標(biāo)志位置為1的包,表示自己已經(jīng)沒有數(shù)據(jù)可以發(fā)送了,但是仍然可以接受數(shù)據(jù)。發(fā)送完畢后,客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)。

  • 第二次揮手(ACK=1,ACKnum=M+1)

? 服務(wù)器端確認(rèn)客戶端的 FIN 包,發(fā)送一個(gè)確認(rèn)包,表明自己接受到了客戶端關(guān)閉連接的請(qǐng)求,但還沒有準(zhǔn)備好關(guān)閉連接。發(fā)送完畢后,服務(wù)器端進(jìn)入 CLOSE_WAIT 狀態(tài),客戶端接收到這個(gè)確認(rèn)包之后,進(jìn)入 FIN_WAIT_2 狀態(tài),等待服務(wù)器端關(guān)閉連接。

  • 第三次揮手(FIN=1,seq=K)

? 服務(wù)器端準(zhǔn)備好關(guān)閉連接時(shí),向客戶端發(fā)送結(jié)束連接請(qǐng)求,F(xiàn)IN 置為1。發(fā)送完畢后,服務(wù)器端進(jìn)入 LAST_ACK 狀態(tài),等待來自客戶端的最后一個(gè)ACK。

  • 第四次揮手(ACK=1,ACKnum=K+1)

? 客戶端接收到來自服務(wù)器端的關(guān)閉請(qǐng)求,發(fā)送一個(gè)確認(rèn)包,并進(jìn)入 TIME_WAIT狀態(tài),等待可能出現(xiàn)的要求重傳的 ACK 包。服務(wù)器端接收到這個(gè)確認(rèn)包之后,關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)??蛻舳说却四硞€(gè)固定時(shí)間(兩個(gè)最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,沒有收到服務(wù)器端的 ACK ,認(rèn)為服務(wù)器端已經(jīng)正常關(guān)閉連接,于是自己也關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)。

五、TCP、UDP對(duì)比

TCP UDP
可靠性 可靠 不可靠
連接性 面向連接 無連接
報(bào)文 面向字節(jié)流 面向報(bào)文
效率 傳輸效率低 傳輸效率高
雙工性 全雙工 一對(duì)一、一對(duì)多、多對(duì)一、多對(duì)多
流量控制 有(滑動(dòng)窗口)
擁塞控制 有(慢開始、擁塞避免、快重傳、快恢復(fù))

六、HTTP方法

HTTP1.0定義了三種請(qǐng)求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五種請(qǐng)求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

HTTP方法名 作用
GET 獲取資源
POST 傳輸資源
PUT 更新/修改資源
DELETE 刪除資源
HEAD 獲得報(bào)文首部
CONNECT HTTP/1.1協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器
OPTIONS 返回服務(wù)器針對(duì)特定資源所支持的HTTP請(qǐng)求方法,允許客戶端發(fā)送'*'查看服務(wù)器的性能
TRACE 回顯服務(wù)器收到的請(qǐng)求,主要用于測(cè)試或診斷

推薦:同一個(gè)url通過不同的方法來實(shí)現(xiàn),設(shè)計(jì)符合RESTful風(fēng)格的接口。

七、POST和GET區(qū)別

場(chǎng)景 GET POST
瀏覽器回退 無害的 會(huì)重復(fù)提交請(qǐng)求
產(chǎn)生的URL地址 可以被收藏 不可以
瀏覽器緩存 主動(dòng)緩存 不會(huì)自動(dòng)緩存,除非手動(dòng)設(shè)置
編碼方式 只能進(jìn)行URL編碼 支持多種編碼方式
瀏覽器歷史記錄中的請(qǐng)求參數(shù) 完整保留 不會(huì)保留
URL中傳遞的參數(shù)長(zhǎng)度 2KB左右,不同瀏覽器限制不同。故參數(shù)不要太長(zhǎng),容易被瀏覽器截?cái)唷?/td> 沒有限制
參數(shù)的數(shù)據(jù)類型 ASCII字符 沒有限制
安全性 參數(shù)直接暴露在URL上,還可能造成CSRF攻擊(以?分割URL和傳輸數(shù)據(jù),多個(gè)參數(shù)用&連接) 可以傳遞敏感信息
參數(shù)傳遞 URL傳遞 Request body中

八、HTTP CODE

一個(gè)好的HTTP服務(wù)可以通過CODE判斷結(jié)果

1XX:指示信息 - 表示請(qǐng)求已接收,繼續(xù)處理

2XX:成功 - 表示請(qǐng)求已被成功接收

  • 200 OK:客戶端請(qǐng)求成功
  • 201 Created:請(qǐng)求成功并且服務(wù)器創(chuàng)建了新的資源
  • 202 Accepted:服務(wù)器已接受請(qǐng)求,但尚未處理
  • 206 Partial Content:客戶端發(fā)送了一個(gè)帶有Range頭的GET請(qǐng)求,服務(wù)器完成了它
    場(chǎng)景:video播放視頻地址/audio播放音頻地址,如果文件過大,則一般會(huì)返回206

3XX:重定向 - 要完成請(qǐng)求必須進(jìn)行更進(jìn)一步的操作

  • 301 Moved Permanently:所請(qǐng)求的頁面已經(jīng)永久轉(zhuǎn)移至新的URL(永久重定向)
  • 302 Found:所請(qǐng)求的頁面已經(jīng)臨時(shí)轉(zhuǎn)移至新的URL(臨時(shí)重定向)
  • 303 See Other:臨時(shí)性重定向,且總是使用 GET 請(qǐng)求新的 URI
  • 304 Not Modified:客戶端有緩沖的文檔并發(fā)出一個(gè)條件性的請(qǐng)求,服務(wù)器告訴客戶原來緩存的文檔還可以繼續(xù)使用
  • 307 Temporary Redirect:臨時(shí)性重定向,除GET、HEAD方法外,其他的請(qǐng)求方法必須等客戶確認(rèn)才能跳轉(zhuǎn)

4XX:客戶端錯(cuò)誤 - 請(qǐng)求有語法錯(cuò)誤或請(qǐng)求無法實(shí)現(xiàn)

  • 400 Bad Request:客戶端有語法錯(cuò)誤,不能被服務(wù)器所理解
  • 401 Unauthorized:請(qǐng)求未經(jīng)授權(quán),這個(gè)狀態(tài)碼必須和WWW-Authenticate報(bào)頭域一起使用
  • 403 Forbidden:對(duì)被請(qǐng)求頁面的訪問被禁止
  • 404 Not Found:請(qǐng)求資源不存在

5XX:服務(wù)器錯(cuò)誤 - 服務(wù)器未能實(shí)現(xiàn)合法的請(qǐng)求

  • 500 Internal Server Error:服務(wù)器發(fā)生不可預(yù)期的錯(cuò)誤原來緩沖的文檔還可以繼續(xù)使用。一般來說,這個(gè)問題都會(huì)在服務(wù)器端的源代碼出現(xiàn)錯(cuò)誤時(shí)出現(xiàn)
  • 502 Bad Gateway:從上游服務(wù)器接收到無效的響應(yīng)
  • 503 Server Unavailable:請(qǐng)求未完成,服務(wù)器臨時(shí)過載或宕機(jī)(可能是過載或正在維護(hù)),一段時(shí)間后可能恢復(fù)正常??碦etry-After頭,可以預(yù)計(jì)延遲時(shí)間,如果沒給出Retry-After頭,那么客戶端應(yīng)當(dāng)以處理500響應(yīng)的方式處理它
  • 504 Gateway Timeout:網(wǎng)頁請(qǐng)求超時(shí)
    場(chǎng)景:訪問大流量或者內(nèi)容數(shù)據(jù)量較多的網(wǎng)站。根據(jù)我們掌握的服務(wù)器性能狀況及網(wǎng)絡(luò)流量情況,合理的對(duì)nginx.conf中的字句進(jìn)行合理正確的設(shè)置。

九、持久連接 - TCP connection

HTTP1.0:采用“請(qǐng)求-應(yīng)答”模式,每個(gè)請(qǐng)求/應(yīng)答客戶和服務(wù)器都要新建一個(gè)連接,完成后立即斷開連接。
HTTP1.1:

  • 當(dāng)使用普通模式,即非Keep-Alive模式時(shí),同HTTP1.0.
  • 當(dāng)使用Keep-Alive模式(又稱持久連接、連接重用)時(shí),Keep-Alive功能使客戶端到服務(wù)器端的連接持續(xù)有效,當(dāng)出現(xiàn)對(duì)服務(wù)器的后繼請(qǐng)求時(shí),Keep-Alive功能避免了建立或重新建立連接(減少三次握手的開銷)。

HTTP2.0:支持信道復(fù)用,即HTTP請(qǐng)求支持并發(fā)。同一個(gè)用戶對(duì)同一個(gè)服務(wù)器發(fā)起網(wǎng)頁請(qǐng)求的時(shí)候(同域),只需要一個(gè)HTTP連接。

十、管線化

在使用持久連接的情況下,某個(gè)連接上消息的傳遞類似于:
請(qǐng)求1 -> 響應(yīng)1-> 請(qǐng)求2 -> 響應(yīng)2 - > 請(qǐng)求3 -> 響應(yīng)3

管線化之后,某個(gè)連接上的消息變成了類似這樣:
請(qǐng)求1 -> 請(qǐng)求2 -> 請(qǐng)求3 -> 響應(yīng)1 -> 響應(yīng)2 -> 響應(yīng)3

管線化的特點(diǎn)

  • 管線化機(jī)制通過持久連接完成,僅HTTP/1.1支持此技術(shù)
  • 只有GET和HEAD請(qǐng)求可以進(jìn)行管線化,而POST則有所限制
  • 初次創(chuàng)建連接時(shí)不建議啟動(dòng)管線機(jī)制,因?yàn)榉?wù)器不一定支持HTTP/1.1版本的協(xié)議
  • 管線化不會(huì)影響響應(yīng)到來的順序,響應(yīng)返回的順序并未改變
  • HTTP/1.1要求服務(wù)端必須支持管線化,但并不是要求服務(wù)器也對(duì)響應(yīng)進(jìn)行管線化處理,只是要求對(duì)于管線化的請(qǐng)求不失敗即可
  • 由于上面提到的服務(wù)器端問題,開啟管線化很可能并不會(huì)帶來大幅度的性能提升,而且很多服務(wù)器端和代理程序?qū)芫€化的支持并不好,因此現(xiàn)代瀏覽器如Chrome和Firefox默認(rèn)并未開啟管線化支持。

十一、創(chuàng)建一個(gè)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é)議、域名、端口有一個(gè)不同就算跨域??缬蛘?qǐng)求,雖然會(huì)成功,但是由于同源安全策略限制不會(huì)返回相應(yīng)的資源。

主要限制以下幾個(gè)方面:

  • Cookie、LocalStorage 和 IndexDB 無法讀取
  • DOM 無法獲得
  • AJAX 請(qǐng)求不能發(fā)送

同源策略:限制從一個(gè)源加載的文檔或腳本和來自另一個(gè)源的資源進(jìn)行交互。這是用于隔離潛在的惡意文件的關(guān)鍵的安全機(jī)制。

前后端如何通信:

  • AJAX
  • WebSocket
  • CORS
    ...

跨域通信幾種解決方案


  • JSONP
  • CORS(可以理解成支持跨域通信的AJAX)
  • Hash
  • window.name/window.postMessage(HTML5)
  • WebSocket
  • Proxy

12.1 JSONP

JSONP:由于同源策略的限制,XMLHttpRequest只允許請(qǐng)求當(dāng)前源的資源。而<script src="...">...</script>,<img>,<link>標(biāo)簽沒有同源限制,所以JSONP通過聲明動(dòng)態(tài)<script>標(biāo)簽,實(shí)現(xiàn)異步加載,為src指定一個(gè)跨域url。繞過同源策略的限制,拿到數(shù)據(jù)。

JSONP由兩部分組成:回調(diào)函數(shù)數(shù)據(jù)。

回調(diào)函數(shù):當(dāng)響應(yīng)到來時(shí)應(yīng)該在頁面中調(diào)用的函數(shù),而數(shù)據(jù)就是傳入回調(diào)函數(shù)中的JSON數(shù)據(jù)(注意圓括號(hào)和大括號(hào)的書寫)。利用回調(diào)函數(shù)處理JSON數(shù)據(jù)。

優(yōu)點(diǎn)

  • 兼容性好

缺點(diǎn)

  • 只支持GET請(qǐng)求,不支持 POST 和其他請(qǐng)求
  • 只支持跨域HTTP請(qǐng)求,不能解決不同域的兩個(gè)頁面之間如何進(jìn)行JavaScript調(diào)用的問題。

簡(jiǎn)述原理與過程:首先在客戶端注冊(cè)一個(gè) callback, 然后把callback的名字傳給服務(wù)器。此時(shí),服務(wù)器先生成一個(gè)function , function 名字就是傳遞上來的參數(shù)。最后將 json 數(shù)據(jù)直接以入?yún)⒌姆绞?,放置?function 中,這樣就生成了一段 JS 語法的文檔,返回給客戶端??蛻舳藶g覽器解析script標(biāo)簽,并執(zhí)行返回的 JS 文檔,此時(shí)數(shù)據(jù)作為參數(shù),傳入客戶端預(yù)先定義好的callback 函數(shù)里。

12.2 CORS

CORS:通過設(shè)置Access-Control-Allow-Origin:'*'來允許跨域。

*表示所有的服務(wù)都接受允許跨域,這里最好設(shè)置成特定的域名。如:'http://100.79.238.34:8888'。
注:此屬性只能設(shè)置一個(gè)值,但是可以動(dòng)態(tài)判斷服務(wù)允不允許跨域,允許就寫進(jìn)去。

優(yōu)點(diǎn)

  • 可用Ajax發(fā)請(qǐng)求獲取數(shù)據(jù)

缺點(diǎn)

  • 兼容性沒有JSONP好(需要瀏覽器支持XHR2)
12.2.1 CORS 預(yù)請(qǐng)求

CORS 限制

  • 默認(rèn)只支持GET、POST、HEAD請(qǐng)求
  • 允許的Content-Type:text/plain、multipart/form-data、application/x-www-form-urlencoded
  • 請(qǐng)求頭限制
  • XMLHttpRequestUpload 均沒有注冊(cè)任何事件監(jiān)聽器
  • 請(qǐng)求中沒有使用 ReadableStream 對(duì)象

詳細(xì)限制請(qǐng)看官方文檔。

使用CORS預(yù)請(qǐng)求(preflight),突破跨域限制

CORS預(yù)請(qǐng)求:就是在發(fā)生CORS請(qǐng)求時(shí),瀏覽器檢測(cè)到跨域請(qǐng)求,會(huì)自動(dòng)發(fā)出一個(gè)OPTIONS請(qǐng)求來檢測(cè)本次請(qǐng)求是否被服務(wù)器接受。

一個(gè)OPTIONS請(qǐng)求一般會(huì)攜帶下面兩個(gè)與CORS相關(guān)的頭:

  • Access-Control-Request-Method : 本次預(yù)檢請(qǐng)求的請(qǐng)求方法。
  • Access-Control-Request-Headers:本次請(qǐng)求所攜帶的自定義首部字段。

這些字段是導(dǎo)致產(chǎn)生OPTIONS請(qǐng)求的一個(gè)原因。

這樣,服務(wù)端收到該預(yù)檢請(qǐng)求后,會(huì)返回與CORS相關(guān)的響應(yīng)頭。主要會(huì)包括下面幾個(gè),但可能還會(huì)有其他的有關(guān)CORS字段:

  • Access-Control-Allow-Origin: 服務(wù)器允許的跨域請(qǐng)求源
  • Access-Control-Allow-Methods: 服務(wù)器允許的請(qǐng)求方法
  • Access-Control-Allow-Headers: 服務(wù)器允許的自定義的請(qǐng)求首部字段
  • Access-Control-Allow-Max-Age:指定本次預(yù)檢請(qǐng)求的有效期,單位為秒
  • Access-Control-Allow-Credentials:接收跨域的Cookie

12.3 跨域相關(guān)拓展:

  • 通過 NODE 發(fā)起請(qǐng)求可以避免 瀏覽器 的同源策略。
  • nginx 設(shè)置反向代理
server {
        listen       80;
        server_name  www.a.com;
        access_log  logs/test.access.log;
        # 匹配以/apis/開頭的請(qǐng)求
        location ^~ /apis/ {
            proxy_pass http://www.b.com/;  #注意域名后有一個(gè)/
        }
        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é)議層面

  • 強(qiáng)緩存:強(qiáng)緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會(huì)發(fā)請(qǐng)求到服務(wù)器。

強(qiáng)緩存主要是采用響應(yīng)頭中的Cache-ControlExpires兩個(gè)字段進(jìn)行控制的。其中Expires是HTTP 1.0中定義的,它指定了一個(gè)絕對(duì)的過期時(shí)期。而Cache-Control是HTTP 1.1時(shí)出現(xiàn)的緩存控制字段。Cache-Control:max-age定義了一個(gè)最大使用期,就是從第一次生成文檔到緩存不再生效的合法生存日期。由于Expires是HTTP1.0時(shí)代的產(chǎn)物,因此設(shè)計(jì)之初就存在著一些缺陷,如果本地時(shí)間和服務(wù)器時(shí)間相差太大,就會(huì)導(dǎo)致緩存錯(cuò)亂。這兩個(gè)字段同時(shí)使用的時(shí)候Cache-Control的優(yōu)先級(jí)給更高一點(diǎn)。 這兩個(gè)字段的效果是類似的,客戶端都會(huì)通過對(duì)比本地時(shí)間和服務(wù)器生存時(shí)間來檢測(cè)緩存是否可用。如果緩存沒有超出它的生存時(shí)間內(nèi),客戶端就會(huì)直接采用本地的緩存。如果生存日期已經(jīng)過了,這個(gè)緩存也就宣告失效。接著客戶端將再次與服務(wù)器進(jìn)行通信來驗(yàn)證這個(gè)緩存是否需要更新。

  • 協(xié)商緩存:當(dāng)強(qiáng)緩存沒有命中的時(shí)候,瀏覽器一定會(huì)發(fā)送一個(gè)請(qǐng)求到服務(wù)器,通過服務(wù)器端依據(jù)資源的另外一些http header驗(yàn)證這個(gè)資源是否命中協(xié)商緩存,如果協(xié)商緩存命中,服務(wù)器會(huì)將這個(gè)請(qǐng)求返回(304),若未命中請(qǐng)求,則將資源返回客戶端,并更新本地緩存數(shù)據(jù)(200)。

強(qiáng)緩存機(jī)制如果檢測(cè)到緩存失效,就需要進(jìn)行服務(wù)器再驗(yàn)證。這種緩存機(jī)制也稱作協(xié)商緩存。瀏覽器在第一次獲取請(qǐng)求的時(shí)候,就會(huì)在響應(yīng)頭中攜帶上資源的上次服務(wù)器修改日期(Last-Modified)或者資源的標(biāo)簽(Etag)。后續(xù)的請(qǐng)求服務(wù)器會(huì)根據(jù)請(qǐng)求頭上的If-Modified-Since(對(duì)應(yīng)Last-Modified)和(If-None-Match)字段來判斷資源是否失效,一旦資源過期,則服務(wù)器會(huì)重新發(fā)送新的資源到客戶端上,從而保證資源的有效性。
另外一種協(xié)商緩存的校驗(yàn)方式的通過校驗(yàn)碼而不是時(shí)間,這樣就保證了在文件內(nèi)容不變的情況下不會(huì)重復(fù)占用網(wǎng)絡(luò)資源。響應(yīng)頭中Etag字段是服務(wù)器給資源打上的一個(gè)標(biāo)記,利用這個(gè)標(biāo)記就可以實(shí)現(xiàn)緩存的更新。后續(xù)發(fā)起的請(qǐng)求,會(huì)在請(qǐng)求頭上附帶上If-None-Match字段,其值就是這個(gè)標(biāo)記的值。
需要注意的是當(dāng)響應(yīng)頭中同時(shí)存在Etag和Last-Modified的時(shí)候,會(huì)先對(duì)Etag進(jìn)行比對(duì),隨后才是Last-Modified。

13.1.1 Cache-control

可緩存性

  • public:任何地方
  • private:只有發(fā)起請(qǐng)求的瀏覽器
  • no-cache:任何節(jié)點(diǎn)都不可以

到期

  • max-age=<seconds>:瀏覽器默認(rèn)讀取
  • s-maxage=<seconds>:代理服務(wù)器優(yōu)先讀取
  • max-stale=<seconds>:如果有此設(shè)置,即便過期了也還可以使用緩存(在發(fā)起端設(shè)置生效)

重新驗(yàn)證

  • must-revalidate
  • proxy-revalidate

其他

  • no-store:希望代理服務(wù)器,去服務(wù)器端拿新的
  • no-transform :希望代理服務(wù)器不要改返回的內(nèi)容

代理服務(wù)器如:Nginx

13.1.2 HTTP頭信息控制緩存

Expires(強(qiáng)緩存)+ 過期時(shí)間 :
ExpiresHTTP1.0提出的一個(gè)表示資源過期時(shí)間的header,它描述的是一個(gè)絕對(duì)時(shí)間。

Cache-control(強(qiáng)緩存):
描述的是一個(gè)相對(duì)時(shí)間,在進(jìn)行緩存命中的時(shí)候,都是利用客戶端時(shí)間進(jìn)行判斷。管理更有效,安全一些。如:Cache-Control: max-age=3600

服務(wù)端返回頭Last-Modified/客戶端請(qǐng)求頭If-Modified-Since(協(xié)商緩存):
標(biāo)示這個(gè)響應(yīng)資源的最后修改時(shí)間。Last-Modified是服務(wù)器相應(yīng)給客戶端的,If-Modified-Sinces是客戶端發(fā)給服務(wù)器,服務(wù)器判斷這個(gè)緩存時(shí)間是否是最新的,是的話拿緩存。

服務(wù)端返回頭Etag/客戶端請(qǐng)求頭If-None-Match(協(xié)商緩存):
etag和last-modified類似,用來發(fā)送一個(gè)字符串來標(biāo)識(shí)版本。

強(qiáng)緩存不請(qǐng)求服務(wù)器,客戶端判斷協(xié)商緩存要請(qǐng)求服務(wù)器。

注:有時(shí)需要將靜態(tài)資源強(qiáng)制更新,通用的方法是給靜態(tài)資源文件添加hash(md5)后綴

13.2 瀏覽器層面

13.2.1 WebStorage

WebStorage是HTML5中新增的本地存儲(chǔ)(存儲(chǔ)在客戶端)的解決方案之一。
WebStorage提供兩種類型的API:localStorage和sessionStorage。

為保證使用localStorage.setItem等API不報(bào)錯(cuò),使用時(shí)盡量加入到try-catch中,因?yàn)槟承g覽器是禁用這個(gè) API 的。

localstorage(常用)

?localStorage一般用來存儲(chǔ)應(yīng)用數(shù)據(jù)(不重要但是不經(jīng)常設(shè)置的信息),也可以利用其存儲(chǔ)js和css等靜態(tài)資源。作為一種性能優(yōu)化的方案,這種方法也曾被大量應(yīng)用于移動(dòng)端的網(wǎng)頁中。不過缺點(diǎn)也很明顯,由于localStorage是保存在本地中的,所以很容易導(dǎo)致 XSS 注入攻擊。如果要使用這種方案,一定要做好對(duì)應(yīng)的安全措施。

特點(diǎn)

  1. 永久有效
  2. 存儲(chǔ)量增大到 5MB
  3. 瀏覽器端(客戶端)緩存,不參與和服務(wù)器的通信(不會(huì)帶到 HTTP 請(qǐng)求中)
  4. API 適用于數(shù)據(jù)存儲(chǔ) localStorage.setItem(key, value) localStorage.getItem(key)
sessionStorage

存放一些需要及時(shí)失效的重要信息

特點(diǎn)

  1. 僅在當(dāng)前會(huì)話下有效,關(guān)閉頁面或?yàn)g覽器后被清除
  2. 存儲(chǔ)量增大到 5MB

13.2.2 Cookie

讀取、添加和更新文檔所關(guān)聯(lián)的 cookie :document.cookie = ....

缺點(diǎn)

  • 存放數(shù)據(jù)大?。?KB左右(cookie的長(zhǎng)度和數(shù)量有所限制。每個(gè)domain最多只能有20條cookie,每個(gè)cookie長(zhǎng)度不能超過4KB。否則會(huì)被截掉。)
  • 個(gè)數(shù)限制:不超過20個(gè)
  • 每次都會(huì)攜帶在HTTP頭中,使用cookie保存過多數(shù)據(jù)會(huì)帶來性能問題
  • 需要自己封裝,原生的接口不友好
  • 安全性問題

注意事項(xiàng)

  1. 通過良好的編程,控制保存在cookie中的session對(duì)象的大小。
  2. 通過加密和安全傳輸技術(shù),減少cookie被破解的可能性。
  3. 在cookie中存放不敏感的數(shù)據(jù),即使被盜取也不會(huì)有很大的損失。
  4. 控制cookie的生命期,使之不會(huì)永遠(yuǎn)有效。這樣的話偷盜者很可能拿到的是一個(gè)過期的cookie。
  5. 有些狀態(tài)不可以保存在客戶端。例如,為了防止重復(fù)提交表單,我們需要在服務(wù)端保存一個(gè)計(jì)數(shù)器。若把計(jì)數(shù)器保存在客戶端,則起不到什么作用。

13.2.3 IndexedDB

通俗地說,IndexedDB 就是瀏覽器提供的本地?cái)?shù)據(jù)庫(kù),它可以被網(wǎng)頁腳本創(chuàng)建和操作。IndexedDB 允許儲(chǔ)存大量數(shù)據(jù),提供查找接口,還能建立索引。這些都是 LocalStorage 所不具備的。就數(shù)據(jù)庫(kù)類型而言,IndexedDB 不屬于關(guān)系型數(shù)據(jù)庫(kù)(不支持 SQL 查詢語句),更接近 NoSQL 數(shù)據(jù)庫(kù)。

IndexedDB 具有以下特點(diǎn)。

(1)鍵值對(duì)儲(chǔ)存。 IndexedDB 內(nèi)部采用對(duì)象倉(cāng)庫(kù)(object store)存放數(shù)據(jù)。所有類型的數(shù)據(jù)都可以直接存入,包括 JavaScript 對(duì)象。對(duì)象倉(cāng)庫(kù)中,數(shù)據(jù)以"鍵值對(duì)"的形式保存,每一個(gè)數(shù)據(jù)記錄都有對(duì)應(yīng)的主鍵,主鍵是獨(dú)一無二的,不能有重復(fù),否則會(huì)拋出一個(gè)錯(cuò)誤。

(2)異步。 IndexedDB 操作時(shí)不會(huì)鎖死瀏覽器,用戶依然可以進(jìn)行其他操作,這與 LocalStorage 形成對(duì)比,后者的操作是同步的。異步設(shè)計(jì)是為了防止大量數(shù)據(jù)的讀寫,拖慢網(wǎng)頁的表現(xiàn)。

(3)支持事務(wù)。 IndexedDB 支持事務(wù)(transaction),這意味著一系列操作步驟之中,只要有一步失敗,整個(gè)事務(wù)就都取消,數(shù)據(jù)庫(kù)回滾到事務(wù)發(fā)生之前的狀態(tài),不存在只改寫一部分?jǐn)?shù)據(jù)的情況。

(4)同源限制 IndexedDB 受到同源限制,每一個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)創(chuàng)建它的域名。網(wǎng)頁只能訪問自身域名下的數(shù)據(jù)庫(kù),而不能訪問跨域的數(shù)據(jù)庫(kù)。

(5)儲(chǔ)存空間大 IndexedDB 的儲(chǔ)存空間比 LocalStorage 大得多,一般來說不少于 250MB,甚至沒有上限。

(6)支持二進(jìn)制儲(chǔ)存。 IndexedDB 不僅可以儲(chǔ)存字符串,還可以儲(chǔ)存二進(jìn)制數(shù)據(jù)(ArrayBuffer 對(duì)象和 Blob 對(duì)象)。

十四、Cookie和Session有什么聯(lián)系和區(qū)別

14.1 Cookie

  • 通過Set-Cookie
  • 下次請(qǐng)求就會(huì)自動(dòng)帶上
  • 鍵值對(duì),可以設(shè)置多個(gè)
14.1.1 Cookie屬性
  • max-age和expires:設(shè)置過期時(shí)間
  • Secure:只在https的時(shí)候發(fā)送
  • HttpOnly:無法通過document.cookie訪問(禁止重要數(shù)據(jù)通過JS訪問,提高安全性,防止CSRF攻擊)

14.2 Cookie 和 Session 的區(qū)別

  • cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。

session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上。當(dāng)訪問增多,會(huì)比較占用服務(wù)器的性能
考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用cookie。

  • session比cookie更安全

cookie不是很安全,可以通過分析存放在本地的cookie并進(jìn)行cookie欺騙。

  • 一般用cookie來存儲(chǔ)session id
  • 單個(gè)cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個(gè)站點(diǎn)最多保存20個(gè)cookie。

建議

  1. 將登錄信息等敏感信息存放為session
  2. 其他信息如果需要保留,可以放在cookie中

十五、內(nèi)容安全策略(CSP:Content Security Policy)

15.1 作用

  1. 限制資源獲取
  2. 報(bào)告資源獲取越權(quán)

15.2 限制方式

  1. default-src限制全局
  2. 指定資源類型 如:img-src
  3. report-uri: 檢測(cè)限制規(guī)則
  4. 建議在HTTP的Header中設(shè)置,也可以在meta標(biāo)簽里設(shè)置
    詳見:內(nèi)容安全策略( CSP ) - HTTP | MDN

十六、HTTPS(HyperText Transfer Protocol over Secure Socket Layer)

HTTPS:主要是HTTP下增加了SSL(安全套接層)或者TSL(傳輸層安全),在SSL或TSL在傳輸層對(duì)數(shù)據(jù)進(jìn)行了加密處理。

HTTPS協(xié)議的主要作用:

  1. 建立一個(gè)信息安全通道,來保證數(shù)據(jù)傳輸?shù)陌踩?/li>
  2. 確認(rèn)網(wǎng)站的真實(shí)性。

16.1 HTTP與HTTPS的區(qū)別

① HTTPS協(xié)議需要到CA申請(qǐng)證書,一般免費(fèi)證書很少,需要付費(fèi)。SSL依靠證書來驗(yàn)證服務(wù)器的身份,并為瀏覽器和服務(wù)器之間的通信加密。
② HTTP是超文本傳輸協(xié)議,信息是明文傳輸,HTTPS則是具有安全性的SSL加密傳輸協(xié)議。
③ HTTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
④ HTTP的連接很簡(jiǎn)單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比HTTP協(xié)議安全。

16.2 HTTPS如何加密

私鑰
解密,放在服務(wù)器上
公鑰
放在互聯(lián)網(wǎng)上所有人都能拿到的加密字符串,加密

HTTPS握手

客戶端在使用HTTPS方式與Web服務(wù)器通信時(shí)有以下幾個(gè)步驟:

(1)客戶使用HTTPS的URL訪問Web服務(wù)器,要求與Web服務(wù)器建立SSL連接。

(2)Web服務(wù)器收到客戶端請(qǐng)求后,會(huì)將網(wǎng)站的證書信息(證書中包含公鑰)傳送一份給客戶端。

(3)客戶端的瀏覽器與Web服務(wù)器開始協(xié)商SSL連接的安全等級(jí),也就是信息加密的等級(jí)。

(4)客戶端的瀏覽器根據(jù)雙方同意的安全等級(jí),建立會(huì)話密鑰,然后利用網(wǎng)站的公鑰將會(huì)話密鑰加密,并傳送給網(wǎng)站。

(5)Web服務(wù)器利用自己的私鑰解密出會(huì)話密鑰(主密鑰),中間人無法解密。

(6)Web服務(wù)器利用會(huì)話密鑰加密與客戶端之間的通信。

以上。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容