深入淺出HTTP

木可大大發表於2018-06-09

我們知道目前很多應用系統中的內容傳輸協議採用的HTTP協議,因此不管你是前端人員、後端人員、運維人員,甚至是管理人員,都需要掌握HTTP知識!!

HTTP發展歷史

  • HTTP/0.9

該版本只有一個命令GET;沒有HEADER等描述資料的資訊; 伺服器傳送完畢,就關閉TCP連線。

  • HTTP/1.0

該版本增加了很多命令;增加status code 和header;多字符集支援、多部分傳送、許可權、快取等。

HTTP/1.1

該版本增加了持久連線Pipeline,增加host和其他一些命令。持久連線會在HTTP特性中介紹;如果沒有pipeline,那麼Web伺服器就需要序列處理請求,而有了pipeline,Web伺服器就並行處理請求;而增加host實現了一臺物理裝置可以執行多個web服務。

  • HTTP/2.0

所有資料以二進位制傳輸,之前版本使用字串進行傳輸;同一個連線 裡面傳送多個請求不再需要按照順序來;頭資訊壓縮以及推送等提高效率的功能。

HTTP三次握手

image.png

為什麼要三次握手?因為網路是有可能延遲的,當客戶端沒有收到服務端的確認包,如果沒有第三次握手,那麼服務端不知道上次傳輸是不是被客戶端正常接收了,如果沒有接收,服務端的這個埠也是開啟的,這就比較浪費資源。

HTTP報文

image

HTTP報文分為請求報文響應報文,請求報文和響應報文分為起始行、首部(header)和主體(body),請求報文的首部包括三部分,分別是HTTP方法、資源目錄和協議,而響應報文的首部包括協議版本、狀態碼和狀態嗎對應的意思,比如200狀態的意思是ok。需要注意的是:HTTP header和HTTP body之間以一行分隔。

  • HTTP方法

HTTP方法定義對資源的操作,常用的有GET、POST等,這就就不詳細展開了。

  • HTTP Code

HTTP Code用於定義伺服器對請求的處理結果,各個區間的code有不用的語義。1xx  表示資訊響應類,表示接收到請求並且繼續處理;2xx 表示成功;3xx 表示重定向;4xx 表示客戶端出錯;5xx 表示伺服器出錯。

HTTP特性

  • 跨域請求

同源策略,也就是說當兩個請求的URL的協議、host和埠都相同的情況下,我們才認為這兩個請求是同域的即同源,而只要協議、host和埠只要有一項是不同的,我們就認為是不同源的,即跨域,例如:

http://www.mukedada.com:80

http://www.mukedada.com:8080

上述兩個請求就是跨域請求。需要注意的是跨域請求不是說瀏覽器限制了發起跨站請求,瀏覽器只是將返回結果攔截下來,最好的例子就是CSRF跨站指令碼攻擊。如果我們想讓瀏覽器放行返回結果,則通過以下方法:

  1. 服務端設定Access-Control-Allow-Origin引數為允許,例如'Access-Control-Allow-Origin' : '*'

  2. <link><img><script>三標籤中的請求是允許跨域的,這也是JSONP的跨域做法。

  • Cache  Control

對於靜態資源,比如說image、js等,它們是不會經常方式變更的,而且它們的容量比較大,如果我們每次訪問都要從伺服器從獲取相應資料,那麼效能就會變得比較差,因此HTTP協議定義一些和快取相關的引數。

可快取性,表示在哪些地方可以快取,比如說客戶端瀏覽器、代理伺服器等,它有三個常用的引數:public、private、no-cache。public 表明響應可以被任何物件快取,包括髮送請求的客戶端瀏覽器、代理伺服器等等;private 表示響應只能被單個使用者快取,不能作為共享快取,即代理伺服器不能快取它;no-cache表明強制所有快取了該響應的快取使用者,在使用已儲存的快取之前,傳送帶驗證器的請求到源始伺服器。

到期,max-age=,設定快取儲存的最大週期,超過這個時間快取就被認為過期。s-maxage= 它的作用域僅在共享快取(比如各個代理)。max-stale= 表明客戶端願意接收一個已過期的資源。

驗證,must-revalidate,快取必須在使用之前驗證舊資源的狀態,並且不可使用過期資源。proxy-revalidate,與must-revalidate作用相同,但它僅適用於共享快取(例如代理),並被私有快取忽略。

其他。no-store,客戶端和代理伺服器不儲存任何快取,而是直接從伺服器獲取內容。no-transform:不得對資源進行轉換或轉變。Content-Encoding, Content-Range, Content-Type等HTTP頭不能由代理修改。例如,非透明代理可以對影象格式進行轉換,以便節省快取空間或者減少緩慢鏈路上的流量。 no-transform指令不允許這樣做。

  • Cookie

服務端通過Set-Cookie將相關資料儲存到瀏覽器中,而這些相關資料就是Cookie,那麼,下次在同域的請求中就會帶上這些Cookie,Cookie是鍵值對,可以設定多個。Cookie中通過max-age和expires設定過期時間,Secure值在https的時候傳送,HttpOnly無法通過document.cookie訪問。具體可以參考Session 和 Cookie

  • 資源驗證

在Cache Control中我們介紹當設定no-cache引數時,表明每次請求都要到伺服器驗證,驗證結果表明可以讀取本地快取才可以從本地讀取快取。只有到資料發生修改時,我們才需要從服務端讀取最新資料,否則從本地讀取快取。此時,判斷資料是否發生修改就變得尤為重要,通常我們採用Last-Modfied和Etag兩個驗證頭來驗證資料是否發生修改。其中Last-Modifed 通常配合If-Modified-Since或者If-UnModified-Since使用,而Etag 通常配合If-Match或者If-Non-Match使用。為了幫助大家理解,我舉一個栗子。假設我們訪問mudedada.com返回頭資訊包含:

Last-Modified:888

Etag:123

下一次訪問mukedada.com的請求頭中就會包含:

If-Modified-Since:888

If-Non-Match:123

伺服器會比較請求頭中的Last-Modified、Etag 和伺服器中的對應值是否相同,如果不相同則重新獲取,否則從本地快取中獲取。

  • 長連線

我們知道一個HTTP需要建立一個TCP連線,完成之後就關閉TCP連線,這個成本比較高(因為建立一個TCP連線需要通過三次握手),所以在HTTP/1.1開始支援長連線,請求頭標識是Connection:keep-alive。如下圖所示,同一個Connection ID表示同一個連線。需要注意的是同一個連線只能是同域請求。

image.png

  • 資料協商

資料協商指的是客戶端向服務端傳送請求時,客戶端會宣告它希望服務端返回個格式是什麼?服務端根據客戶端的宣告來判斷返回什麼要的資料。其中客戶端通過Accept、Accept-Encoding等引數進行設定,而服務端通過Content-Type等引數進行設定。

客戶端相關引數

  1. Accept指定返回資料型別;

  2. Accept-Encoding指定服務端的資料壓縮方式,目前服務端的壓縮演算法有gzip, deflate, br等;

  3. Accept-Language指定返回資料的語言,例如 Accept-Language:  zh-CN,zh;q=0.9,en;q=0.8,其中q表示的是權重,也就是說瀏覽器更希望伺服器返回的是中文;

  4. User-Agent表示瀏覽器的相關資訊,它能區分是移動端瀏覽器還是PC端瀏覽器,從而返回特定的頁面。

服務端相關引數:

  1. Content-Type指的是服務端返回的資料型別;

  2. Content-Encoding對應客戶端的Accept-Encoding,指的是資料壓縮方式;

  3. Content-Language服務端語言。

    image

image