HTTP 火鍋【高階前端必備】

薔薇愛學習發表於2018-10-03

一、網路基礎 TCP | IP

通常使用的網路是在 TCP | IP 協議族的基礎上運作的,而 HTTP 屬於其中的一個子集

  • 協議:通訊,雙方必須基於相同的方法,比如如何探測到通訊目標、由哪一邊先發起通訊、使用哪種語言進行通訊、怎樣結束通訊等規則都需要事先確定。不同的硬體、作業系統之間的通訊等。
  • TCP | IP:是在IP協議的通訊過程中,使用到的協議族的統稱
  • TCP | IP 分層:
    • 應用層:FTP | DNS | HTTP | websocket
    • 傳輸層:提供可靠的位元組流服務,如TCP | UDP
    • 網路層:在眾多的選項中選擇一條傳輸路線,如 IP
    • 資料鏈路層:網路硬體部分,包括控制作業系統、硬體的裝置驅動、網路卡、光纖

1、IP協議

負責把各種資料包傳送給對方

  • IP地址:指明瞭節點被分配到的地址
  • MAC地址:指網路卡所屬的固定地址
    • ARP:是一種用以解析地址的協議,根據通訊方的IP地址就可以反查出對應的MAC地址

2、TCP

採用三次握手準確無誤地將資料送達目標處

  • SYN(synchronize)
  • ACK(acknowledgement)

3、UDP

  • UDP是無連線的
  • TCP保證資料正確性,UDP可能丟包
  • TCP保證資料順序,UDP不保證
  • TCP連線只能是點到點的,UDP支援一對一,一對多,多對一和多對多的互動通訊

4、DNS

提供域名到IP地址之間的解析服務,或逆向從IP地址反查域名的服務

5、URI 和 URL

URI:Uniform Resource Identifier, 統一資源識別符號,用字串標識某一網際網路資源

URL:Uniform Resource Locator,統一資源定位符,表示資源的地點(網際網路上所處的位置)

URL 是 URI 的子集

http://user:pass@www.example.com:80/dir/index.html?uid=1#ch1

協議方案名 + 登入資訊(認證)+ 伺服器地址 + 伺服器埠號 + 帶層次的檔案路徑 + 查詢字串 + 片段識別符號

二、HTTP協議格式

1、HTTP請求協議格式

<request line>          // http請求行,用來說明請求型別(method)、要訪問的資源(request-URI)以及使用的HTTP版本
<headers>               // http請求訊息報頭,說明伺服器要使用的附加資訊
<blank line>            // 回車換行
[<request-body>]        // http請求正文
複製程式碼
POST /index.html HTTP/1.1 # 請求報文
Host: hackr.jp  # 請求首部欄位
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 16
If-Modified_Since:Thu, 12Jul 2012 07:30:00 GMT # 僅返回2012年7月12日7點30分以後更新過的index.html頁面資源,如果未有內容更新,則以304 Not Modified作為響應返回

name=ueno&age=37 # 內容實體
複製程式碼

2、HTTP響應協議格式

<status line>          // http響應狀態行,通過提供一個狀態碼(status code)來說明所請求的資源情況。及原因短語(reason-phrase)
<headers>              // http響應訊息報頭
<blank line>           // 回車換行
[<response-body>]      // http響應正文
複製程式碼
HTTP/1.1 200 OK		# 協議版本 + 狀態碼 + 用以解釋狀態碼的原因短語 
Date: Tue, 10 Jul 2012 06:50:15 GMT # 可選的響應首部欄位
Content-Length: 362
Content-Type: text/html

<html> # 資源實體的主體(entity-body)

複製程式碼

三、HTTP 方法

1、GET

獲取資源。GET提交的資料會在位址列中顯示出來。特定瀏覽器和伺服器對URL長度有限制,例如 IE對URL長度的限制是2083位元組(2K+35)。對於其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決於作業系統的支援。因此對於GET提交時,傳輸資料就會受到URL長度的限制。

2、POST

傳輸實體主體。由於不是通過URL傳值,理論上資料不受限。但實際各個WEB伺服器會規定對post提交資料大小進行限制,Apache、IIS6都有各自的配置。

3、PUT

用於傳輸檔案,由於不帶驗證機制,存在安全性問題。若配合Web應用程式的驗證機制,或架構設計採用REST(REpresentational State Transfer, 表徵狀態轉移)標準的同類Web網站,可能會開放使用PUT方法。

4、HEAD

和GET方法一樣,只是不返回報文主體部分,用於確認URI的有效性及資源更新的日期時間等

5、DELETE

用於刪除檔案,和PUT一樣不帶驗證機制

6、OPTIONS

用來查詢針對請求URI指定的資源支援的方法:Allow: GET, POST, HEAD, OPTIONS

如果不是訪問特定資源而是對伺服器本身發起請求,可以用一個*來代替請求URL

OPTIONS * HTTP/1.1

7、TRACE

讓伺服器將之前的請求通訊環回給客戶端的方法,客戶端通過該方法可以查詢傳送出去的請求是怎樣被加工/篡改的。容易引發XST(Cross-Site Tracing)攻擊

8、CONNECT

要求用隧道協議連線代理,主要使用SSL|TLS把通訊內容加密後經網路隧道傳輸

  • SSL: 安全套接層 Secure Sockets Layer
  • TLS:傳輸層安全 Transport Layer Security
CONNECT 代理伺服器名:埠號 HTTP版本
複製程式碼

四、HTTP 狀態碼

1. 狀態碼類別

  • 1XX: 資訊性狀體碼 接收的請求正在處理
  • 2XX: 成功狀態碼 請求正常處理完畢
  • 3XX: 重定向狀態碼 需要進行附加操作以完成請求
  • 4XX: 客戶端錯誤狀態碼 伺服器無法處理請求
  • 5XX: 伺服器錯誤狀態碼 伺服器處理請求出錯

2. 14種常見狀態碼

當返回301、302、303,幾乎所有的瀏覽器都會把POST改為GET,並刪除請求報文內的主體,之後請求會自動重新傳送

  • 200 OK: 請求被正常處理
  • 204 NO Content: 請求處理成功,但無資源可返回;在只需要從客戶端往伺服器傳送資訊,而對客戶端不需要傳送新資訊內容的情況下使用
  • 206 Partial Content: 成功處理範圍請求
  • 301 Moved Permanently: 永久性重定向,表示請求的資源已被分配了新的URI。當指定資源路徑的最後忘記新增‘/’,就會返回該狀態碼
  • 302 Found:臨時性重定向,表示請求的資源存在另一個URI;當替代303使用時,表示客戶端應當採用GET方法獲取資源
  • 304 NOT Modified: 允許請求訪問資源,但未滿足條件(指請求首部包含If-Match,If-Modified-Since,If-None-Match, If-Range,If-Unmodified-Since),響應不包含任何響應的主體部分。和重定向沒有關係
  • 400 Bad Request: 請求報文中存在語法錯誤,需修改請求內容後再次傳送請求
  • 401 Unauthorized: 表示傳送的請求需要有通過HTTP認證(BASIC認證、DIGEST認證)的認證資訊。響應必須包含一個適用於被請求資源的WWW-Authenticate首部用以質詢(challenge)使用者資訊
  • 403 Forbidden: 不允許訪問那個資源
  • 404 Not Found: 伺服器上沒有請求的資源。也可以在伺服器端拒絕請求且不想說明理由時使用
  • 500 Internal Server Error: 伺服器端在執行請求時發生了錯誤
  • 503 Service Unavailable: 表明伺服器暫時處於超負載或正在進行停機維護,無法處理請求。最好寫入Retry-After首部欄位再返回給客戶端

五、HTTP 首部

若首部欄位重複了,根據瀏覽器內部處理邏輯的不同,結果可能不一致。有些會優先處理第一次出現的首部欄位,有些則會優先處理最後出現的首部欄位。

HTTP 要確保它的報文被正確傳送、識別、提取以及適當處理:

  • 可以被正確地識別(通過Content-Type首部說明媒體格式,Content-Language首部說明語言),以便瀏覽器和其他客戶端能正確處理內容
  • 可以被正確的解包(通過Content-Length首部和Content-Encoding首部)
  • 是最新的(通過實體驗證碼和快取過期控制)
  • 符合使用者的需要(基於Accept系列的內容協商首部)
  • 在網路上可以快速有效地傳輸(通過範圍請求、差異編碼以及其他資料壓縮方法)
  • 完整到達、未被篡改(通過傳輸編碼首部和Content-MD5校驗和首部)

報文是箱子,實體是貨物

1. 通用首部欄位

  • Cache-Control: 控制快取的行為
  • Connection:逐跳首部、連線的管理
  • Date:建立報文的日期時間
  • Pragma:報文指令
  • Trailer:報文末端的首部一覽
  • Transfer-Encoding:指定報文主體的傳輸編碼方式
  • Upgrade:升級為其他協議
  • Via:代理伺服器的相關資訊
  • Warning:錯誤通知

2. 請求首部欄位

  • Accept: 使用者代理可處理的媒體型別
  • Accept-Charset: 優先的字符集
  • Accept-Encoding: 優先的內容編碼
  • Accept-Language: 優先的語言(自然語言)
  • Authorization: Web認證資訊
  • Expect: 期待伺服器的特定行為
  • From: 使用者的電子郵箱地址
  • Host: 請求資源所在伺服器
  • If-Match: 比較實體標記(ETag)
  • If-None-Match: 比較實體標記
  • If-Modified-Since(IMS請求): 比較資源的更新時間
  • If-Unmodified-Since: 比較資源的更新時間
  • If-Range: 資源未更新時傳送實體Byte的範圍請求
  • Max-Forwards: 最大傳輸逐跳數
  • Proxy-Authorization: 代理伺服器要求客戶端的認證資訊
  • Range: 實體的位元組範圍請求
  • Referer: 對請求中URI的原始獲取方
  • TE: 傳輸編碼的優先順序
  • User-Agent: HTTP客戶端程式的資訊

3. 響應首部欄位

  • Accept-Ranges: 是否接受位元組範圍請求
  • Age: 推算資源建立經過時間
  • ETag: 資源的匹配資訊
  • Location: 令客戶端重定向至指定URI
  • Proxy-Authenticate: 代理伺服器對客戶端的認證資訊
  • Retry-After: 對再次發起請求的時機要求
  • Server: HTTP伺服器的安裝資訊
  • Vary: 代理伺服器快取的管理資訊
  • WWW-Authenticate: 伺服器對客戶端的認證資訊
  • Last-Modified: 最後修改日期

4、實體首部欄位

  • Allow: 資源可支援的HTTP方法
  • Content-Encoding: 實體主體適用的編碼方式
  • Content-Language: 實體主體的自然語言
  • Content-Length: 實體主體的大小
    • 對快取代理伺服器尤其重要,如果快取伺服器收到被截尾的報文卻沒有識別出截尾的話,它可能會儲存不完整的內容並多次使用它來提供服務。快取代理伺服器通常不會為沒有顯式Content-Length首部的HTTP主體做快取,以此來減小快取已截尾報文的風險。
    • 持久連線:因為連線是持久的,客戶端無法依賴連線關閉來判斷報文的結束。通過該首部就可以知道報文從何處開始,從何處結束。
    • 如果編碼了,則顯示的是編碼後的主體位元組長度。
  • Content-Location: 替代對應資源的URI
  • Content-MD5: 實體主體的報文摘要
    • 傳送方可以在生成初始的主體時,生成一個資料的校驗和,這樣接收方就可以通過檢查這個校驗和來捕獲所有意外的實體修改
    • 當作雜湊表的關鍵字,用來快速定位文件並消除不必要的重複內容儲存
    • 如果編碼了,針對編碼後的文件
  • Content-Range: 實體主體的位置範圍
  • Content-Type: 實體主體的媒體型別(MIME型別)
    • 主媒體型別/子型別
    • 編碼之前的實體主體型別
    • 支援可選的引數進一步說明內容的型別
  • Expires: 實體主體過期的日期時間
  • Last-Modified: 資源的最後修改日期時間
  • ETag: 這份文件特定例項的唯一驗證碼
  • Cache-Control: 應該如何快取該文件

5、RFC4229 HTTP Header Field Registrations

  • Cookie: 請求首部欄位,伺服器接收到的Cookie資訊
  • Set-Cookie: 響應首部欄位,開始狀態管理所使用的Cookie資訊
    • NAME=VALUE:賦予Cookie的名稱和值
    • expires=DATE: Cookie的有效期
    • path=PATH: 將伺服器上的檔案目錄作為Cookie的適用物件(若不指定則預設為建立Cookie的伺服器的域名)
    • domain=域名: 作為Cookie適用物件的域名(若不指定則預設為建立Cookie的伺服器的域名)
    • Secure: 僅在HTTPS安全通訊時才會傳送Cookie
    • HttpOnly: 加以限制,使Cookie不能被JavaScript指令碼訪問
      • 使用JS的document.cookie無法讀取附加該屬性後的
  • Content-Disposition

6、逐跳首部(Hop-by-hop Header)

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • Trailer
  • TE
  • Transfer-Encoding
  • Upgrade

7、端到端首部(End-to-end Header)

除了8個逐跳首部外,其他所有欄位都屬於端到端首部

8、其他首部欄位:HTTP首部欄位是可以自行擴充的

  • X-Frame-Options:防止點選劫持攻擊
    • DENY: 拒絕
    • SAMEORIGIN:僅同源域名下的頁面匹配時許可
  • X-XSS-Protection:防止跨站指令碼攻擊,用於控制瀏覽器XSS防護機制的開關
    • 0: 將XSS過濾設定成無效狀態
    • 1: 將XSS過濾設定成有效狀態
  • DNT:拒絕個人資訊被收集

六、HTTP 的缺點

  • 通訊使用明文(不加密),內容可能會被竊聽
  • 不驗證通訊方的身份,因此有可能遭遇偽裝
  • 無法證明報文的完整性,所以有可能已遭篡改

七、HTTPS

HTTPS = 資料加密 + 網站認證 + 完整性驗證 + HTTP

  • 通過證照等資訊確認網站的真實性
  • 建立加密的資訊通道
  • 資料內容的完整性

CA中心釋出的數字證照通過對稱加密和非對稱加密對我們網上傳輸的資訊進行加密。埠號:443

  • 對稱加密:加密和解密使用同一個金鑰
  • 非對稱加密:
    • 公鑰加密:發給檢視網站的所有人
    • 私鑰解密:只有網站伺服器自己擁有

八、HTTP 2.0 的優勢

  • 採用二進位制格式傳輸資料,而非 HTTP1.1 的文字格式,二進位制格式在協議的解析和優化擴充上帶來更多的優勢和可能;

  • 對訊息頭採用 HPACK 進行壓縮傳輸,能夠節省訊息頭佔用的網路流量,而 HTTP1.1 每次都會攜帶大量冗餘頭資訊,浪費頻寬,頭壓縮能夠很好的解決該問題;

  • 多路複用,就是多個請求都通過一個 TCP 連線併發完成,HTTP1.1 雖然通過 pipeline 也能併發請求,但是多個請求之間的響應會被阻塞的,所以 pipeline 至今也沒有被普及應用,而 HTTP2.0 做到了真正的併發請求,同時,流還支援優先順序和流量控制;

  • Server Push, 服務端能夠更快的把資源推送給客戶端,例如服務端可以主動把 JS 和 CSS 檔案推送給客戶端,而不需要客戶端解析 HTML; 再傳送這些請求,當客戶端需要的時候,它已經在客戶端了。

九、WebSocket

websocket 是 HTML5 提出的一套補缺 HTTP 連結中不能持久連結的協議。

HTTP協議建立的“長連線”是“偽長連線”,只是靠伺服器不斷迴圈實現了所謂的長連線效果。在連線後的過程中,伺服器都會不停的連結與斷開,資料頭資訊不停重複的傳送,浪費寬頻,資訊交換的效率低下。

websocket伺服器主動推送,只要有資料就推送到請求方。

  • WS使用HTTP來建立連線,但是定義了一系列新的header域,這些域在HTTP中並不會使用。

  • WS的連線不能通過中間人來轉發,它必須是一個直接連線。

  • WS連線建立之後,通訊雙方都可以在任何時刻向另一方傳送資料。

  • WS連線建立之後,資料的傳輸使用幀來傳遞,不再需要Request訊息。

  • WS的資料幀有序

基於 Node.js 編寫的一個 Socket.IO 是一個開源實現WebSocket的庫,它通過node.js實現服務端的同時,也提供了客戶端js庫,socket.io支援事件觸發為基礎進行的雙向資料通訊

十、面試題

Etag 的值是服務端對檔案的索引節、大小和最後修改時間進行 Hash 後得到的

有了 Last-Modified, 為什麼還要用 Etag?

  • 如果在1S之內對一個檔案進行兩次更改,Last-Modified 就會不正確
  • 某些伺服器不能精確的得到檔案的最後修改時間
  • 一些檔案也許會週期性的更改,但是內容並沒有改變(僅僅改變的是修改時間),這個時候我們並不希望客戶端認為這個檔案被修改了,而重新GET
  • 即有時候 Etag 可以彌補 Last-Modified 的判斷缺陷

有了 Etag, 為什麼還要用 Last-Modified?

  • 有時候 Last-Modified 可以彌補 ETag 判斷的缺陷,比如一些圖片等靜態檔案的修改,如果每次掃描內容都生成 ETag 來比較,顯然要比直接比較修改時間慢很多。

相關文章