「 面試三板斧 」之 HTTP (上)

前言
HTTP 也是前端面試中常見(jiàn)的考察點(diǎn), 了解這部分內(nèi)容十分有必要。
常見(jiàn)的問(wèn)題有:
為什么說(shuō) HTTPS 更安全HTTP 1/2 有什么區(qū)別304 是什么option 請(qǐng)求是什么,每次都會(huì)發(fā)嗎描述一下密鑰交換過(guò)程...
這類(lèi)問(wèn)題都是 HTTP 相關(guān)的問(wèn)題,十分常見(jiàn)。
下面我們就整體的回顧一下, 內(nèi)容較多,?分成上下兩部分。
今天的主要內(nèi)容包括:
HTTP 是什么HTTP 的前世今生HTTP 的基礎(chǔ)特性基于 HTTP 的組件系統(tǒng)HTTP 報(bào)文組成HTTP 狀態(tài)碼GET 和 Post的區(qū)別?優(yōu)化 options 請(qǐng)求 HTTPSHTTP/2 及 HTTP/3HTTPS 及其工作流程為何不所有的網(wǎng)站都使用HTTPS
全稱:超文本傳輸協(xié)議(HyperText Transfer Protocol)
概念:HTTP 是一種能夠獲取像 HTML、圖片等網(wǎng)絡(luò)資源的通訊協(xié)議。
它是在 web 上進(jìn)行數(shù)據(jù)交換的基礎(chǔ),是一種 client-server 協(xié)議。
HTTP 在因特網(wǎng)的角色:充當(dāng)一個(gè)信使的角色,干的就是一個(gè)跑腿的活,在客戶端和服務(wù)端之間傳遞信息,但我們又不能缺少它。
HTTP 協(xié)議是「 應(yīng)用層 」協(xié)議,是與前端開(kāi)發(fā)最息息相關(guān)的協(xié)議。
平時(shí)我們遇到的 HTTP 請(qǐng)求、 HTTP 緩存、Cookies、跨域等其實(shí)都跟 HTTP 息息相關(guān)。
HTTP 的前世今生
HTTP(HyperText Transfer Protocol)是萬(wàn)維網(wǎng)(World Wide Web)的基礎(chǔ)協(xié)議。
Tim Berners-Lee 博士和他的團(tuán)隊(duì)在1989-1991年間創(chuàng)造出它。
在 1991 年發(fā)布了 HTTP 0.9 版,在 1996 年發(fā)布 1.0 版,1997 年是 1.1 版,1.1 版也是到今天為止傳輸最廣泛的版本。
2015 年發(fā)布了 2.0 版,其極大的優(yōu)化了 HTTP/1.1 的性能和安全性,而 2018 年發(fā)布的 3.0 版,繼續(xù)優(yōu)化 HTTP/2,激進(jìn)地使用 UDP 取代 TCP 協(xié)議。
目前,HTTP/3 在 2019 年 9 月 26 日 被 Chrome,F(xiàn)irefox,和 Cloudflare 支持。

HTTP 0.9
單行協(xié)議,請(qǐng)求由單行指令構(gòu)成。以唯一可用的方法 GET 開(kāi)頭。后面跟的是目標(biāo)資源的路徑
GET /mypage.html 響應(yīng):只包括響應(yīng)文檔本身
這是一個(gè)非常簡(jiǎn)單的HTML頁(yè)面 沒(méi)有響應(yīng)頭,只傳輸 HTML 文件沒(méi)有狀態(tài)碼
HTTP 1.0
RFC 1945 提出了 HTTP1.0,構(gòu)建更好可拓展性
協(xié)議版本信息會(huì)隨著每個(gè)請(qǐng)求發(fā)送。
響應(yīng)狀態(tài)碼
引入了 HTTP 頭的概念,無(wú)論是請(qǐng)求還是拓展,允許傳輸元數(shù)據(jù)。使協(xié)議變得靈活,更加具有拓展性
Content-Type 請(qǐng)求頭,具備了傳輸除純文本 HTML 文件以外其他類(lèi)型文檔的能力。
在響應(yīng)中,Content-Type 標(biāo)頭告訴客戶端實(shí)際返回的內(nèi)容的內(nèi)容類(lèi)型
媒體類(lèi)型是一種標(biāo)準(zhǔn)。用來(lái)表示文檔、文件或者字節(jié)流的性質(zhì)和格式。
瀏覽器通常使用 MIME (Multipurpose Internet Mail Extensions )類(lèi)型來(lái)確定如何處理 URL,因此 Web 服務(wù)器在響應(yīng)頭中配置正確的 MIME 類(lèi)型會(huì)非常的重要。
如果配置不正確,可能會(huì)導(dǎo)致網(wǎng)站無(wú)法正常的工作。
MIME 的組成結(jié)構(gòu)非常簡(jiǎn)單: 由類(lèi)型與子類(lèi)型兩個(gè)字符串中間用’/‘分隔而組成。
HTTP 從 MIME type 取了一部分來(lái)標(biāo)記報(bào)文 body 部分的數(shù)據(jù)類(lèi)型,這些類(lèi)型體現(xiàn)在Content-Type 這個(gè)字段,當(dāng)然這是針對(duì)于發(fā)送端而言,接收端想要收到特定類(lèi)型的數(shù)據(jù),也可以用 Accept 字段。
這兩個(gè)字段的取值可以分為下面幾類(lèi):
- text:text/html, text/plain, text/css 等
-?image:?image/gif,?image/jpeg,?image/png?等
-?audio/video:?audio/mpeg,?video/mp4?等
-?application:?application/json,?application/javascript,?application/pdf,?application/octet-stream
同時(shí)為了約定請(qǐng)求的數(shù)據(jù)和響應(yīng)數(shù)據(jù)的壓縮方式、支持語(yǔ)言、字符集等,還提出了以下的 Header:
1.壓縮方式:
發(fā)送端:Content-Encoding(服務(wù)端告知客戶端,服務(wù)器對(duì)實(shí)體的主體部分的編碼方式)接收端:Accept-Encoding(用戶代理支持的編碼方式)
gzip: 當(dāng)今最流行的壓縮格式;deflate: 另外一種著名的壓縮格式, 一種專門(mén)為 HTTP 發(fā)明的壓縮算法。
2.支持語(yǔ)言
Content-Language 和 Accept-Language(用戶代理支持的自然語(yǔ)言集)
3.字符集
發(fā)送端:Content-Type 中,以 charset 屬性指定。接收端:Accept-Charset(用戶代理支持的字符集)。
//?發(fā)送端
Content-Encoding:?gzip
Content-Language:?zh-CN,?zh,?en
Content-Type:?text/html;?charset=utf-8
//?接收端
Accept-Encoding:?gzip
Accept-Language:?zh-CN,?zh,?en
Accept-Charset:?charset=utf-8
雖然 HTTP1.0 在 HTTP 0.9 的基礎(chǔ)上改進(jìn)了很多,但還是存在這不少的缺點(diǎn).
HTTP/1.0 版的主要缺點(diǎn)
每個(gè) TCP 連接只能發(fā)送一個(gè)請(qǐng)求。發(fā)送數(shù)據(jù)完畢,連接就關(guān)閉,如果還要請(qǐng)求其他資源,就必須再新建一個(gè)連接。
TCP 連接的新建成本很高,因?yàn)樾枰蛻舳撕头?wù)器三次握手,并且開(kāi)始時(shí)發(fā)送速率較慢(slow start)。
HTTP 最早期的模型,也是 HTTP/1.0 的默認(rèn)模型,是短連接。
每一個(gè) HTTP 請(qǐng)求都由它自己獨(dú)立的連接完成;
這意味著發(fā)起每一個(gè) HTTP 請(qǐng)求之前, 都會(huì)有一次 TCP 握手,而且是連續(xù)不斷的。
HTTP 1.1
HTTP/1.1 在1997年1月以 RFC 2068 文件發(fā)布。
HTTP 1.1 消除了大量歧義內(nèi)容并引入了多項(xiàng)技術(shù)
1. 連接可以復(fù)用
2. 長(zhǎng)連接:connection: keep-alive。
HTTP 1.1 支持長(zhǎng)連接(PersistentConnection),在一個(gè) TCP 連接上可以傳送多個(gè) HTTP 請(qǐng)求和響應(yīng),減少了建立和關(guān)閉連接的消耗和延遲。
在 HTTP1.1 中默認(rèn)開(kāi)啟 Connection:keep-alive,一定程度上彌補(bǔ)了 HTTP1.0 每次請(qǐng)求都要?jiǎng)?chuàng)建連接的缺點(diǎn)。
3. 增加了管道化技術(shù)
允許在第一個(gè)應(yīng)答被完全發(fā)送完成之前就發(fā)送第二個(gè)請(qǐng)求,以降低通信延遲。
復(fù)用同一個(gè) TCP 連接期間,即便是通過(guò)管道同時(shí)發(fā)送了多個(gè)請(qǐng)求,服務(wù)端也是按請(qǐng)求的順序依次給出響應(yīng)的;
而客戶端在未收到之前所發(fā)出所有請(qǐng)求的響應(yīng)之前,將會(huì)阻塞后面的請(qǐng)求(排隊(duì)等待),這稱為隊(duì)頭堵塞(Head-of-line blocking)。
4. 支持響應(yīng)分塊
分塊編碼傳輸:Transfer-Encoding: chunked
Content-length 聲明本次響應(yīng)的數(shù)據(jù)長(zhǎng)度。
keep-alive 連接可以先后傳送多個(gè)響應(yīng),因此用 Content-length 來(lái)區(qū)分?jǐn)?shù)據(jù)包是屬于哪一個(gè)響應(yīng)。
使用 Content-Length 字段的前提條件是,服務(wù)器發(fā)送響應(yīng)之前,必須知道響應(yīng)的數(shù)據(jù)長(zhǎng)度。
對(duì)于一些很耗時(shí)的動(dòng)態(tài)操作來(lái)說(shuō),這意味著,服務(wù)器要等到所有操作完成,才能發(fā)送數(shù)據(jù),顯然這樣的效率不高。
更好的處理方法是,產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊,采用”流模式”(Stream)取代”緩存模式”(Buffer)。
因此,HTTP 1.1 規(guī)定可以不使用 Content-Length 字段,而使用”分塊傳輸編碼”(Chunked Transfer Encoding)。
只要請(qǐng)求或響應(yīng)的頭信息有 Transfer-Encoding: chunked 字段,就表明 body 將可能由數(shù)量未定的多個(gè)數(shù)據(jù)塊組成。
每個(gè)數(shù)據(jù)塊之前會(huì)有一行包含一個(gè) 16 進(jìn)制數(shù)值,表示這個(gè)塊的長(zhǎng)度;
最后一個(gè)大小為 0 的塊,就表示本次響應(yīng)的數(shù)據(jù)發(fā)送完了。
5. 引入額外的緩存控制機(jī)制。
在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 等來(lái)做為緩存判斷的標(biāo)準(zhǔn).
HTTP1.1 則引入了更多的緩存控制策略例, 如 Entity tag, If-None-Match,Cache-Control 等更多可供選擇的緩存頭來(lái)控制緩存策略。
6. Host 頭
不同的域名配置同一個(gè) IP 地址的服務(wù)器。
Host 是 HTTP 1.1 協(xié)議中新增的一個(gè)請(qǐng)求頭,主要用來(lái)實(shí)現(xiàn)虛擬主機(jī)技術(shù)。
虛擬主機(jī)(virtual hosting)即共享主機(jī)(shared web hosting),可以利用虛擬技術(shù)把一臺(tái)完整的服務(wù)器分成若干個(gè)主機(jī),因此可以在單一主機(jī)上運(yùn)行多個(gè)網(wǎng)站或服務(wù)。
舉個(gè)栗子,有一臺(tái) ip 地址為 61.135.169.125 的服務(wù)器,在這臺(tái)服務(wù)器上部署著谷歌、百度、淘寶的網(wǎng)站。
為什么我們?cè)L問(wèn) https://www.google.com 時(shí),看到的是 Google 的首頁(yè), 而不是百度或者淘寶的首頁(yè)?
原因就是: Host 請(qǐng)求頭決定著訪問(wèn)哪個(gè)虛擬主機(jī)。
HTTP 的基礎(chǔ)特性
可拓展協(xié)議。
HTTP 1.0 出現(xiàn)的 HTTP headers 讓協(xié)議拓展變得更加的容易。
只要服務(wù)端和客戶端就 headers 達(dá)成語(yǔ)義一致,新功能就可以被輕松的加入進(jìn)來(lái)。
HTTP 是無(wú)狀態(tài)的、有會(huì)話的。
在同一個(gè)連接中,兩個(gè)執(zhí)行成功的 HTTP 請(qǐng)求之間是沒(méi)有關(guān)系的。
這就帶來(lái)了一個(gè)問(wèn)題,用戶沒(méi)有辦法在同一個(gè)網(wǎng)站中進(jìn)行連續(xù)的交互,比如在一個(gè)電商網(wǎng)站里,用戶把某個(gè)商品加入到購(gòu)物車(chē),切換一個(gè)頁(yè)面后再次添加了商品,這兩次添加商品的請(qǐng)求之間沒(méi)有關(guān)聯(lián),瀏覽器無(wú)法知道用戶最終選擇了哪些商品。
而使用 HTTP 的頭部擴(kuò)展,HTTP Cookies 就可以解決這個(gè)問(wèn)題。把 Cookies 添加到頭部中,創(chuàng)建一個(gè)會(huì)話讓每次請(qǐng)求都能共享相同的上下文信息,達(dá)成相同的狀態(tài)。
HTTP 與連接。通過(guò) TCP,或者 TLS——加密的 TCP 連接來(lái)發(fā)送,理論上任何可靠的傳輸協(xié)議都可以使用。連接是傳輸層控制的,這從根本上來(lái)講不是 HTTP 的范疇。

也就是說(shuō),HTTP 依賴于面向連接的 TCP 進(jìn)行消息傳遞,但連接并不是必須的。
只需要它是可靠的,或不丟失消息的(至少返回錯(cuò)誤)。
HTTP/1.0 默認(rèn)為每一對(duì) HTTP 請(qǐng)求/響應(yīng)都打開(kāi)一個(gè)單獨(dú)的 TCP 連接。
當(dāng)需要連續(xù)發(fā)起多個(gè)請(qǐng)求時(shí),這種模式比多個(gè)請(qǐng)求共享同一個(gè) TCP 鏈接更低效。
為此,HTTP 1.1 持久連接的概念,底層 TCP 連接可以通過(guò) connection 頭部實(shí)現(xiàn)。
但 HTTP 1.1 在連接上也是不完美的,后面我們會(huì)提到。
基于 HTTP 的組件系統(tǒng)
HTTP 的組件系統(tǒng)包括客戶端、web 服務(wù)器和代理

1. 客戶端:user-agent
瀏覽器,特殊比如是工程師使用的程序,以及 Web 開(kāi)發(fā)人員調(diào)試應(yīng)用程序。
2. Web服務(wù)端
由 Web Server 來(lái)服務(wù)并提供客戶端所請(qǐng)求的文檔。
每一個(gè)發(fā)送到服務(wù)器的請(qǐng)求,都會(huì)被服務(wù)器處理并返回一個(gè)消息,也就是 response。
3. 代理(Proxy)
在瀏覽器和服務(wù)器之間,有很多計(jì)算機(jī)和其他設(shè)備轉(zhuǎn)發(fā)了 HTTP 消息。
它們可能出現(xiàn)在傳輸層、網(wǎng)絡(luò)層和物理層上,對(duì)于 HTTP 應(yīng)用層而言就是透明的 有如下的一些作用:
緩存 過(guò)濾(像防病毒掃描、家長(zhǎng)控制) 負(fù)載均衡 認(rèn)證(對(duì)不同的資源進(jìn)行權(quán)限控制) 日志管理
HTTP 報(bào)文組成
HTTP 有兩種類(lèi)型的消息:
請(qǐng)求
即:由客戶端發(fā)送用來(lái)觸發(fā)一個(gè)服務(wù)器上的動(dòng)作.
響應(yīng)
即:來(lái)自服務(wù)器端的應(yīng)答。
HTTP 消息由采用 ASCII 編碼的多行文本構(gòu)成的。
在 HTTP/1.1 以及更早的版本中,這些消息通過(guò)連接公開(kāi)的發(fā)送。
在 HTTP2.0 中,消息被分到了多個(gè) HTTP 幀中。
通過(guò)配置文件(用于代理服務(wù)器或者服務(wù)器),API(用于瀏覽器)或者其他接口提供 HTTP 消息。
典型的 HTTP 會(huì)話
建立連接
在客戶端-服務(wù)器協(xié)議中,連接是由客戶端發(fā)起建立的。
在 HTTP 中打開(kāi)連接意味著在底層傳輸層啟動(dòng)連接,通常是 TCP。
使用 TCP 時(shí),HTTP 服務(wù)器的默認(rèn)端口號(hào)是 80,另外還有 8000 和 8080 也很常用.
發(fā)送客戶端請(qǐng)求
服務(wù)器響應(yīng)請(qǐng)求
HTTP 請(qǐng)求和響應(yīng)
HTTP 請(qǐng)求和響應(yīng)都包括起始行(start line)、請(qǐng)求頭(HTTP Headers)、空行(empty line)以及 body 部分,如下圖所示:

起始行。
請(qǐng)求的起始行:請(qǐng)求方法、請(qǐng)求 Path 和HTTP 版本號(hào) 響應(yīng)的起始行:HTTP 版本號(hào)、響應(yīng)狀態(tài)碼以及狀態(tài)文本描述 下面詳細(xì)說(shuō)下請(qǐng)求 Path,請(qǐng)求路徑(Path)有以下幾種:
一個(gè)絕對(duì)路徑,末尾跟上一個(gè) ‘ ? ‘ 和查詢字符串。
這是最常見(jiàn)的形式,稱為 原始形式 (origin form)。
被 GET,POST,HEAD 和 OPTIONS 方法所使用:
POST / HTTP/1.1 GET /background.png HTTP/1.0 HEAD /test.html?query=alibaba HTTP/1.1 OPTIONS /anypage.html HTTP/1.0
一個(gè)完整的 URL
主要在使用 GET 方法連接到代理的時(shí)候使用:
GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1
由域名和可選端口(以’:’為前綴)組成的 URL 的 authority component,稱為 authority form。
僅在使用 CONNECT 建立 HTTP 隧道時(shí)才使用:
CONNECT developer.mozilla.org:80 HTTP/1.1
星號(hào)形式(asterisk form)
一個(gè)簡(jiǎn)單的星號(hào)(‘*‘),配合 OPTIONS 方法使用,代表整個(gè)服務(wù)器:
OPTIONS * HTTP/1.1 Headers 請(qǐng)求頭或者響應(yīng)頭。詳見(jiàn)下面的首部。不區(qū)分大小寫(xiě)的字符串,緊跟著的冒號(hào) (‘:’) 和一個(gè)結(jié)構(gòu)取決于 header 的值
空行。很多人容易忽略
Body
請(qǐng)求 Body 部分:
有些請(qǐng)求將數(shù)據(jù)發(fā)送到服務(wù)器以便更新數(shù)據(jù):常見(jiàn)的的情況是 POST 請(qǐng)求(包含 HTML 表單數(shù)據(jù))。
請(qǐng)求報(bào)文的 Body 一般為兩類(lèi)。
一類(lèi)是通過(guò) Content-Type 和 Content-Length 定義的單文件 body。
另外一類(lèi)是由多Body 組成,通常是和 HTML Form 聯(lián)系在一起的。
兩者的不同表現(xiàn)在于 Content-Type 的值。
1)Content-Type —— application/x-www-form-urlencoded
對(duì)于 application/x-www-form-urlencoded 格式的表單內(nèi)容。
有以下特點(diǎn):
I. 其中的數(shù)據(jù)會(huì)被編碼成以&分隔的鍵值對(duì)
II. 字符以URL編碼方式編碼。
轉(zhuǎn)換過(guò)程: {a: 1, b: 2} -> a=1&b=2 -> 如下(最終形式) "a%3D1%26b%3D2"
2)Content-Type —— multipart/form-data
請(qǐng)求頭中的 Content-Type 字段會(huì)包含 boundary,且 boundary 的值有瀏覽器默認(rèn)指定。
例:
Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe。
數(shù)據(jù)會(huì)分為多個(gè)部分,每?jī)蓚€(gè)部分之間通過(guò)分隔符來(lái)分隔,每部分表述均有 HTTP 頭部描述子包體,如Content-Type,在最后的分隔符會(huì)加上—表示結(jié)束。
Content-Disposition:?form-data;name="data1";
Content-Type:?text/plain
data1
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition:?form-data;name="data2";
Content-Type:?text/plain
data2
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--
響應(yīng) Body 部分:
1)由已知長(zhǎng)度的單個(gè)文件組成。該類(lèi)型 body 由兩個(gè) header 定義:Content-Type 和 Content-Length
2)由未知長(zhǎng)度的單個(gè)文件組成,通過(guò)將 Transfer-Encoding 設(shè)置為 chunked 來(lái)使用 chunks 編碼。關(guān)于 Content-Length 在下面 HTTP 1.0 中會(huì)提到,這個(gè)是 HTTP 1.0 中新增的非常重要的頭部。
方法
安全方法:HTTP 定義了一組被稱為安全方法的方法。
GET 方法和 HEAD 方法都被認(rèn)為是安全的,這意味著 GET 方法和 HEAD 方法都不會(huì)產(chǎn)生什么動(dòng)作 —— HTTP 請(qǐng)求不會(huì)再服務(wù)端產(chǎn)生什么結(jié)果,但這并不意味著什么動(dòng)作都沒(méi)發(fā)生,其實(shí)這更多的是 web 開(kāi)發(fā)者決定的.
GET:請(qǐng)求服務(wù)器發(fā)送某個(gè)資源HEAD:跟 GET 方法類(lèi)似,但服務(wù)器在響應(yīng)中只返回了首部。不會(huì)返回實(shí)體的主體部分。PUT:向服務(wù)器中寫(xiě)入文檔。語(yǔ)義:用請(qǐng)求的主體部分來(lái)創(chuàng)建一個(gè)由所請(qǐng)求的 URL 命名的新文檔POST:用來(lái)向服務(wù)器中輸入數(shù)據(jù)的。通常我們提交表單數(shù)據(jù)給服務(wù)器?!綪OST 用于向服務(wù)器發(fā)送數(shù)據(jù),PUT 方法用于向服務(wù)器上的資源(例如文件)中存儲(chǔ)數(shù)據(jù)】TRACE:主要用于診斷。實(shí)現(xiàn)沿通向目標(biāo)資源的路徑的消息環(huán)回(loop-back)測(cè)試 ,提供了一種實(shí)用的 debug 機(jī)制。OPTIONS:請(qǐng)求 WEB 服務(wù)器告知其支持的各種功能??梢栽儐?wèn)服務(wù)器支持哪些方法?;蛘哚槍?duì)某些特殊資源支持哪些方法。DELETE:請(qǐng)求服務(wù)器刪除請(qǐng)求 URL 中指定的的資源
關(guān)于 options 請(qǐng)求
從很多資料我們可以了解到使用OPTIONS方法對(duì)服務(wù)器發(fā)起請(qǐng)求,可以檢測(cè)服務(wù)器支持哪些 HTTP 方法。
但是這次我們并沒(méi)有主動(dòng)去發(fā)起 OPTIONS 請(qǐng)求,那OPTIONS請(qǐng)求為何會(huì)自動(dòng)發(fā)起 ?
規(guī)范要求,對(duì)那些可能對(duì)服務(wù)器數(shù)據(jù)產(chǎn)生副作用的 HTTP 請(qǐng)求方法(特別是 GET 以外的 HTTP 請(qǐng)求,或者搭配某些 MIME 類(lèi)型的 POST 請(qǐng)求),瀏覽器必須首先使用 OPTIONS 方法發(fā)起一個(gè)預(yù)檢請(qǐng)求(preflight request),從而獲知服務(wù)端是否允許該跨域請(qǐng)求。
所以這個(gè)跨域請(qǐng)求觸發(fā)了瀏覽器自動(dòng)發(fā)起OPTIONS請(qǐng)求,看看此次跨域請(qǐng)求具體觸發(fā)了哪些條件。

由于修改了Content-Type為application/json,觸發(fā)了CORS預(yù)檢請(qǐng)求。
優(yōu)化OPTIONS請(qǐng)求:Access-Control-Max-Age 或者 避免觸發(fā)
可見(jiàn)一旦達(dá)到觸發(fā)條件,跨域請(qǐng)求便會(huì)一直發(fā)送2次請(qǐng)求,這樣增加的請(qǐng)求數(shù)是否可優(yōu)化呢?答案是可以,OPTIONS預(yù)檢請(qǐng)求的結(jié)果可以被緩存。
Access-Control-Max-Age這個(gè)響應(yīng)首部表示 preflight request (預(yù)檢請(qǐng)求)的返回結(jié)果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被緩存的最長(zhǎng)時(shí)間,單位是秒。(MDN)
如果值為 -1,則表示禁用緩存,每一次請(qǐng)求都需要提供預(yù)檢請(qǐng)求,即用OPTIONS請(qǐng)求進(jìn)行檢測(cè)。
在其他場(chǎng)景,比如跨域并且業(yè)務(wù)有自定義請(qǐng)求頭的話就很難避免了。
現(xiàn)在使用的axios或者superagent等第三方ajax插件,如果出現(xiàn)CORS預(yù)檢請(qǐng)求,可以看看默認(rèn)配置或者二次封裝是否規(guī)范。
GET 和 POST 的區(qū)別
首先要了解下副作用和冪等的概念,副作用指的是: 對(duì)服務(wù)器端資源做修改。
冪等, 指發(fā)送 M 和 N 次請(qǐng)求(兩者不相同且都大于 1),服務(wù)器上資源的狀態(tài)一致。
應(yīng)用場(chǎng)景上:
get 是無(wú)副作用的,冪等的。
post 主要是有副作用的,不冪等的情況。
技術(shù)上有以下的區(qū)分:
緩存:Get 請(qǐng)求能緩存,Post 請(qǐng)求不能
安全:Get 請(qǐng)求沒(méi)有 Post 請(qǐng)求那么安全,因?yàn)檎?qǐng)求都在 URL 中。且會(huì)被瀏覽器保存歷史紀(jì)錄。POST 放在請(qǐng)求體中,更加安全
限制:URL 有長(zhǎng)度限制,會(huì)干預(yù) Get 請(qǐng)求,這個(gè)是瀏覽器決定的
編碼:GET 請(qǐng)求只能進(jìn)行 URL 編碼,只能接收 ASCII 字符,而 POST 沒(méi)有限制。POST 支持更多的編碼類(lèi)型,而且不對(duì)數(shù)據(jù)類(lèi)型做限制。
從 TCP 的角度,GET 請(qǐng)求會(huì)把請(qǐng)求報(bào)文一次性發(fā)出去,而 POST 會(huì)分為兩個(gè) TCP 數(shù)據(jù)包,首先發(fā) header 部分,如果服務(wù)器響應(yīng) 100(continue), 然后發(fā) body 部分。(火狐瀏覽器除外,它的 POST 請(qǐng)求只發(fā)一個(gè) TCP 包)
HTTP 狀態(tài)碼
100~199——信息性狀態(tài)碼
101 Switching Protocols。在HTTP升級(jí)為WebSocket的時(shí)候,如果服務(wù)器同意變更,就會(huì)發(fā)送狀態(tài)碼 101。
200~299——成功狀態(tài)碼
200 OK,表示從客戶端發(fā)來(lái)的請(qǐng)求在服務(wù)器端被正確處理
204 No content,表示請(qǐng)求成功,但響應(yīng)報(bào)文不含實(shí)體的主體部分
205 Reset Content,表示請(qǐng)求成功,但響應(yīng)報(bào)文不含實(shí)體的主體部分,但是與 204 響應(yīng)不同在于要求請(qǐng)求方重置內(nèi)容
206 Partial Content,進(jìn)行范圍請(qǐng)求
300~399——重定向狀態(tài)碼
301 moved permanently,永久性重定向,表示資源已被分配了新的 URL
302 found,臨時(shí)性重定向,表示資源臨時(shí)被分配了新的 URL
303 see other,表示資源存在著另一個(gè) URL,應(yīng)使用 GET 方法獲取資源
304 not modified,表示服務(wù)器允許訪問(wèn)資源,但因發(fā)生請(qǐng)求未滿足條件的情況
307 temporary redirect,臨時(shí)重定向,和302含義類(lèi)似,但是期望客戶端保持請(qǐng)求方法不變向新的地址發(fā)出請(qǐng)求
400~499——客戶端錯(cuò)誤狀態(tài)碼
400 bad request,請(qǐng)求報(bào)文存在語(yǔ)法錯(cuò)誤
401 unauthorized,表示發(fā)送的請(qǐng)求需要有通過(guò) HTTP 認(rèn)證的認(rèn)證信息
403 forbidden,表示對(duì)請(qǐng)求資源的訪問(wèn)被服務(wù)器拒絕
404 not found,表示在服務(wù)器上沒(méi)有找到請(qǐng)求的資源
500~599——服務(wù)器錯(cuò)誤狀態(tài)碼
500 internal sever error,表示服務(wù)器端在執(zhí)行請(qǐng)求時(shí)發(fā)生了錯(cuò)誤
501 Not Implemented,表示服務(wù)器不支持當(dāng)前請(qǐng)求所需要的某個(gè)功能
503 service unavailable,表明服務(wù)器暫時(shí)處于超負(fù)載或正在停機(jī)維護(hù),無(wú)法處理請(qǐng)求
HTTP 首部
HTTP Headers
1.通用首部(General headers)同時(shí)適用于請(qǐng)求和響應(yīng)消息,但與最終消息主體中傳輸?shù)臄?shù)據(jù)無(wú)關(guān)的消息頭。如 Date。
2.請(qǐng)求首部(Request headers)包含更多有關(guān)要獲取的資源或客戶端本身信息的消息頭。
如 User-Agent
3.響應(yīng)首部(Response headers)包含有關(guān)響應(yīng)的補(bǔ)充信息
4.實(shí)體首部(Entity headers)含有關(guān)實(shí)體主體的更多信息,比如主體長(zhǎng)(Content-Length)度或其 MIME 類(lèi)型。如 Accept-Ranges。
詳細(xì)的 Header 見(jiàn) HTTP Headers 集合:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
未完待續(xù), 見(jiàn)下篇。
愛(ài)心三連擊
1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的在看是我創(chuàng)作的動(dòng)力。
2.關(guān)注公眾號(hào)腦洞前端,獲取更多前端硬核文章!加個(gè)星標(biāo),不錯(cuò)過(guò)每一條成長(zhǎng)的機(jī)會(huì)。
3.如果你覺(jué)得本文的內(nèi)容對(duì)你有幫助,就幫我轉(zhuǎn)發(fā)一下吧。
