「開位」你所應該知道的HTTP——進階篇

前言

接上篇,本篇將講一些更加深刻理論的內容。ajax

URL的編碼

編碼規範

爲了讓只認識二進制的計算機顯示各類各樣的文字咱們發明了編碼規範,好比常見的GBK、ASCⅡ、Unicode等。編碼規範由三部分組成:字庫表、字符集、編碼方式。數據庫

  • 字庫表:存儲字符圖形的集合(數據庫)。
  • 字符集:字庫表每一個字符對應的地址(通常是數字)。
  • 編碼方式:在內存中表示字符集地址的方式,不一樣編碼方式適用的場景不一樣,使用的內存空間不同。(如Unicode有utf-八、utf-16等編碼方式)

顯示文字的原理就是:一串二進制數據,經過一種「編碼方式」,分割、轉化成「字符集」中的地址,而後在「字庫表」中找到對應的字符圖形數據,輸出設備依據圖形數據顯示出字。
通常編碼與解碼須要相同的編碼規範才能保證正確,雖然也有Unicode兼容ASCⅡ的狀況,但反過來ASCⅡ就沒法編碼和解碼Unicode。segmentfault

「%編碼」規範

背景

HTTP協議規範裏URL是採用ASCⅡ編碼規範,理論上對於採用Unicode編碼的中文等其餘文字是不支持的,因此若是URL中含有非ASCII字符集的字符(以及保留字,好比&),要對其進行編碼,因而有了「%編碼」規範。瀏覽器

RFC3986文檔規定,Url中只容許包含英文字母(a-zA-Z)、數字(0-9)、-_.~4個特殊字符以及全部保留字符。

定義

對於URL中屬於ASCⅡ字符集的非保留字不作編碼;對URL中的保留字須要取其ASCⅡ內碼,而後加上「%」前綴進行編碼;對於URL中非ASCⅡ字符須要取其Unicode內碼,而後加上「%」前綴進行編碼。緩存

額外補充

這裏對於「非ASCII字符集的字符」和「保留字」還應該分開說明:安全

  • 「非ASCII字符集的字符」是必定會被編碼的。
  • 「保留字」是在產生歧義的狀況下才須要編碼。好比:http://g.cn/search?a=b這裏的等於號是結構的一部分因此不須要編碼;http://g.cn/search?a=b%3D這裏本來是a=b=,這裏的等於號是參數值,非結構的一部分,因此被編碼成「%3D」。

認證方式

常見的認證方式可分爲4種:BASIC認證(基本認證)、DIGEST認證(摘要認證)、SSL客戶端認證、FormBase認證(基於表單認證)。
前兩種是HTTP協議的標準認證方式,但其實如今已經不多使用;後兩種是由客戶端自行實現,通常SSL客戶端認證用於網銀等高安全環境,FormBase認證是如今最經常使用的認證方式。服務器

BASIC認證

  1. 客戶端發送請求;
  2. 服務器返回401,頭部信息:WWW-Authenticate:Basic realm="xxx",告知須要驗證;
  3. 客戶端將用戶名和密碼以Base64方式編碼後發送,頭部信息:Authorization:Basic <base64串>;
  4. 服務器驗證經過返回200,不然重複②。

示意圖以下:(來自MDN)
HTTPAuth.pngcookie

DIGEST認證

爲了彌補BASIC認證存在的弱點,從HTTP/1.1起就有了DIGEST認證。
DIGEST認證一樣使用質詢/響應的方式,但不會像BASIC認證那樣直接發送明文密碼。過程相似於BASIC認證,示意圖參考上面的。網絡

  1. 客戶端發送請求;
  2. 服務器返回401,頭部信息:WWW-Authenticate:Digest realm="xxx",nonce="<質詢碼>" algorithm=<加密方式>,qop="<保護質量參數>",告知須要驗證;
  3. 客戶端回傳②中的全部信息,並加上username、url、response字段,response就是通過用戶名密碼等信息加密而已的字符串;
  4. 服務器使用相同的加密方法獲得一個字符串,將它與response比較,相同就經過返回200,不然重複②。

SSL客戶端認證

藉由HTTPS的客戶端證書完成認證的方式。憑藉客戶端證書認證,服務器可確認訪問是否來自已登陸的客戶端。session

基於表單的認證

基於表單的認證方式並非在HTTP協議中定義,是由Web應用程序各自實現。好比session-cookie機制。

鏈接管理模型

在HTTP/1.x裏有多種模型:短鏈接,長鏈接,和HTTP流水線。
HTTP流水線並無瀏覽器支持,已經被HTTP/2.0的多路複用特性所取代,這裏就不詳細討論了。

鏈接的長與短只是相對的概念,並無嚴格意義上規定多久纔算長。
討論HTTP的長鏈接與短鏈接,本質是討論TCP鏈接的複用狀況。
由請求報文頭和響應報文頭裏的Connection字段決定,值爲close則爲短鏈接,值爲keep-alive則爲長鏈接,只有服務器與客戶端協商一直纔會進行長鏈接,而且雙方在任意時刻均可以關閉,彼此都不受影響。

短鏈接

HTTP/1.0中,默認使用的是短鏈接。也就是說,瀏覽器和服務器每進行一次HTTP操做,就創建一次TCP鏈接,結束就中斷。
基礎篇(傳送門)中講到HTTP協議在1.0版本以前的一個特色是「無鏈接」,這個也就是短鏈接,只是在後續版本種變成了可選項。
每次請求都通過」這樣的過程如圖:

短鏈接

長鏈接(keep-alive鏈接)

HTTP/1.1起,默認使用長鏈接。也就是說,就是隻創建一次TCP鏈接,屢次資源請求都複用該TCP鏈接,完成後再關閉。
每次請求都通過這樣的過程如圖:

長鏈接

缺陷及變通手段

長鏈接雖然增長了TCP鏈接的複用率,但實質上仍是基於請求/響應模式的,並不能實現及時更新、或是服務器主動向客戶端發送信息。因而就有了「ajax輪詢」、「ajax長輪詢(Long Poll)」這兩種變通手段。

  • ajax輪詢:原理很簡單,就是每隔一段時間就發起一次請求,已到達及時更新的目的。
  • ajax長輪詢:服務器接收到請求後若是沒有更新內容就不響應,客戶端也不作超時處理一直處於等待狀態,一直等到有更新內容,服務器才響應,客戶端接收到響應後又再發起請求,如此往復。

這兩種變通手段都是以消耗大量服務器資源爲代價,所以爲了根本解決這個問題,後來發展出了WebSocket協議,這就是後話了。

Web代理

定義

代理扮演的是「中間人」角色,對於鏈接到它的客戶端來講,它是服務端;對於要鏈接的服務端來講,它是客戶端。它就負責在兩端之間來回傳送HTTP報文。

示意圖以下:

Web代理

應用

  • 抓包調試:好比經常使用的抓包軟件Fiddler和Charles。
  • 匿名訪問:常見的在線代理網站。
  • 過濾器:一些綠色淨網的軟件。

Web網關

定義

網關扮演的是「協議轉換器」角色,能夠做爲某種翻譯器使用,它抽象出了一種可以到達資源的方法。網關是資源和應用程序之間的粘合劑。
代理與網關的區別:代理是轉發相同協議的數據,網關是轉換不一樣協議的數據。

示意圖以下:

Web網關

應用

  • (HTTP/*) 服務器端Web網關
  • (HTTP/HTTPS) 服務器端安全網關
  • (HTTPS/HTTP) 客戶端安全加速器網關
  • 資源網關

內容協商機制

概述

指客戶端和服務器就響應的資源內容進行交涉,而後提供給客戶端最爲合適的資源。內容協商會以響應資源的語言,字符集,編碼方式等做爲判斷的基準。

協商方式及優缺點

  • 客戶端驅動:客戶端發起請求,服務器發送可選項列表,客戶端做出選擇後再發送第二次請求。
    優勢:容易實現,給用戶選擇權。
    缺點:增長訪問次數和延遲。
  • 服務器驅動:服務器檢查客戶端的請求頭部集並決定提供哪一個版本的頁面。(如今最廣泛)
    優勢:比較快,沒有額外開銷,支持優先級匹配。
    缺點:頭部集都不匹配的時候,服務器只能猜想。
  • 透明協商:某個中間設備(一般是緩存代理)表明客戶端進行協商。
    優勢:比較快。
    缺點:須要中間設備,非http標準。

服務器驅動內容協商原理

客戶端經過請求報文頭傳遞告訴服務器支持狀況,而且能夠帶有近似匹配的優先級,服務器迴應的響應報文頭裏進行確認,就完成了內容協商。

  • 相關請求報文頭
字段名 說明文字
Accept 告訴服務器本身能接受的媒體類型
Accept-Language 能接受的語言
Accept-Charset 能接受的字符集(如unicode)
Accept-Encoding 能接受的編碼方式(如utf-8)
  • 相關響應報文頭
字段名 說明文字
Content-Type 對應Accept
Content-Language 對應Accept-Language
Content-Type 對應Accept-Charset
Content-Encoding 對應Accept-Encoding
  • 近似匹配(優先級)
    好比:Accept-Encoding:en;q=0.5,fr;q=0.0,nl;q=1.0,tr;q=0.0
    這裏nl的優先級是1.0,最高優先級,因此會優先返回。

斷點續傳和多線程

概述

經過在報文頭裏兩個參數實現的,客戶端發請求時對應的是Range,服務器響應時對應的是Content-Range 。

請求報文頭

Range用於請求頭中,指定第一個字節的位置和最後一個字節的位置。
格式爲:

Range:(unit=first byte pos) - \[last byte pos\]

響應頭

HTTP/1.1 200 Ok(不使用斷點續傳方式)
HTTP/1.1 206 Partial Content(使用斷點續傳方式)
Content-Range用於響應頭中,在發出帶Range的請求後,服務器會在Content-Range頭部返回當前接受的範圍和文件總大小。
格式爲:

Content-Range:bytes(unit first byte pos) - \[last byte pos\]/\[entity length\](文件總大小)

例子

  1. 客戶端下載一個1024K的文件 已經下載了其中512K;
  2. 網絡中斷,客戶端請求續傳 所以須要在HTTP頭申明本次須要續傳的片斷「Range:bytes=512000- 」這個頭通知服務端從文件的512K位置開始傳輸文件;
  3. 服務端收到斷點續傳請求,從文件的512K位置開始傳輸,而且在HTTP頭中增長「Content-Range:bytes 512000- /1024000」而且此時服務返回的HTTP狀態碼應該206,而不是200。

關於多線程

斷點續傳是被動的增量下載,多線程是主動的分片下載,但使用都是Range模式。

相關文章
相關標籤/搜索