推薦一下極客時間的《透視HTTP協議》,記錄專欄中一些比較重要的點。若有侵權,請聯繫我。javascript
講解了HTTP發展的趨勢 從HTTP 0.9到HTTP1.0(不做爲正式使用)到HTTP1.1 (如今主流)到HTTP2 (2014產生)到HTTP3(QUIC協議推進發展) HTTP2和HTTP3主要是由谷歌需求推進協議發展。css
緩存管理和控制:當瀏覽器得到資源後,服務器回傳資源有效時間,瀏覽器將參數放在Cache-Control中下次請求時判斷緩存是否過時再次請求html
HTTP 是一個在計算機世界裏專門在兩點之間傳輸文字、圖片、音頻、視頻等超文本數據的約定和規範。java
TCP是有狀態的協議,發送數據前雙方必須創建鏈接,由此能夠保證傳輸字節流 是連續的並且沒有重複。UDP是沒有狀態的協議,發送前不須要創建鏈接。UDP發送的數據包是無序的,且亂序收的。算法
CDN處於應用層 (一開始覺得處於網絡層,果真對於請求處理層數越少越好)json
DNS域名解析的過程能夠分別爲本地host文件-> 本地域名服務器->根域名服務器->權威域名服務器後端
外圍有多級緩存爲大公司爲了加速域名解析,會建立本身的DNS域名服務器,非權威域名服務器。做爲用戶DNS查詢的代理,代替用戶訪問核心DNS。如同谷歌建立的8.8.8.8免費公共域名服務器。瀏覽器
配置實驗環境 ,同時安裝了wireshak以及openresty緩存
再簡要敘述一下此次最簡單的瀏覽器 HTTP 請求過程:安全
HTTP協議主要由如下三部分構成
HTTP協議再細分能夠分爲 請求以及響應
請求行包括
這三個部分一般用空格來進行隔開,最後用CRLF來表示結束
狀態行包括
頭部字段主要分爲四大類
請求字段:
Host字段:告訴服務器這個請求應該由哪一個主機來處理
User-Agent字段:告訴服務器請求的客戶端信息
通用字段:
Data字段:客戶端可使用這個時間再搭配其餘字段決定緩存策略
響應字段:
Server字段:告訴客戶端 響應服務器信息(也有部分網站不用透露信息)
實體字段:
content-length:表示響應體中報文body的長度
總結
HTTP/1.1 規定了八種方法
GET POST DELETE PUT 不用過多介紹
HEAD
HEAD方法與 GET 方法相似,也是請求從服務器獲取資源,服務器的處理機制也是同樣的,但服務器不會返回請求的實體數據,只會傳回響應頭,也就是資源的「元信息」。
HEAD 方法能夠看作是 GET 方法的一個「簡化版」或者「輕量版」。由於它的響應頭與 GET 徹底相同,因此能夠用在不少並不真正須要資源的場合,避免傳輸 body 數據的浪費。
安全與冪等
對於安全性來講GET和HEAD是安全的,不會修改計算機的資源。剩下三種會修改或者刪除計算機的資源因此不是安全的。
對於冪等性來講GET和HEAD是冪等的。同時PUT DELETE方法也是冪等的,屢次修改一條記錄最後的結果也是一條,而POST則會修改數據的個數 不是冪等的。
總結:
URI,也就是統一資源標識符(Uniform Resource Identifier)
URL——統一資源定位符(Uniform Resource Locator)
URL 實在是太普及了,因此經常把這二者簡單地視爲相等。
URL組成的基本格式
瀏覽器會根據cheme使用默認的端口號 (HTTP 80 端口,HTTPS 443端口)
總結
狀態碼的分類爲
1××
1××類狀態碼屬於提示信息,是協議處理的中間狀態,實際可以用到的時候不多。
2××
2××類狀態碼錶示服務器收到併成功處理了客戶端的請求,這也是客戶端最願意看到的狀態碼。
「200 OK」是最多見的成功狀態碼,表示一切正常,服務器如客戶端所指望的那樣返回了處理結果,若是是非 HEAD 請求,一般在響應頭後都會有 body 數據。
「204 No Content」是另外一個很常見的成功狀態碼,它的含義與「200 OK」基本相同,但響應頭後沒有 body 數據。因此對於 Web 服務器來講,正確地區分 200 和 204 是很必要的。
「206 Partial Content」是 HTTP 分塊下載或斷點續傳的基礎,在客戶端發送「範圍請求」、要求獲取資源的部分數據時出現,它與 200 同樣,也是服務器成功處理了請求,但 body 裏的數據不是資源的所有,而是其中的一部分。
3××
3××類狀態碼錶示客戶端請求的資源發生了變更,客戶端必須用新的 URI 從新發送請求獲取資源,也就是一般所說的「重定向」,包括著名的 30一、302 跳轉。
「301 Moved Permanently」俗稱「永久重定向」,含義是這次請求的資源已經不存在了,須要改用改用新的 URI 再次訪問。
與它相似的是「302 Found」,曾經的描述短語是「Moved Temporarily」,俗稱「臨時重定向」,意思是請求的資源還在,但須要暫時用另外一個 URI 來訪問。
4××
4××類狀態碼錶示客戶端發送的請求報文有誤,服務器沒法處理,它就是真正的「錯誤碼」含義了。
「400 Bad Request」是一個通用的錯誤碼,表示請求報文有錯誤,但具體是數據格式錯誤、缺乏請求頭仍是 URI 超長它沒有明確說,只是一個籠統的錯誤,
「403 Forbidden」實際上不是客戶端的請求出錯,而是表示服務器禁止訪問資源。緣由可能多種多樣,例如信息敏感、法律禁止等,若是服務器友好一點
「404 Not Found」多是咱們最常看見也是最不肯意看到的一個狀態碼,它的原意是資源在本服務器上未找到
5××
5××類狀態碼錶示客戶端請求報文正確,但服務器在處理時內部發生了錯誤,沒法返回應有的響應數據,是服務器端的「錯誤碼」。
「500 Internal Server Error」與 400 相似,也是一個通用的錯誤碼
「501 Not Implemented」表示客戶端請求的功能還不支持
「502 Bad Gateway」一般是服務器做爲網關或者代理時返回的錯誤碼
「503 Service Unavailable」表示服務器當前很忙,暫時沒法響應服務,咱們上網時有時候遇到的「網絡服務正忙,請稍後重試」的提示信息就是狀態碼 503
總結
總結
HTTP雖然是可靠的傳輸協議但不保證傳輸的時候是徹底有效的,想要徹底可靠,須要使用中間件消息隊列等。
總結
數據類型和壓縮
當請求返回的時候,TCP和IP任務已經完成可是HTTP須要解析出響應文件的類型。同時HTTP文件內容在傳輸時候常常會有壓縮。所以產生數據類型和壓縮類型的需求。
HTTP支持壓縮類型有:
HTTP常見數據類型有:
HTTP 協議爲此定義了兩個 Accept 請求頭字段和兩個 Content 實體頭字段,用於客戶端和服務器進行「內容協商」。也就是說,客戶端用 Accept 頭告訴服務器但願接收什麼樣的數據,而服務器用 Content 頭告訴客戶端實際發送了什麼樣的數據。
爲了解決瀏覽器可以解析出正確的語言。爲此引入了語言類型和編碼。
Accept-language:指定了用戶使用想要使用的語言類型 (可有多個參數)
Accept-Language: zh-CN, zh, en
Content-Language:返回瀏覽器的語言類型
Content-Language: zh-CN
字符集在 HTTP 裏使用的請求頭字段是Accept-Charset,但響應頭裏卻沒有對應的 Content-Charset,而是在Content-Type字段的數據類型後面用「charset=xxx」來表示,這點須要特別注意。
總結
主要方法有兩種,壓縮以及分塊傳輸
壓縮的三種算法中gzip壓縮率能夠達到百分之60,而br算法對於HTML文件壓縮效率在gzip基礎上還能夠提高百分之20。
分塊傳輸(重點)
若使用分塊傳輸那麼響應報文會添加Transfer-Encoding以及Content-length。「Transfer-Encoding: chunked」和「Content-Length」這兩個字段是互斥的,也就是說響應報文裏這兩個字段不能同時出現,一個響應報文的傳輸要麼是長度已知,要麼是長度未知(chunked)。
範圍請求
HTTP 協議爲了知足視頻跳點觀看的需求,提出了「範圍請求」(range requests)的概念,範圍請求不是 Web 服務器必備的功能,能夠實現也能夠不實現,因此服務器必須在響應頭裏使用字段「Accept-Ranges: bytes」明確告知客戶端:「我是支持範圍請求的」。
主要內容短鏈接 長鏈接 隊頭阻塞
短鏈接
短鏈接對應版本爲HTTP0.9 指使用HTTP進行通訊時,二者每次傳送數據都要創建TCP鏈接,短鏈接的缺點嚴重製約了服務器的服務能力。
長鏈接
對於短鏈接的缺陷,HTTP1.1提出屢次請求只需創建一次TCP鏈接,減小服務器的消耗。使用的字段是Connection,值是「keep-alive」。長時間的空閒鏈接也會佔據服務器的資源,因此長鏈接也須要在適當的時間關閉。一般有兩種方式來在適當時間關閉請求,在必定請求後關閉鏈接 在設定空閒時間內無請求關閉鏈接
隊頭阻塞
隊頭阻塞主要是由於網絡模型爲「請求-應答」模型。前面的未響應請求對阻塞後方請求。對於HTTP來講可使用 併發鏈接來解決,對於同一個域名創建多個鏈接。(多個鏈接會加重服務器資源消耗被服務器當成攻擊拒絕鏈接)
總結
在網頁中由用戶主動發起請求的跳轉稱爲 主動跳轉,用戶沒法控制的稱爲 被動跳轉 ,同時也被稱爲 重定向
這裏出現了一個新的頭字段「Location: /index.html」,它就是 301/302 重定向跳轉的祕密所在。
「Location」字段屬於響應字段,必須出如今響應報文裏。但只有配合 301/302 狀態碼纔有意義,它標記了服務器要求重定向的 URI。
對於站內的連接可使用 相對URl 站外的連接必須使用 絕對URI
301 以及 302
在重定向狀態碼中重用的分別爲301以及302。 301稱爲「永久重定向」 302稱爲「臨時重定向」 。
永久重定向指當運行服務器進行更新以及修改,資源位置徹底改變時使用
臨時重定向指當系統進行維修或者在服務降級時進行調用
對於瀏覽器來講 永久和臨時的區別在於對於永久性的重定向,瀏覽器下次該地址時會進行優化。對於臨時,瀏覽器在下次訪問的時候只會認爲該地址暫時沒法使用,下次請求時仍會使用原來URL。
HTTP增長Cookie是爲了解決HTTP是無狀態鏈接的問題。爲此HTTP中增長響應頭字段Set-Cookie和請求頭字段Cookie。Cookie是存儲在客戶端也就是瀏覽器中,只在本瀏覽器內生效。
在Cookie中也能夠設置其餘cookie屬性如cookie過時時間,可使用 Expires 和 Max-Age 兩個屬性來設置。
Expires爲絕對過時時間,爲某個絕對時間點。 Max-Age爲相對過時時間在某個時間點上延長必定時間。瀏覽器會優先使用 Max-Age做爲過時的時間。
對於cookie的安全性,可使用另外一個屬性「SameSite」防範「跨站請求僞造」(XSRF)攻擊。屬性「HttpOnly」會告訴瀏覽器,此 Cookie 只能經過瀏覽器 HTTP 協議傳輸,禁止其餘方式訪問。
總結
這篇文章感受比較乾貨,建議看原文
服務器有緩存,瀏覽器也有緩存。緩存有什麼做用,又是經過哪幾個字段來保證有效,就是這篇文章的全部內容。
當使用瀏覽器的前進或者後退的時候,這時使用了緩存。在緩存期內瀏覽器有時仍會請求服務器獲取資源,由於緩存的使用是服務器和瀏覽器協商的結果。
緩存的字段有以下幾個
max-age:緩存使用的最大有效時間,注意max-age爲ttl(time to live)當服務器響應時開始計時;
no_store:不容許緩存,用於某些變化很是頻繁的數據,例如秒殺頁面;
no_cache:它的字面含義容易與 no_store 搞混,實際的意思並非不容許緩存,而是能夠緩存,但在使用以前必需要去服務器驗證是否過時,是否有最新的版本;
must-revalidate:又是一個和 no_cache 類似的詞,它的意思是若是緩存不過時就能夠繼續使用,但過時了若是還想用就必須去服務器驗證。
對於後兩種驗證緩存的類型,HTTP採用條件請求字段,將緩存的判斷放在服務端進行處理,由此來避免兩次請求佔用網絡帶寬。
條件請求一共有 5 個頭字段,咱們最經常使用的是「if-Modified-Since」和「If-None-Match」這兩個。須要第一次的響應報文預先提供「Last-modified」和「ETag」,而後第二次請求時就能夠帶上緩存裏的原值,驗證資源是不是最新的。(看原文)
總結
代理的主要做用:
代理相關頭字段:
Via:標明代理的身份,追加代理用戶的主機名或者域名。
X-Forwarded-For:每通過一個代理節點就會在字段裏追加一個信息。追加的是代理主機的IP。
X-Real-IP:記錄客戶端 IP 地址,沒有中間的代理信息,至關因而「X-Forwarded-For」的簡化版。
從抓包裏就能夠清晰地看出代理與客戶端、源服務器的通訊過程:
總結:
這篇我的認爲是漲知識的一篇文章
總結
由於 HTTPS 至關於「HTTP+SSL/TLS+TCP/IP」,其中的「HTTP」和「TCP/IP」咱們都已經明白了,只要再瞭解一下 SSL/TLS,HTTPS 也就可以輕鬆掌握。
SSL 的全稱是「Secure Socket Layer」,由網景公司發明,當發展到 3.0 時被標準化,更名爲 TLS,即「Transport Layer Security」,但因爲歷史的緣由仍是有不少人稱之爲 SSL/TLS,或者直接簡稱爲 SSL。
SSL 使用了許多密碼學最早進的研究成果,綜合了對稱加密、非對稱加密、摘要算法、數字簽名、數字證書等技術,可以在不安全的環境中爲通訊的雙方建立出一個祕密的、安全的傳輸通道,爲 HTTP 套上一副堅固的盔甲。
由於HTTP明文傳輸的不安全因此在原先HTTP運行的TCP/IP層上面添加了一層TLS/SSL來確保安全性。
安全性主要包括如下四個方面
SSL最初在1994年由網景公司提出,後在1999年更名爲TSL。目前普遍使用的協議是TSL1.2。
TLS 由記錄協議、握手協議、警告協議、變動密碼規範協議、擴展協議等幾個子協議組成,綜合使用了對稱加密、非對稱加密、身份認證等許多密碼學前沿技術。
TLS 的密碼套件命名很是規範,格式很固定。基本的形式是「密鑰交換算法 + 簽名算法 + 對稱加密算法 + 摘要算法」
「握手時使用 ECDHE 算法進行密鑰交換,用 RSA 簽名和身份認證,握手後的通訊使用 AES 對稱算法,密鑰長度 256 位,分組模式是 GCM,摘要算法 SHA384 用於消息認證和產生隨機數。」
總結
實現機密性最經常使用的手段是「加密」(encrypt),就是把消息用某種方式轉換成誰也看不懂的亂碼,只有掌握特殊「鑰匙」的人才能再轉換出原始文本。
這裏的「鑰匙」就叫作「密鑰」(key),加密前的消息叫「明文」(plain text/clear text),加密後的亂碼叫「密文」(cipher text),使用密鑰還原明文的過程叫「解密」(decrypt),是加密的反操做,加密解密的操做過程就是「加密算法」。
加密能夠分爲兩大類:對稱加密和非對稱加密。
對稱加密
「對稱加密」很好理解,就是指加密和解密時使用的密鑰都是同一個,是「對稱」的。只要保證了密鑰的安全,那整個通訊過程就能夠說具備了機密性。
對稱加密的算法主要由AES以及ChaCha20 。
加密分組模式
對稱算法還有一個「分組模式」的概念,它可讓算法用固定長度的密鑰加密任意長度的明文,把小祕密(即密鑰)轉化爲大祕密(即密文)。
非對稱加密
對稱加密看上去好像完美地實現了機密性,但其中有一個很大的問題:如何把密鑰安全地傳遞給對方,術語叫「密鑰交換」。
非對稱加密的算法主要有RSA和ECC。
混合加密
因爲非對稱加密常用數學方法進行加密解密,因此計算時間較長。對稱加密時間則比非對稱加密速度快好幾個量級。因此TSL使用混合加密。
在通訊剛開始的時候使用非對稱算法,好比 RSA、ECDHE,首先解決密鑰交換的問題。
而後用隨機數產生對稱算法使用的「會話密鑰」(session key),再用公鑰加密。由於會話密鑰很短,一般只有 16 字節或 32 字節,因此慢一點也無所謂。
對方拿到密文後用私鑰解密,取出會話密鑰。這樣,雙方就實現了對稱密鑰的安全交換,後續就再也不使用非對稱加密,全都使用對稱加密。
總結
實現完整性的手段主要是摘要算法(Digest Algorithm),也就是常說的散列函數、哈希函數(Hash Function)。
摘要算法使得絲絕不同的內容產生的結果也是徹底不一樣,TLS推薦使用的摘要算法主要是 SHA-2 , MD5以及SHA-1因爲算法的安全性不足 ,在TLS中被禁用。
真正的完整性必需要創建在機密性之上,在混合加密系統裏用會話密鑰加密消息和摘要,這樣黑客沒法得知明文,也就沒有辦法動手腳了。
數字簽名
非對稱加密裏的「私鑰」,使用私鑰再加上摘要算法,就可以實現「數字簽名」,同時實現「身份認證」和「不能否認」。
數字簽名的原理其實很簡單,就是把公鑰私鑰的用法反過來,以前是公鑰加密、私鑰解密,如今是私鑰加密、公鑰解密。
但又由於非對稱加密效率過低,因此私鑰只加密原文的摘要,這樣運算量就小的多,並且獲得的數字簽名也很小,方便保管和傳輸。
簽名和公鑰同樣徹底公開,任何人均可以獲取。但這個簽名只有用私鑰對應的公鑰才能解開,拿到摘要後,再比對原文驗證完整性,就能夠像簽署文件同樣證實消息確實是你發的。
數字證書和 CA
咱們常說的CA(Certificate Authority,證書認證機構)。它就像網絡世界裏的公安局、教育部、公證中心,具備極高的可信度,由它來給各個公鑰簽名,用自身的信譽來保證公鑰沒法僞造,是可信的。
CA 對公鑰的簽名認證也是有格式的,不是簡單地把公鑰綁定在持有者身份上就完事了,還要包含序列號、用途、頒發者、有效時間等等,把這些打成一個包再簽名,完整地證實公鑰關聯的各類信息,造成「數字證書」(Certificate)。
總結
頭部壓縮
因爲報文請求頭通常都會攜帶許多固定的頭字段,而請求體的內容每每只有不多同時屢次重複的請求使得重複的頭部字段被屢次發送,因此HTTP2開發出專門的壓縮算法進行頭部壓縮,因爲gzip算法會被」crime「攻擊因此HTTP2開發了專門的「HPACK」算法,在客戶端和服務器兩端創建「字典」,用索引號表示重複的字符串,還釆用哈夫曼編碼來壓縮整數和字符串,能夠達到 50%~90% 的高壓縮率。
二進制格式
因爲傳統的純文本形式會使用複雜的狀態機,致使文本解析效率低。HTTP2採用二進制來優化,將原來的的「Header+Body」的消息「打散」爲數個小片的二進制「幀」(Frame),用「HEADERS」幀存放頭數據、「DATA」幀存放實體數據。
虛擬的「流」
HTTP/2 爲此定義了一個「流」(Stream)的概念,它是二進制幀的雙向傳輸序列,同一個消息往返的幀會分配一個惟一的流 ID。經過流ID來組裝分散的二進制幀,由於「流」是虛擬的,實際上並不存在,因此 HTTP/2 就能夠在一個 TCP 鏈接上用「流」同時發送多個「碎片化」的消息,這就是常說的「多路複用」( Multiplexing)——多個往返通訊都複用一個鏈接來處理。
推送模式
HTTP/2 還在必定程度上改變了傳統的「請求 - 應答」工做模式,服務器再也不是徹底被動地響應請求,也能夠新建「流」主動向客戶端發送消息。好比,在瀏覽器剛請求 HTML 的時候就提早把可能會用到的 JS、CSS 文件發給客戶端,減小等待的延遲,這被稱爲「服務器推送」(Server Push,也叫 Cache Push)。
強化安全
互聯網上一般所能見到的 HTTP/2 都是使用「https」協議名,跑在 TLS 上面。
爲了區分「加密」和「明文」這兩個不一樣的版本,HTTP/2 協議定義了兩個字符串標識符:「h2」表示加密的HTTP/2,「h2c」表示明文的 HTTP/2,多出的那個字母「c」的意思是「clear text」。
協議棧
小結:
鏈接前言
TLS 握手成功以後,客戶端必需要發送一個「鏈接前言」(connection preface),用來確認創建 HTTP/2 鏈接。
HTTP2的鏈接前言使用的是「Magic」確保使用的HTTP2
頭部壓縮 :smiling_imp:
頭部壓縮算法使用的是HPACK算法。它是一個「有狀態」的算法,須要客戶端和服務器各自維護一份「索引表」,也能夠說是「字典」(這有點相似 brotli),壓縮和解壓縮就是查表和更新表的操做。 具體的實現爲將原先頭部的字段改成僞頭部形式爲「:authority」,":method"等來跟原先頭部進行區分。HTTP/2 就爲一些最經常使用的頭字段定義了一個只讀的「靜態表」(Static Table)。經過key——value的形式如 ":method":2來表示GET請求,在發送時候只要一個字節發送對應的索引2就能夠。
同時爲了解決自定義字段找不到的問題,使用了動態表,跟在靜態表的後面,在編碼解碼的時候隨時更新。
二進制幀
格式
二進制幀頭部佔9個字節。 幀長度3個字節表示最大傳輸的大小爲2^24 爲16M,通常默認上限爲2^14 爲16Kb 幀類型,大體能夠分紅數據幀和控制幀兩類,HEADERS 幀和 DATA 幀屬於數據幀,存放的是 HTTP 報文,而 SETTINGS、PING、PRIORITY 等則是用來管理流的控制幀。
標誌位:能夠保存 8 個標誌,攜帶簡單的控制信息。經常使用的標誌位有END_HEADERS表示頭數據結束,至關於 HTTP/1 裏頭後的空行(「\r\n」),END_STREAM表示單方向數據發送結束(即 EOS,End of Stream),至關於 HTTP/1 裏 Chunked 分塊結束標誌(「0\r\n\r\n」)。
流標識符:是用來確保多個複用的一個重要標誌,接收方使用它就能夠從亂序的幀裏識別出具備相同流 ID 的幀序列,按順序組裝起來就實現了虛擬的「流」。擁有32位,最多能夠表示21億個標誌,不過通常發送端使用的單數,服務端使用雙數。單邊流標誌在10億個左右。
流與多路複用
流是二進制幀的雙向傳輸序列 **在 HTTP/2 鏈接上,雖然幀是亂序收發的,但只要它們都擁有相同的流 ID,就都屬於一個流,並且在這個流裏幀不是無序的,而是有着嚴格的前後順序。**http2解決了原先請求響應的隊頭阻塞問題,須要明白的是並無解決流內部的隊頭阻塞問題,由於HTTP2使用的還是TCP協議,HTTP3改變使用UDP。
流的特色:
流狀態轉換
狀態轉換相似tcp的狀態轉換
總結:
總結篇 探索篇 安全篇的部份內容沒有記錄 本身感受在實踐中沒有太多用到,或者是自身儲備不足。下次再作記錄。