你們好,我是圖圖。也有一個多月沒有寫文章了。因爲各類緣由,被迫提桶,真是艱難。通過幾輪的面試以後,被面試官虐得慘慘的,其中許多緣由是沒有仔細的學過 HTTP 的知識,我對這塊的知識相對來講比較薄弱,因此決定把數據結構和算法得先放一放了。因此把 HTTP 的知識學一遍,而後再補一下JS的基礎。css
下面廢話很少說,咱們開始吧!html
HTTP是一種超文本傳輸協議,用於完成客戶端和服務器端等等一系列的運做流程。而協議指的是規則的約定。能夠說,Web 是創建在 HTTP 協議上進行通訊的。面試
我相信你們也是這樣,在學一門技術以前都會去了解一下它的歷史,下面來看看 HTTP 的發展史。算法
HTTP 誕生於 1989 年 3 月。是一個名叫蒂姆伯納斯-李的哥們兒提出的,最初設想的基本理念是:藉助多文檔之間相互關聯造成的超文本,連成可相互參閱的 WWW(World Wide Web,萬維網)。簡稱 Web。json
HTTP 0.9 在 1990 年問世。那時候的 HTTP 尚未做爲正式的標準被創建。瀏覽器
HTTP 1.0 在 1996 年 5 月 正式做爲標準。該協議標準如今仍然被普遍使用在服務器端。緩存
HTTP 1.1 在 1997 年 1 月公佈爲當前主流的 HTTP 協議版本。安全
HTTP 2.0 在 2012 年 3 月 徵集建議。性能優化
HTTP 2.0 在 同年的 9 月份 發佈了第一個草案。服務器
HTTP 2.0 在 2014 年 11 月實現了標準化。
在理解 HTTP 以前,咱們先簡單的來了解一下 TCP/IP 協議族。通常使用的網絡都是在 TCP/IP 協議的基礎上運做的,而 HTTP 屬於它內部的一個子集。
在計算機和網絡設備進行互相通訊時,雙方都必須基於相同的方法。好比,如何探測到通訊目標,是哪邊先發起通訊、用什麼語言進行通訊、怎樣結束通訊等等一些規則都是先要肯定好的。不一樣的硬件、操做系統之間的通訊,全部的這一切都須要一種規則。而這種規則稱爲協議
。
協議中包括:從電纜的規格到 IP 地址的選定方法、尋找異地用戶的方法、雙方創建通訊的順序,以及 Web 頁面顯示要處理的步驟,等等。將這些相關聯的協議集合起來總稱爲 TCP/IP。
TCP/IP 重要的點就是分層。有如下4
層:應用層、傳輸層、網絡層和數據鏈路層。
下面來介紹各層的做用。
應用層:應用層決定了向用戶提供應用服務時通訊的活動。好比,FTP(文件傳輸協議)和 DNS(域名解析系統)。HTTP 協議也在該層。
傳輸層:傳輸層對上層應用層,提供處於網絡鏈接中的兩臺計算機之間的數據傳送。該層有兩個不一樣的協議:TCP 傳輸控制協議和 UDP 用戶數據協議。
網絡層:網絡層用來處理在網絡上的數據包。數據包是網絡傳輸的最小數據單位。網絡層的做用就是在多條路線中選出一條傳輸路線進行數據傳輸。
鏈路層:用來處理鏈接網絡的硬件部分。包括什麼操做系統、硬件的設備、什麼路由器啊之類的等等,都屬於該層。
TCP/IP 層次化的好處是:若是互聯網由一個協議統一規劃,某個地方須要改變設計時,就必須將全部部分總體替換掉。而分層以後只須要把變更的層替換掉。把各層之間的接口部分規劃好以後,每層內部的設計就能夠自由改動。好比,處於應用層上的應用能夠只考慮分配給本身的任務,不用去考慮其餘的問題。
TCP/IP 協議進行通訊時,會經過分層順序和對方進行通訊。客戶端從應用層往下走,服務器端則從鏈路層往上走。看下面的圖。
在HTTP客戶端向服務器端發送報文以前,須要用到 IP、TCP、DNS 這三個和 HTTP 密不可分的協議。
IP(Internet Protocol
)網絡協議處於網絡層。IP協議的做用是把各類數據包傳送給對方。但要保證正確的傳送給對方,其中兩個重要的條件是 IP 地址和 MAC 地址。能夠把它想象成你家的地址,或者說你的電話號碼。
IP 地址指的是節點被分配到的地址,MAC 地址指的是網卡所屬的固定地址。IP 地址能夠跟 MAC 地址進行配對。IP 地址是可變的,MAC 地址是不可變的。
IP 和 IP地址別搞混了,IP是一種協議。而IP地址是則是每臺計算機的標識
IP 間的通訊依賴 MAC 地址。在網絡上通訊的雙方不多會在同一個局域網,通常都是通過多臺計算機或者網絡設備中專才能鏈接到對方。而在中轉的過程當中,會利用下一站中轉設備的 MAC 地址進行搜索下一個中轉目標。而這時,會用到ARP協議。ARP協議是一種用來解析地址的協議,經過通訊方的 IP 地址就能反查出對應的 MAC 地址。
在到達通訊目標前的中轉過程當中,計算機和路由器只能獲取粗略的傳輸路線,這種機制叫作路由選擇。
就跟你在淘寶上買東西是同樣的道理。好比,你在淘寶網買了件衣服,快遞公司會根據你的地址進行送貨,在送貨這個過程當中,並非直接送到你手裏。而是通過各類什麼杭州中轉站而後又到深圳中轉站,以後才送到你手裏。
TCP 協議處於傳輸層,主要的做用是提供可靠的字節流服務。字節流服務指的是,爲了方便傳輸,將大塊的數據分割成以報文段爲單位的數據包進行管理。而可靠性的傳輸服務指的是,可以把數據準確可靠的傳給對方。
爲了準確的將數據傳送給對方,三次握手就出現了。下圖展現這個過程。
DNS 服務和 HTTP協議同樣,處於應用層。它主要的做用是,將域名解析成 IP 地址。DNS 協議能夠經過域名查找 IP 地址,也能夠經過 IP 地址反查域名的服務。
下面展現每一個協議和HTTP協議的關係。
http://www.tutu.com
。Uniform Resource Identifier
,它的做用是區分互聯網中的不一樣資源。好比,HTML 文檔、圖像、視頻片斷、程序等等。而 URL 是 URI 的一個子集。下圖展現了 URI 的格式。
http:
或https:
表示協議名稱。不區分字母大小寫,最後加上//
。user:pass@
表示獲取服務器資源的用戶和密碼。但不推薦使用,由於不安全。www.tutu.com
;192.168.0.1
地址名;[0:0:0:0:0:0:1]
這種方括號括起來的 IPv6 地址;:8080
表示端口號。/html/index.html
表示服務器文件路徑,資源的訪問位置。?userId=1
表示文件路徑中的參數。?
後面以key=value
的形式。若是後面還須要加參數,用&
拼接。#cn1
表示文件中的某個位置。就是平時的網頁錨點定位。HTTP 是一種無狀態的協議,對發送過的請求/響應都不作持久化處理。
HTTP 1.1 中的全部鏈接都是默認開啓的(keep-alive
)。經過請求/響應頭部的Connection
字段能夠查看是否開啓持久化鏈接(後面會介紹該字段的值),而在 HTTP1.0中是默認關閉的(close
)。
它的特色是,無論是客戶端仍是服務器端,只要其中的一端沒有提出斷開鏈接,那麼就會保持 TCP 鏈接。好處是,減小 TCP 鏈接的重複創建和斷開鏈接形成的額外開銷,減輕服務器壓力。這樣使得 HTTP 請求和響應速度更快結束,也提升頁面的顯示速度。
管線化是不用等待響應就能夠發送下一個請求,也就是並行處理。不用一個接一個的等待響應,管線化比持久化鏈接還要更快。
HTTP 一共有兩種報文:請求報文、響應報文。報文又分爲報文頭部和報文主體,報文主體是可選的。報文包含了如下三個部分。
start line
)有如下兩種類型。
header
):一些頭部信息,以key: value
的形式。body
):被髮送的數據。這張圖是以請求報文爲例。
1XX
表示接收的請求正在處理。
200 OK
:表示客戶端發送的請求在服務器端被正常處理了。204 No Content
:表示請求被處理成功,但沒有資源可返回。206 Partial Content
:表示客戶端只獲取文件的一部份內容,而服務器成功執行了這部分的GET
請求。響應報文中含Content-Range
指定部分的實體內容。301 Moved Permanenty
:永久重定向。表示請求的資源已經被分配了新的 URL,之後就使用資源如今所指的 URL。302 Found
:臨時重定向。表示請求的資源被分配了新的 URL。303 See Other
:表示請求的資源存着另外一個 URL,應該用GET
方法獲取請求的資源。304 Not Modified
:表示請求已經找到,但不符合條件請求。協商緩存就會返回這個狀態碼。307 Temporary Redirect
:臨時重定向,和302
相似。可是補鞥呢改變請求方法。當30一、30二、303響應狀態碼返回時,幾乎全部瀏覽器都會將POST改成GET,並刪除請求報文中的主體,以後請求會自動再次發送。30一、302標準是禁止把POST改爲GET的,但實際使用的時候你們都會這麼作。
400 Bad Request
:表示請求報文中存在語法錯誤。401 Unauthorized
:表示發送的請求要經過 HTTP 認證的認證消息。若是以前請求過一次,就表示用戶認證失敗。403 Forbidden
:表示對請求資源的訪問被服務器拒絕。404 Not Found
:表示服務器上沒法找到請求的資源。500 Internal Serve Error
:表示服務器端在執行請求時發生錯誤。503 Service Unavailable
:表示服務器暫處於超負荷或者正在進行停機維護。HTTP進行通訊時,除了客戶端和服務器端這兩個以外,還有一些用於通訊數據轉發的應用程序。例如代理、網關、隧道和緩存。
代理是一種具備轉發功能的應用程序,它存在於客戶端和服務器端之間,至關於一箇中間人。它將客戶端發送過來的請求並轉發給服務器端。固然,它也會將服務器端返回的響應轉發給客戶端。
每次經過代理服務器轉發請求或響應時,頭部都會出現Via
這個字段。
網關是一種特殊的服務器,做爲其餘服務器的中間實體使用。用於將 HTTP 請求轉化成其餘協議通訊。網關接收請求時就好像本身的資源的源服務器同樣對請求作處理。
隧道是可按要求創建一條和其餘服務器的通訊線路,到時候使用 SSL 加密進行通訊。隧道的目的是保證客戶端和服務器進行安全的通訊。
緩存是指代理服務器或客戶端本地磁盤中保存的資源副本。利用緩存能夠減小向源服務器的訪問,主要目的是減小網絡帶寬的流量和通訊時間。
緩存服務器是代理服務器的一種,當代理轉發從服務器返回的響應時,會保存一份資源的副本。緩存服務器的優勢在於經過緩存能夠避免屢次從源服務器轉發資源。所以客戶端可就近從緩存服務器上獲取資源,而源服務器也沒必要屢次處理相同的請求。
每當源服務器上的資源更新時,若是仍是用不變的緩存,那就會變成返回更新前的舊資源。
即便存在緩存,也會由於客戶端的要求、緩存的有效期等等一些因素,向源服務器確認資源的有效性。若是緩存的資源已過時,緩存服務器會向源服務器上獲取新的資源。
這裏的客戶端緩存指的是瀏覽器中的緩存。瀏覽器緩存若是未過時,就不用向源服務器請求相同的資源,直接獲取緩存在本地磁盤中的資源。當資源過時時,會向源服務器確認資源的有效性。若是緩存的資源過時,就會再次向源服務器發起資源請求。
內容協商機制是指客戶端和服務器端就響應的資源內容進行互相協商,而後提供客戶端最合適的資源。內容協商會以語言、字符集、編碼方式等。
主要使用的請求頭有:
內容協商技術有下面三種類型。
HTTP 頭字段定義成緩存代理和非緩存代理。分爲兩種類型。
End-to-end
Hop-by-hop
Hop-by-hop
頭,就要提供 Connection
頭字段。除了下面 8 個頭字段外,其餘全部字段都屬於端到端頭部。
Connection
Keep-Alive
Proxy-Authenticate
Proxy-Authorization
Trailer
TE
Transfer-Encoding
Upgrade
下面列出請求/響應頭都會出現的字段,這些字段都含有重要的信息。
Cache-Control
表示資源的緩存操做,參數是可選的,若是存在多個參數的話,以,
分隔開。
在請求頭中使用Cache-Control
字段時,它的值以下:
no-cache
:不使用強緩存,強制向源服務器再次驗證緩存的資源是否過時(走協商緩存)。no-store
:不使用任何緩存,每次都向源服務器獲取最新的資源。max-age
:以秒爲單位。表示緩存的資源沒有超過指定的時間,客戶端就從緩存中獲取資源。min-fresh
:以秒爲單位。要求代理服務器返回至少還沒過指定時間的緩存資源。max-stale
:即便是過時的資源,也照樣接收。only-if-cached
:告訴代理服務器,從緩存中獲取資源(若是有)。no-transform
:不能對資源進行轉換,能夠防止緩存或代理壓縮圖片等相似操做。在響應頭中使用Cache-Control
字段時,它的值以下:
public
:資源可被瀏覽器和代理服務器進行緩存。private
:資源只能夠被瀏覽器進行緩存。其餘都不能夠。no-cache
:能夠緩存,但每次使用前要向源服務器驗證緩存資源是否過時。s-maxage
:只提供給代理服務器,表示代理服務器中的資源過時時長,用s-maxage
後,會忽略max-age
和Expires
字段。max-age
:以秒爲單位。設置緩存時間,若是沒超過該時間,不用向服務器請求資源。若是超過,就證實資源已過時。若是響應頭出現Expires
字段,在 HTTP 1.1 中會有限處理max-age
,而 HTTP1.0 中則相反。must-revalidate
:能夠緩存,但必須向源服務器再次驗證。若是請求失敗,則返回504
狀態碼。該字段會忽略max-stale
。proxy-revalidate
:要求緩存服務器對緩存的響應有效性進行確認。no-transform
:不能對資源進行轉換,能夠防止緩存或代理壓縮圖片等相似操做。Connection
字段決定當前 TCP鏈接 完成後,是否關閉鏈接。有如下兩種。
keep-Alive
:持久化鏈接。close
: TCP 鏈接完成後,立馬關閉鏈接。Date
字段的值爲GMT時間日期格式,表示 HTTP 報文建立的時間和日期。
Date: Tue, 13 Apr 2021 12:35:41 GMT
複製代碼
Pragma
是用來向後兼容只支持 HTTP1.0 協議的緩存服務器。它的效果和Cache-Control
同樣。
Pragma: no-cache
複製代碼
Upgrade
用於查看 HTTP 協議或者其餘協議是否可使用更高的版本進行通訊。
Upgrade: HTTP/2.0
Connection: Upgrade <!-- 表示刪除了Upgrade後再轉發 -->
複製代碼
Via
用於跟蹤客戶端和服務器端之間的請求和響應報文的傳輸路徑,還能夠避免請求循環的發生。
<!-- 通過單個代理服務器 -->
Via: 1.0 gw.hackr.jp(Squid/3.1)
<!-- 通過多個代理服務器 -->
Via: 1.0 gw.hackr.jp(Squid/3.1), 1.1 al.example.com(Squid/2.7)
複製代碼
通過代理服務器 A 時,Via頭部附加了 「1.0 gw.hackr.jp(Squid/3.1)」 這樣的字符串值。行頭 1.0 指的是接收請求的服務器上應用的 HTTP 協議版本。若是通過多個代理服務器的話,這些信息會後面追加。
Warning
字段告訴用戶一些與緩存有關的警告。
Accept
請求頭用來告訴服務器,客戶端能處理的內容類型。下面列出幾種媒體類型。
text/html
、text/plain
、text/css
、application/xhtml+xml
、application/xml
等等。image/jpeg
、image/gif
、image/png
;video/mpeg
、video/quicktime
;application/octet-stream
、application/zip
;當值爲*/*
,表示客戶端能夠是任意內容類型。當值爲image/*
,用來表明任何其餘圖片類型。
若是想給顯示的媒體類型增長優先級,經過用q=
表示權重值,用分號(;
)分隔開。權重值的範圍是0~1
,能夠精確到小數點後 3 位,1
是最大值。沒有指定權重值時,默認權重是q=1.0
。
Accept: text/html, appliaction/json;q=0.9
複製代碼
Accept-Charset
請求頭用來告訴服務器,客戶端可處理的字符集類型。另外,能夠一次性指定多種字符集。和Accept
同樣,經過q
值來表示優先級。該頭部應用於內容協商機制的服務器驅動協商。
Accept-Charset: iso-8859-1
Accept-Charset: iso-8859-1;q=0.5
複製代碼
Accept-Encoding
請求頭用來告訴服務器,客戶端能理解的內容編碼方式。能夠一次性指定多種內容編碼,有如下幾種編碼。
gzip
生成的編碼格式,使用 Lempel-Ziv
算法以及 32 位循環冗餘驗證。compress
生成的編碼方式,採用Lempel-Ziv-Welch
算法。zlib
格式以及由deflate
壓縮算法生成的編碼方式。Accept-Encoding: gzip, deflate
複製代碼
和Accept
同樣,用q
值來設置優先級。還有使用星號(*
),表示指定任意的編碼格式。
Accept-Language
請求頭用來告訴服務器,客戶端能夠理解的天然語言集(指中文和英文集),以及天然語言集的優先級。和Accept
同樣的,可指定多個天然語言集。使用q
值設置優先級。
Accept-Language: zh-CN,zh;q=0.9;q=0.8
複製代碼
客戶端在服務器有中文版的狀況下,會請求返回中文版的響應,若是沒有,則返回英文版。
Authorization
用來告訴服務器,用戶代理的認證信息(證書值)。一般會在服務器返回401
狀態碼響應後,把頭部字段Authorization
添加到請求中。
Authorization: Basic dWVub3NlbjpwYXNzd29yZA==
複製代碼
Expect
用來告訴服務器,只有在知足這個條件的狀況下才會處理請求。若是服務器不能知足客戶端的要求,會返回417
狀態碼。目前只規定了100-continue
這個條件。
Expect: 100-continue
複製代碼
From
字段表示用戶代理的用戶的電子郵箱地址,目的是爲了顯示搜索引擎用戶代理的負責人的電子郵箱聯繫方式。
From: info@hackr.jp
複製代碼
Host
請求頭指明瞭請求的資源所在的服務器主機名和端口號。若是服務器沒設置主機名,會發送一個空值。
Host: www.tutu.com
複製代碼
像這種If-xxxx
開頭的請求頭字段,都是條件請求。服務器接收到附帶條件的請求後,只判斷條件是真時纔會執行請求。
If-Match
字段用於和服務器資源的ETag
值作對比時,ETag
值和If-Match
的值相等時纔會處理該請求。不然返回412
狀態碼。經過用星號(*
)的方式,表示只要資源存在就處理請求,但服務器會忽略掉ETag
的值。
If-Match: "123456"
複製代碼
If-Modified-Since
用於肯定代理服務器或客戶端的資源有效性。在指定的時間以後,請求的資源發生改變時,就處理請求。若是資源都沒有改變,則返回304
狀態碼。
If-Modified-Since: Tue, 13 Apr 2021 12:35:41 GMT
複製代碼
If-None-Match
和If-Match
相反,只有服務器資源的ETag
的值和If-None-Match
的值不同時,纔會處理該請求。在GET
和HEAD
請求方法中加入該字段能夠獲取最新的資源。
If-Range
用於告訴服務器,若是If-Range
字段的值和請求資源的ETag
值或時間同樣時,就會做爲範圍請求處理(Range
字段規定請求多少字節的數據)。不然,忽略範圍請求,返回所有資源。
If-Range: "123456"
Range: bytes=5001-10000
複製代碼
If-Unmodified-Since
字段用來告訴服務器,只有當請求資源在指定的時間以後沒有修改的狀況下,纔會處理請求。若是在指定的時間後發生了修改,則返回412
狀態碼。
If-Unmodified-Since: Tue, 13 Apr 2021 12:35:41 GMT
複製代碼
Proxy-Authorization
字段包含了用戶代理提供給代理服務器用於身份驗證的憑證。
Proxy-Authorization: Basic dGlwOjkpNLAGfFY5
複製代碼
Range
請求頭字段表示獲取資源的哪一部分。服務器收到帶有Range
字段的請求後,會在處理請求以後返回206
狀態碼。若是沒法處理,則返回200
狀態碼並把所有資源返回。
Range: bytes=5001-10000 <!-- bytes=5001-10000爲資源的字節 -->
複製代碼
Referer
字段表示請求的URL是從哪一個 Web 頁面發起的。服務器經過Referer
字段來標識訪問來源,進行統計分析、日誌記錄和緩存優化。
Referer: www.tutu.com <!-- 請求是由www.tutu.com發起的 -->
複製代碼
TE
表示客戶端可以處理響應的傳輸編碼方式以及優先級。
TE: gzip, deflate;q=0.5
複製代碼
User-Agent
字段用於把請求的瀏覽器和用戶代理名稱等信息傳給服務器。
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36
複製代碼
Accept-Ranges
表示服務器端能處理指定範圍內的資源。有兩個值:bytes
和none
。none
表示不能處理指定範圍內的請求。
Age
表示源服務器再多久前返回過資源。單位爲秒。
Age: 3600
複製代碼
ETag
表示資源的特定標識符,服務器會給每份資源都分配對應的ETag
值。當資源發生變化時,ETag
值也會改變。例如,訪問同一個 URL 的網站同時具有有中英文版,當切換中文時,會返回中文的資源(ETag: user-chi
),而切換到英文時,返回的是英文的資源(ETag: user-us
)。
ETag: "user-123456"
複製代碼
ETag
值。字段值最開頭會添加W/
的字符ETag: W/"user-123456"
複製代碼
Location
字段表示須要將頁面重定向到某個地址,通常都是響應碼爲3xx
的響應纔有用。
Location: www.baidu.com <!-- 重定向到www.baidu.com -->
複製代碼
Proxy-Authenticate
字段表示獲取代理服務器的資源要經過身份驗證的方式。
Retry-After
字段表示客戶端應該在多久以後再次請求。配合503
和3xx
狀態碼響應一塊兒使用。
Retry-After: 120
複製代碼
Server
字段表示處理請求的服務器所用到的軟件相關信息。
Server: Apache/2.2.17
複製代碼
Vary
字段能夠對緩存進行控制。從代理服務器收到源服務器返回含有Vary
指定項的響應後,若是要進行緩存,那麼會對請求中含有Vary
指定頭部字段的請求返回緩存。即便對相同資源發起請求,若是Vary
指定的頭部字段不相同,就必須從源服務器從新獲取資源。
Vary: Accept-Language
複製代碼
Allow
用於告訴客戶端,資源所支持的 HTTP 方法,若是服務器收到不支持的 HTTP 方法時,會返回405
狀態碼做爲響應。
Allow: GET, DELETE
複製代碼
Content-Encoding
字段表示服務器對實體的主體部分用的內容編碼方式。內容編碼在Accept-Encoding
中已經介紹過,一共有4
種。
Content-Encoding: gzip
複製代碼
Content-Language
字段表示實體主體使用的天然語言。
Content-Language: zh-CN
複製代碼
Content-Length
表示實體主體部分的大小(以字節爲單位)。
Content-Length: 1500
複製代碼
Content-Location
字段表示要返回數據的地址。
Content-Location: https://www.tutu.com/index.html
複製代碼
Content-Range
字段表示的是一個數據片斷在整個文件中的位置。
Content-Range: bytes 5001-10000/10000
複製代碼
Content-type
字段表示實體主體中對象的媒體類型。
Content-type: text/html; charset=UTF-8
複製代碼
Expires
字段會把資源失效的日期告訴客戶端。在這個日期後,資源就會過時。也就是說,在指定的日期內能夠從瀏覽器緩存中獲取資源。若是超過了這個日期,就必須向服務器發起資源請求。若是頭部存在Cache-Control: max-age
時,會優先處理max-age
指令。
Expires: Tue, 13 Apr 2021 12:35:41 GMT
複製代碼
Last-Modified
字段表示資源最後修改的時間。
Last-Modified: Tue, 13 Apr 2021 12:35:41 GMT
複製代碼
HTTP 緩存可分爲強緩存和協商緩存,主要用於加快資源的獲取速度,提升用戶體驗,減小網絡鏈接,緩解服務器壓力。
對強緩存來講,瀏覽器會判斷請求的資源是否在有效期內。若是是在有效期內,就直接從緩存中讀取資源,不用向服務器發送資源請求。強緩存經過Expires
、Cache-Control
和Pragma
這三個頭部字段設置。
Cache-Control
頭部字段在上面也詳細介紹過在各端所具有的屬性值。下面來列出最多見的幾個值。
public
: 該資源能夠被瀏覽器和代理服務器進行緩存。private
: 該資源只能夠被瀏覽器緩存,其餘都不能夠。no-cache
: 不使用強緩存,強制向源服務器再次驗證緩存的有效性。這個值表示走協商緩存。no-store
: 不使用任何緩存,每次都向源服務器獲取最新資源。max-age
: 若是緩存的資源沒有超過規定的時間,客戶端就從緩存中獲取資源。以秒爲單位。s-maxage
: 只適用於代理服務器,表示代理服務器中的資源過時時長,用了s-maxage
後,會忽略max-age
和Expires
字段。Expires
字段的值是一個GMT
格式的時間日期,將資源失效的日期告訴客戶端,客戶端收到帶有該字段的響應體後進行緩存。後續客戶端發起相同的資源請求,會用Expires
的值和本地時間作對比,若是該請求的本地時間小於Expires
的值,就直接用緩存中的資源,不用向服務器發起請求。
Expires
的值會產生一個問題。若是修改了本地時間,就會致使客戶端和服務器端的時間不一致,那麼對於緩存過時的判斷就沒法和預期同樣了。
Expires
在三者中優先級最低。
Pragma
能夠看上面的介紹,這裏不過多講解。
強緩存在 Chrome 中會返回200
狀態碼而且有兩種狀況。
memory cache
: 只要頁面不關閉,就會從瀏覽器內存中獲取資源。disk cache
: 從磁盤中讀取緩存資源。用了強緩存後,若是服務器端的資源更新了,客戶端是不知道的,並且在過時以前都會用緩存中的資源。能夠經過Ctrl
+ F5
強制刷新。
協商緩存是在用本地緩存以前,會向服務器發起一次GET
請求,驗證瀏覽器保存在本地的資源是否過時。
通常狀況下是用請求資源的最近一次修改時間戳來判斷。來舉個例子:假設客戶端向服務器端請求一個文件,爲了讓資源被再次請求時能經過協商緩存機制使用本地緩存。首次返回該資源的響應頭中會包含一個last-modified
的字段,字段的值表示資源最後修改的時間。當刷新頁面時,該資源使用的是協商緩存,瀏覽器沒法確認本地緩存是否過時,而後向服務器發起一次GET
請求,進行緩存有效性的協商,本次請求的請求頭中包含一個if-modified-since
字段,字段的值是上次響應頭中的last-modified
字段的值。
last-modified
存在兩個缺陷:
爲了彌補經過時間判斷的不足,HTTP 1.1 加入了ETag
(實體標籤)的頭信息。
ETag
表示資源的特定標識符,相似文件指紋。做用上面也有提到,這裏不過多講解。
當響應頭同時存在last-modified
和ETag
這兩個字段時,會以ETag
爲準。再次對該資源發起請求時,會將以前的響應頭中ETag
的值看成此次請求中if-none-match
字段的值,發送給服務器進行緩存有效性驗證。若是驗證緩存有效,就返回304
狀態碼響應重定向到本地緩存。
ETag
的出現並非last-modified
的代替品,而是一種補充方案,它仍是存在弊端的。
ETag
的過程會影響到服務器的性能。ETag
還分強ETag
和弱ETag
。
ETag
值是根據資源內容進行生成,保證每一個字節都相同。ETag
值是根據資源的部分屬性值來生成,生成速度快可是沒法保證每一個字節都相同。若是瀏覽器走的是協商緩存,而且資源沒發生改變,服務器端會返回304
狀態響應碼告訴瀏覽器獲取本地緩存的資源便可。
HTTP協議主要的不足之處有如下幾點。
HTTP 協議自己沒有加密功能,因此沒法作到對通訊請求和響應內容進行加密。
因爲 TCP/IP 協議的工做機制,通訊內容在全部通訊線路上都有可能遭到窺視。無論是哪一個角落的服務器在跟客戶端進行通訊,通訊的線路上的一些設備都不多是我的物品。因此不排除在某個環節上遭到惡意窺視的行爲。即便進行加密處理,也會被窺視到通訊的內容。竊聽相同端上的通訊並非難事,只要收集在網絡上流動的數據包就行。能夠經過抓包和嗅探器工具來收集數據包。
最多見的兩種加密方式是通訊加密和內容加密
HTTP 協議中自己沒有加密機制,但能夠經過 SSL(Secure Socket Layer 安全套階層) 或 TLS(Transport Layer Security 安全傳輸層協議) 的組合使用,加密HTTP的通訊內容。用 SSL 創建安全通訊線路後,就能夠在這條線路上進行 HTTP 通訊。和 SSL 組合使用的 HTTP 叫作 HTTPS (HTTP Secure 超文本傳輸安全協議) 或 HTTP over SSL。
因爲 HTTP 協議中沒有加密機制,那麼能夠對傳輸的內容自己進行加密。也就是把 HTTP 報文中包含的內容進行加密處理。在這種狀況下,客戶端須要對 HTTP 報文主體(body
)進行加密處理後再發送請求。要作到內容的加密,前提是客戶端和服務器端同時具備加密和解密的機制。主要應用在 Web 服務器中。該方式不一樣於 SSL 和 TLS 把整個通訊線路加密處理,因此內容仍是會有被篡改的可能。
HTTP 協議的請求和響應都不會對通訊方進行確認。
在 HTTP 協議通訊時,因爲不存在肯定通訊方的處理步驟,任何人均可以發起請求。服務器只要收到請求,無論是誰都會返回一個響應(僅限發送端的 IP 地址和端口號沒被 Web 服務器設置限制訪問的前提下)。也就是來者不拒。
雖然使用 HTTP 協議沒法肯定通訊方,但使用 SSL 能夠。SSL 除了加密處理外,還用了一種證書的手段,用於確認通訊方。證書是由值得信任的第三方機構頒發,用來證實服務器和客戶端是真實存在的。
經過證書,以證實通訊方就是意料中的服務器,對我的來講,減小了我的信息泄露的危險。另外,客戶端持有證書便可完成我的身份的確認,也可用於對 Web 網站的認證環節。
沒有任何辦法確認,發出去的請求或響應和接收到的請求或響應是先後相同的。有可能在中途被篡改爲其餘的內容,即便內容是真的被改了,接收方也不會知道。
可使用 MD5 和 SHA-1 等散列值校驗方法,以及用來確認文件的數字簽名方法(PGP簽名)對內容進行加密。可是用這些方法也沒法保證正確,由於 MD5 和 PGP 自己被修改的話,用戶也不會知道。
HTTP加上加密處理和認證以及完整性保護機制就是HTTPS
HTTPS 不是應用層的一種新協議。只是 HTTP 通訊接口部分用 SSL 和 TLS 協議代替而已。以前是 HTTP 和 TCP 進行通訊,用了 SSL 以後,就變成了 HTTP 先和 SSL 通訊,以後 SSL 和 TCP 通訊。
使用 SSL 以後,HTTP 就有了 HTTPS 的加密、證書和完整保護性這些功能。
SSL 用的是公開密鑰加密的處理方式。加密方法中的加密算法是公開的,密鑰則是保密的。經過這種方式能夠保持加密方法的安全性。
加密和解密都會用到密鑰。沒有密鑰就沒辦法對密碼解密,任何人只要有密鑰就能夠進行解密,若是密鑰被攻擊者得到,那麼加密也就沒有意義了。
加密和解密同用一個密鑰的方式叫作共享密鑰加密,也稱爲對稱密鑰加密。也就是說,客戶端和服務器端共用一個密鑰對消息進行加密。客戶端在發送請求時,會用密鑰對消息加密。服務器收到後,再用密鑰對消息進行解密。
對稱加密雖然保證了消息保密性,但客戶端和服務器端用的都是同一個密鑰,若是說在傳輸的過程當中出現了中間人或攻擊者。密鑰就有可能落到攻擊者手中,這樣就對消息加密就沒有什麼意義了。
非對稱加密解決了對稱加密的缺點。非對稱加密用的是一對非對稱的密鑰。一把叫作私有密鑰,另外一把叫作公開密鑰。私有密鑰只能是本身所擁有,而公開密鑰則是任何人均可以拿到。
當客戶端發送消息前,使用公共密鑰進行加密,而服務器收到消息後,使用私有密鑰進行解密。
非對稱加密須要在發送端在發送消息時,用公鑰加密。但公鑰是任何人均可以拿到,中間人也能夠。中間人雖然不知道接收方的私鑰是什麼,但能夠截獲發送端的公鑰,本身另外生成一把公鑰或者篡改公鑰,把公鑰發給接收端。並且非對稱加密處理起來比對稱加密的方式更加複雜,這樣就致使了效率變低。
HTTPS 用的就是對稱加密和非對稱加密二者的混合加密。使用對稱加密的好處是解密效率快,使用非對稱加密的好處是在傳輸消息的過程當中不會被破解。即便截獲了數據,沒有對應的私鑰,也沒法對消息進行破解。
數字摘要是採用 Hash 函數將須要加密的明文 「摘要」 成一串固定長度(128
位)的密文,這串密文又稱爲數字指紋,它有固定長度,並且不一樣的明文摘要成密文,其結果老是不一樣,而一樣的明文摘要必須一致。數字摘要是 HTTPS 能確保數據完整性和防篡改的根本緣由。
數字簽名是非對稱加密和數字摘要兩項技術的應用,它將摘要信息用發送者的私鑰加密,和原文一塊兒發給接收者。接收者只有用發送者的公鑰才能解密被加密的摘要信息,而後用 Hash 函數對收到的原文產生一個摘要信息,與解密的摘要信息對比。若是同樣,那就說明收到的信息是完整的。不然說明信息被修改過,所以數字簽名可以驗證信息的完整性。
數字簽名是附加在報文上的特殊加密校驗碼。使用數字簽名有如下兩點好處。
數字簽名的過程以下: 明文 -> hash運算 -> 摘要 -> 私鑰加密 -> 數字簽名
數字證書(CA)就像咱們的身份證同樣,信息都是惟一性的。它是屬於可信任的一些第三方機構全部。證書包含了如下的信息。
數字證書還包括對象的公鑰,對象和所用簽名算法的描述信息。全部人均可以建立一個數字證書,但並非全部人都能得到簽發權,從而爲證書信息擔保,並用它私有密鑰簽發證書。
HTTPS 用的是 SSL(Secure Socket Layer 安全套階層) 和 TLS(Transport Layer Security 安全傳輸層協議)這兩個協議。SSL 最開始是網景先倡導,後來網景涼了,就轉移給了 IETF 的手裏。IETF 以 SSL 3.0 爲準,以後又定製了 TLS1.0、TLS1.1和 TLS1.2。TLS 是以 SSL 爲原型開發的協議。有時候統一稱該協議爲 SSL。
凡事都具備兩面性,不是說 HTTPS 安全就沒有問題了。其實它仍是存在一些問題的。在使用 SSL 時,它的處理速度會變慢。其緣由有兩種,一是通訊慢,二是每次都進行加密通訊,就致使消耗大量的 CPU 和內存資源,致使處理速度變慢。
固然能夠用 SSL 加速(專用服務器)硬件來改善效率的問題。能夠提升 SSL 的計算速度,分擔負載。但只有在 SSL 處理時才發揮 SSL 加速器的效果。像一些非敏感的信息就用 HTTP 進行通訊,對於敏感信息採用 HTTPS 通訊,以節約資源。
80
,後者是 443
。HTTP 1.x主要有如下幾個缺點:
SPDY 是由谷歌開發的基於 TCP 協議的應用層協議。目標是爲了優化 HTTP 協議的性能,經過壓縮、多路複用和優先級技術,縮短網頁的加載時間並提升安全性。SPDY 協議的核心思想是儘可能減小 TCP 的鏈接數。SPDY 並非一種代替 HTTP 的協議,而是對 HTTP 協議的加強。
SPDY 沒有改寫 HTTP 協議,而是在 TCP/IP的應用層和傳輸層之間經過新加會話層的形式運做。同時,考慮到安全問題,SPDY 規定通訊中使用 SSL。
SPDY 以會話層的形式加入,控制對數據的流動,但仍是採用 HTTP 創建通訊。所以,能夠照常使用 HTTP 的請求方法、Cookie 以及 HTTP 報文等等。
HTTP 2.0 能夠說是 SPDY 的升級版(實際上是基於 SPDY 設計的),但HTTP 2.0和 SPDY 仍是存在一些不一樣的。主要有如下兩點:
下面就簡單的介紹一下 HTTP 2.0 新增的功能。因爲HTTP 2.0 設計到的東西太多了,以後我會一篇文章單獨講講 HTTP 2.0。
二進制分幀層:HTTP 2.0 性能加強的核心就是新增的二進制分幀層,HTTP 1.x是以換行符做爲純文本的分隔符,而 HTTP 2.0 把全部傳輸的信息分割成更小的消息和幀,並對它們採用二進制的格式編碼。
多向請求和響應:HTTP 2.0 中心的二進制分幀層,將 HTTP 消息分解成獨立的幀,交錯發送。而後在另外一個端根據流標識符和頭部把它們從新組裝。解決了 HTTP 1.x的隊首阻塞問題。
請求優先級:把 HTTP 消息分解成多個獨立的幀後,就能夠經過優化這些幀的交錯和傳輸順序進一步性能優化。
服務器推送:服務器能夠對一個客戶端請求發送多個響應。服務器還能夠向客戶端推送資源並且無需客戶端明確的請求。
頭部壓縮:在 HTTP 2.0 中,使用了 HPACK(HTTP2頭部壓縮算法)壓縮格式對傳輸的頭部進行編碼,減小了頭部的大小。並在兩端維護了索引表,用於記錄出現過的頭部,以後在傳輸過程當中就能夠傳輸已經記錄過的頭部健名,對端收到數據後就能夠經過鍵名找到對應的值。
若是想要了解更多 HTTP2.0 的知識能夠看看《Web性能權威指南》這本書,裏面講得挺詳細的。
網絡架構模型除了TCP/IP模型以外,還有OSI模型。OSI模型其實是多了三層。
也就是上面所說的多加了 SSL 和 SPDY 這兩個協議(都處於應用層)。
而數據鏈路層細分的話有兩層:
前面也說到,HTTP 是無狀態的協議,它不會對以前發送過的請求和響應的狀態進行管理。假設,客戶端的用戶發送一個請求,服務器端收到請求後想知道這個請求是哪一個傢伙發過來的,那麼就要有一個狀態進行管理。而Cookie
正是解決這類問題而出現。
從服務器端返回的響應頭信息中有一個Set-Cookie
的字段信息,告訴客戶端保存Cookie
。在下次客戶端向服務器端發送請求時,客戶端會自動在請求頭信息中加入Cookie
的值發送出去。
服務器收到客戶端發送過來的Cookie
以後,會檢查究竟是從哪一個客戶端發送過的請求,而後對比服務器上的記錄,最後獲得了以前的狀態信息。
Set-Cookie
是屬於響應頭中的一個字段,它包含如下的值。
NAME=VALUE
: Cookie
的名稱和值。expires=DATE
: Cookie
的有效期。path=PATH
: 把服務器上的文件目錄做爲Cookie
的使用對象,若是沒有設置,默認是文檔所在的文件目錄。domain=域名
: 做爲Cookie
適用對象的域名,若是沒有設置,默認是建立Cookie
的服務器的域名。Secure
: 只有在 HTTPS 時纔會發送Cookie
。HttpOnly
: JavaScript 不能訪問Cookie
。主要是爲了防止跨站腳本攻擊時Cookie
的信息竊取。Cookie
是請求頭中的一個字段,它包含服務器經過Set-Cookie
頭部設置並存到客戶端的值。若是接收多個Cookie
時,能夠以多個Cookie
形式發送回去。
以上是我一個多月在學 HTTP 相關書籍作的一些筆記。哪裏有不對的地方,請各位大佬多多指點!固然文章對你有所幫助,歡迎點贊加關注哦!