一文打盡HTTP

一文打盡Http

本篇主要爲學習筆記,涉及到HTTP/一、HTTP/二、CSP、RestfulApi、跨域等等內容。javascript

從輸入url到返回HTTP響應,瀏覽器的處理流程?css

HTTP-1.0

依賴其餘協議

HTTP協議依賴其它協議實現,如IP、TCP、UDP、DNS、ARP協議等html

  • TCP/IP,分層協議前端

    • 應用層:ftp、dns、http
    • 傳輸層:tcp、udp
    • 網絡層:數據包是網絡傳輸的最小數據單位
    • 鏈路層:用來處理鏈接網絡的硬件部分
  • ARP協議,將IP轉爲MAC java

  • DNS協議,將域名轉爲IP ios

HTTP報文依賴上述協議進行傳入,其傳輸過程以下: web

在傳輸過程當中,有一個很重要的的概念,什麼是TCP三次握手? ajax

從更普遍的角度來看,當瀏覽器輸入url後,各種協議如何協同工做? 算法

還有一個很是重要的概念::chrome

  • url是統一資源定位器,如http://b.edu.51cto.com
  • uri統一資源標誌符,如ftp://abc/a.txt

HTTP的應用

HTTP主要用於客戶端和服務端之間的通訊通訊數據轉發服務,重點了解下通訊數據轉發應用:

  • 代理,接受客戶端發送的請求並轉發給服務器,接受服務器的響應並轉發給客戶端

  • 網關,接收客戶端的請求,就像本身擁有資源同樣,對請求進行處理(轉發局域網內其餘服務器的數據,局域通訊的協議能夠不是http)

  • 隧道,相隔甚遠的客戶端和服務器之間進行中轉,並保持雙方通訊鏈接的應用程序

代理的意義:緩存代理(將服務端資源緩存在代理服務器),透明代理(不對報文進行任何加工處理),非透明代理(對報文內容進行處理)

網關的意義:將非HTTP服務轉爲HTTP服務,提升通訊的安全性?

隧道的意義:隧道可按照要求創建一條與其餘服務器的通訊線路,使用SSL等加密手段進行通訊;隧道的目的是確保客戶端可以與服務器進行安全的通訊;隧道自己不會去解析HTTP請求,請求和響應原樣傳輸;隧道會在通訊雙方斷開鏈接時結束。

緩存是指代理服務器或客戶端本地磁盤內保存的資源副本,利用緩存能夠減小對源服務器的訪問,也就節省了通訊流量和時間。緩存能夠設置有效時間,若是資源過時則從新請求。

HTTP特色和缺陷

  • 無狀態

不對請求和響應之間的通訊狀態(如登陸態)保存,不作持久化處理,好處就是簡單!

  • 無鏈接

請求完成後斷開tcp鏈接,好處就是減小服務器CPU和內存消耗

隨着Web愈來愈複雜,用戶期待更好的體驗,如速度更快、保留登陸態等等,因而就須要進行改進。

如何要保留用戶的狀態(如登陸態),因而有了Cookie技術:

TCP的鏈接過程是至關複雜的,須要經歷3次握手才能傳遞數據。能不能節省握手時間,因而就有了持久鏈接技術:

HTTP/1.1開始支持持久化鏈接,且默認爲持久鏈接;持久鏈接使用字段:connection:keep-alive;Chrome爲了進一步提高速度,會爲單個域名開啓6個線程去請求資源。

傳統的HTTP是請求/響應模式的,單個請求必需要等待響應完成後才能繼續其它請求。如何節省請求等待時間,因而就有了管線化技術:

管線化能夠克服同域並行請求限制帶來的阻塞,把全部請求一塊兒發給服務器,服務器按順序響應(依賴於持久鏈接技術)。

HTTP報文

學習HTTP必需要了解報文,透過報文結構能夠了解請求/響應附加的各類信息,如:

  • 實體類型,請求數據的類型multipart/form-data、application/json

  • 獲取部份內容的範圍請求(斷點恢復下載),設定獲取資源範圍,Range: bytes=5001-10000

  • 內容協商,客戶端和服務端就響應的資源內容進行交涉,而後提供給客戶端最爲適合的資源,如中英文界面:Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language

  • 緩存控制信息,如Cache-Control、Expires

HTTP請求報文

HTTP響應報文

HTTP報文結構

HTTP的請求方法: get/post/put/delete/head/option/trace/connect

業務中經常使用Post和Get,他們有什麼區別?

1. get在瀏覽器回退是無害的,而post會再次請求
2. get請求的url地址能夠被收藏,而post不能夠?
3. get請求瀏覽器會主動緩存,而post不會,post須要手動使用localStorage等
4. get只支持URI編碼,而post支持多種編碼形式
5. get請求參數會被完整的保留在瀏覽器歷史記錄中,而post中的參數不會被保留
6. get請求攜帶的數據長度有限制,而post沒有限制
7. get沒有post安全,由於參數直接在url中,因此不能傳遞敏感信息
8. get參數經過url傳遞,而post經過請求體(request Body)
複製代碼

HTTP的狀態碼:

200,請求被服務器正常處理
204,請求成功,可是響應報文不含實體主體部分,收到204響應,瀏覽器頁面不發生更新。【應用:通常在只須要從客戶端往服務器發送信息,而對客戶端不須要發送新信息內容的狀況下使用】
206,客戶端進行範圍請求,服務器成功處理並返回有Content-Range指定範圍的實體內容
301,永久性重定向。表示請求的資源被分配到新的URI上,之後應使用資源如今所指的URI。若是保存了書籤,打開後依就會重定向(瀏覽器記住了重定向地址)【應用:res.location + res.sendStatus 配合使用等價於 res.redirect,重定向】
302,臨時重定向,請求的資源被分配到新的URI上,但願用戶本次使用新的URI訪問(永久重定向時,即便修改重啓了服務端源碼,chrome瀏覽器依舊進行重定向跳轉)
303,同302,可是要求指定客戶端使用get方法請求新的URI
304,客戶端發送附帶條件的請求,若是爲知足條件則返回304,知足則容許訪問
307,與302相同,禁止從post請求變成get請求??
400,請求報文中存在語法錯誤,須要修改請求的內容後再次發送請求。瀏覽器會像200同樣對待該狀態碼?(200如何處理的?)
401,請求須要經過http認證(BASIC認證,DIGEST認證),若是攜帶認證信息依就返回401則表示認證失敗
403,請求訪問的資源被服務器拒絕
404,服務器沒法找到請求的資源,或者服務端拒絕請求且不想說明理由時使用。
500,服務端在執行請求時發生錯誤,可能web應用中存在的bug或臨時故障
503,服務器處於超負載或者正在進行停機維護,沒法處理請求
複製代碼

HTTP首部字段:

首部字段根據類型或緩存行爲進行分類:

通用首部字段、請求首部字段、響應首部字段、實體首部字段 首部字段根據緩存行爲分爲兩中類型,端到端首部字段(請求響應的最終接收目標)、逐跳首部字段(會因經過緩存或代理服務器再也不轉發,在HTTP/1.1後必須配合connection才能使用!)

# 客戶端請求首部
GET / HTTP/1.1
Upgrade: HTTP/1.1
Connection: Upgrade

# 通過代理服務器後發送給Web服務器的首部
GET / HTTP/1.1
複製代碼

通用首部字段

請求首部字段

響應首部字段

實體首部字段

逐跳首部字段

通用首部字段詳細介紹:

  • Cache-Control:控制緩存邏輯

    • public,響應能夠被任何對象緩存(代理服務器、客戶端)
    • private,響應只能被髮起請求的客戶緩存,不能被做爲共享緩存(代理服務器)
    • no-cache,緩存資源,每次必須驗證才能夠被使用
    • no-store,不緩存任何內容
    • no-transform,不得對資源進行轉換或轉變。Content-Encoding、Content-Range、Content-Type等HTTP頭不能由代理修改
    • max-age,設置緩存存儲的最大週期
    • s-maxage,緩存服務器使用,緩存時間
    • max-stale,發起請求攜帶,即便緩存過時,在statle時間內仍是可使用緩存
    • must-revalidate,緩存max-age過時後,必須去服務端獲取新的資源
    • proxy-revalidate,緩存服務器使用,效果同上
  • Connection:管理持久連接,配合逐跳首部字段使用

    • close,代表客戶端或服務器想要關閉該網絡鏈接
    • keep-alive,代表客戶端想要保持該網絡持久鏈接
  • pragma:再也不推薦使用,與cache-control功能基本相同

  • Date:報文建立的日期和事件

  • trailer:待查詢

  • transfer-encoding:逐跳傳輸消息首部,用於指定編碼形式

    • chunked
    • compress
    • deflate
    • gzip
    • identity
  • upgrade:詢問服務器是否支持其餘協議,或者http更高協議??須要配合connection使用??

  • via:追蹤客戶端和服務端之間請求響應報文的傳輸路徑,避免循環請求

  • warning: 報文存在的問題,部分警告碼只能用於緩存代理服務器的響應報文

請求首部字段詳細介紹

從客戶端發出,用於補充請求的附加信息、客戶端信息、對響應內容相關的優先級等

  • Accept,告知服務器,用戶(或代理)可以處理的媒體類型及媒體類型的相對優先級,如Accept: text/plain; 1=0.3, text/html

  • Accept-Charset,告知服務器用戶(或代理)支持的字符集及字符集的相對優先順序,如Accept-Charset:utf-8,iso-8859-1;q=0.5

    Content-Type響應字段返回服務器的選擇,如Content-Type: text/html; charset=utf-8

  • Accept-Encoding,告知服務器用戶(或代理)支持的內容編碼及內容的編碼的優先級順序。如Accept-Encoding:gzip、compress、deflate、identity

    Content-Encoding響應字段返回服務器的選擇,如Content-Encoding: gzip

  • Accept-Language,告知服務器用戶代理可以處理的天然語言集(中文或英文)。如Accept-Language: en-US,en;q=0.5

    Content-Language響應字段返回服務器的選擇,如Content-Language: de-DE

  • Authorization,告知服務器用於驗證用戶身份的憑證,如Authorization: Basic abcdefg

  • Expect: 服務器只有知足此指望條件狀況下才能妥善地處理請求。如Expect:100-continue(客戶端要發送一個體積很大的消息體),等待狀態碼100後再發送消息體?

  • Form,電子郵箱

  • Host,虛擬主機運行在同一個ip上,使用此字段加以區分

  • If-Match,條件請求,服務端接受附帶條件的請求後,只有判斷爲真時才執行請求。(if-match,資源ETag值相同)

  • if-Modified-Since,資源更新時間;;;;若是資源未更新返回狀態碼304Not Modified

  • if-None-Match,與if-Match相反

  • If-Range,若字段值與Etag或更新日期匹配,則繼續做爲範圍請求。配合Range字段一塊兒使用。若不一致則忽略返回,返回所有資源。(節約請求次數???)

  • Max-Forwards,設定請求被代理服務器轉發的次數。

  • proxy-Authorization

  • Range,指定獲取資源的範圍,如Range: bytes=5001-10000(成功返回206,失敗返回200+所有資源)

  • Referer,告訴服務器請求的原始資源的URI,經常使用於防盜鏈。

  • TE,告訴服務端客戶端可以響應的傳輸編碼方式及相對優先級,與Accept-Encoding功能很相像?

  • userAgent:將建立請求的瀏覽器和用戶代理名稱等信息傳達給服務器。

響應首部字段詳細介紹:

用於補充響應的附加信息、服務端信息、以及對客戶端的附加要求等信息。

  • Accept-Ranges: bytes可處理範圍請求,none不可處理範圍請求

  • Age,源服務器在多久前建立了響應,字段值爲秒。???

  • Etag,實體標識,uri相同時,藉助etag區分文件

    • 強Etag,不論實體發生多麼細微的變化都會改變其值。如Etag:usagi-1234
    • 弱Etag,用於提示資源是否相同。只有資源發生根本改變,產生差別時纔會改變ETag值。
  • Location,將響應接收方引導到某個與請求URI位置不一樣的資源,基本上配合3XX:Redirection,進行重定向,。

  • Proxy-Authenticate,

  • Retry-After,高知客戶端應該在多久以後再次發送請求。配合狀態碼503Service Unavailable。或3XX Redirect一塊兒使用。能夠指定具體日期,或者建立響應後的秒數

  • Server,告知客戶端服務器上安裝的http服務程序信息,如Server:Apache/2.2.6(Unix) PHP/5.2.5

  • Vary

  • www-Authenticate

實體首部字段詳細介紹

請求報文和響應報文中實體部分使用的首部,用於補充內容的更新時間等與實體相關的信息

  • Allow,GET/HEAD,通知客戶端,只接受指定方法
  • Content-Encoding:端到端首部字段(與transfer-encoding功能相似),實體內容編碼方式。
  • Content-Language:zh-CN,通知客戶端,實體所使用的天然語言(中文或英文)
  • Content-Length:實體主體部分的大小
  • Content-Location,
  • Content-MD5,報文主體生成MD5編碼,服務端使用相同算法計算,進行比較。(可是沒法意識到報文主體是否被篡改????)【主要用於判斷報文主體的有效性?】
  • Content-Range,針對範圍請求,返回響應時使用Content-Range指明實體的範圍
  • Content-Type,實體主體內對象的媒體類型,如text/html;application/x-www-form-urlencoded
  • Exprires,指明資源失效的日期。(若是同時又max-age字段,則優先處理max-age字段。)
  • last-Modified,指明資源最終修改的時間。

Cookie字段詳細介紹

set-cookie,服務端下發cookie,set-Cookie:status=enable; expires=Tue, 05 Jul 2011 07:26:31 GMT path=/ domain=.hack.jp secure httponly

  • expires,max-age指定cookie有效期
  • path指定cookie的範圍
  • domain指定域名
  • secure指定https連接才發送cookie
  • httponly指定js沒法得到cookie
  • cookie。服務端請求時候自動攜帶cookie
  • 關閉瀏覽器後,未設置時間的cookie自動清除【會話時效】

http認證機制

認證信息的方式一般有:密碼,動態令牌、數字證書、生物認證、IC卡。HTTP如何認證?

HTTP使用表單攜帶密碼進行認證,藉助cookie、session、jwt等方式管理狀態,具體流程以下:

注:服務端如何安全保存密碼?密碼加鹽添加額外信息,再使用散列函數進行處理,最後存儲散列值!

  • cookie技術

存放在客戶端,主要由服務器下發set-cookie。cookie符合同源策略,每次請求時會自動攜帶。cookie有大小限制,單個限制3kb。

  • session

存放在服務端,用於記錄用戶狀態。依賴於cookie技術(下發sessionIdcookie)。當訪客較多時,佔用服務端性能。

  • JWT

session-cookie技術,session保存在服務端安全,能夠手動清除session,兼容性好。可是在跨域場景下不夠友好,基於cookie技術很容易被CRSF(跨站請求僞造)。

JWT技術,服務端將信息進行加密(還會設置驗籤)下發給客戶端,客戶端存儲在sessionStorage或localStorage中,每次請求中Authorization字段攜帶jwt信息,服務端驗證經過後返回信息。

HTTPS安全性

理解網絡安全:

  • 網絡信息安全與保密的三個要素:保密性、完整性、可用性
  • 對稱加密:用同一個密鑰進行加密和解密
  • 非對稱加密:加解密使用一對惟一性密鑰(公鑰和私鑰)。公鑰加密、私鑰解密稱爲解密;私鑰加密、公鑰解密稱爲簽名和驗證簽名。(rsa,dsa)
  • 單向加密:不可逆的加密,定長輸出。(md五、sha1,sha256)

HTTP的缺點

  • 通訊使用明文,內容可能被監聽;
  • 不驗證通訊方的身份,可能遭遇假裝攻擊;
  • 沒法證實報文完整性,有可能被篡改。

HTTPS藉助SSL或TLS協議,加密HTTP通訊內容,基於證書服務實現身份認證,即http + 加密 + 認證 + 完整性保護 === https,可是,加密和解密消耗計算資源,也會使通訊變慢。

https加密原理

共享密鑰加密:

公私鑰加密:

混合加密機制:

引入證書證實公鑰是正確的:

瞭解了加解密原理,瞭解了證書原理,HTTPS創建通訊的全過程:

AJAX等技術

傳統的HTTP通訊過程,每次請求時都返回整個頁面,沒法作到局部更新:

AJAX技術,使用js執行異步網路請求,能夠實現局部更新:

Comet技術,收到請求後服務端會等待內容更新,再返回響應,實現了服務端推送,可是爲了維持連接,須要消耗更多的資源:

輪詢效率低,因此有了全雙工通訊websocket,其最經常使用場景---聊天軟件

前端安全

瞭解瀏覽器的CSP/同源策略,瞭解常見的攻擊方式,保證業務安全。

前端主要攻擊形式:XSS跨站腳本攻擊、SQL注入、CSRF跨站請求僞造。

Content-Security-Policy

內容安全策略,用於減弱並削弱某些特定類型攻擊,包括跨站腳本和數據注入攻擊。CSP向後兼容,網頁默認會使用同源策略確保安全。

如何使用:

一是能夠由服務端下發,而是能夠經過meta設置<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

防護原理:

指定瀏覽器可執行js的來源,避免xss腳本攻擊;指定資源加載域;指定資源加載的協議,如強制HTTPS協議。

經常使用字段`default-src/script-src/style-src/img-src/self

跨域及同源策略

同源策略限制了從同一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互,同源的定義是:協議/域名/端口 相同。

不符合同源策略的請求,如何實現實現通訊呢?即如何跨域?

跨域限制是瀏覽器的行爲,能夠給chrome瀏覽器設置--disable-web-security --user-data-dir=C:\MyChromeDevUserData,便可輕鬆實現跨域,設置教程:www.cnblogs.com/laden666666…

除了上述hack方法,還有以下正規的途徑。

CORS跨域資源共享

Ajax符合同源策略,如何突破ajax跨域限制?即CORS方法!

  • 簡單請求的條件

    • 請求方法只能是:HEAD、GET、POST
    • Header字段是能有:Accept、Accept-Language、Content-Language、Content-Type(application/x-www-form-urlencodedmultipart/form-datatext/plain)
  • cors請求流程

    • 請求攜帶Origin字段,說明本次請求來自哪一個源(協議+域名+端口)
    • 響應會包含字段Access-Control-Allow-Origin等
  • 預請求

    • 對於非簡單請求,在正式請求以前會預請求

    • 使用OPTIONS方法,詢問瀏覽器是否容許跨源請求

      OPTIONS /cors HTTP/1.1
      Origin: http://api.bob.com
      Access-Control-Request-Method: PUT
      Access-Control-Request-Headers: X-Custom-Header
      複製代碼

jsonp跨域請求

Cors比jsonp更強大,支持全部請求類型;而jsonp只支持get請求,可是jsonp支持老版本瀏覽器,兼容性更好。JSOP的實現代碼以下:

function jsonp(src, onsuccess, onerror) {
    const callback = 'callback_' + Math.random().toString().substr(1, 6)
    window[callback] = function () {
        onsuccess && onsuccess.apply(null, arguments)
    }

    const script = document.createElement('script')
    script.setAttribute("type","text/javascript")
    script.setAttribute('src', `${src}?jsonp=${callback}`)
    script.async = true
    script.onload = script.onreadstatechange = function () {
        if (!script.readystate && /complete|loaded/.test(script.readystate)) {
            script.onload = script.onreadstatechange = null
            if (script.parentNode) {
                script.parentNode.removeChild(script)
            }
            window[callback] = null
        }
    }
    script.onerror = function () {
        onerror && onerror()
    }

    document.appendChild(script)
}
複製代碼

WebSocket

Webscoket全雙工通訊,事件驅動響應,支持跨域通訊。

// 客戶端
let ws = new WebSocket('ws://localhost:3000/')
ws.onopen = function() {
    ws.send('Hello!');
}
ws.onmessage = function(msg) {
    console.log('get Message:', msg.data); 
}

// 服務端
const WebSocket = require('ws')
const wss = new WebSocket.Server({port: 3000})
wss.on('connection', function(ws) {
  ws.on('message', function (message) {
    ws.send(`${message}-server`, err => {
      if (err) {
        console.log(err)
      }
    })
  })
})
複製代碼

XSS--跨站腳本攻擊

以下圖演示的攻擊原理,上圖爲正常渲染,下圖爲攻擊方式:

XSS腳本危害很是大,嵌入了可執行腳本能夠作不少事情:

  • 獲取頁面數據
  • 獲取cookies
  • 劫持前端邏輯
  • 發送請求

XSS根據存儲方式分爲:

  • 反射型:url參數直接注入
  • 存儲型:儲存到DB後讀取注入

XSS的攻擊途徑:

  • 節點內容攻擊:模版代碼<p v-html="from"></p>,攻擊載荷http://localhost:8080/?from=%3Cscript%3Ealert(1)%3C/script%3E
  • HTML屬性攻擊:模版代碼<img src="avatar"/>,攻擊載荷http://localhost:8080/?avatar=1%22onerror=%22alert(1)%22
  • 富文本:展現富文本內容<p>hello world!</p><script>alert(1)</script>

針對上述攻擊方式,如何有效進行防禦?

  • 防護節點內容和屬性:瀏覽器自帶xss防護X-XSS-Protection,針對於反射型xss
  • 防護節點內容:<>等特殊符號轉義爲實體字符集
function SaferHTML(templateData) {
    let s = templateData[0];
    for (let i = 1; i < arguments.length; i++) {
      let arg = String(arguments[i]);
  
      // Escape special characters in the substitution.
      s += arg.replace(/&/g, "&amp;")
              .replace(/</g, "&lt;")
              .replace(/>/g, "&gt;")
              .replace(/"/g, "&quot;")
              .replace(/'/g, '&#39;')
              .replace(/ /g, '&#160;');
  
      // Don't escape special characters in the template.
      s += templateData[i];
    }
    return s;
  }
複製代碼
  • 防護富文本:黑名單過濾,過濾掉onerror等屬性;白名單保留部分標籤和屬性,定義[{img: ['src']}]

CSRF--跨站請求僞造

用戶登陸A網站,在B網站誘導用戶發起對A網站的請求(第3步),因爲同源策略該攻擊請求自動攜帶了cookie。

跨站請求僞造**利用用戶登陸態完成業務請求*,能夠進行盜取用戶資金、冒充用戶發帖等行爲

針對上述攻擊特徵,如何進行有效防禦?

  • Cookie設置same-site屬性,同站點才自動攜帶cookie
  • 在用戶前端頁面加入驗證信息,如驗證碼、token<input name="csrf" value="xxx" hidden/>形式,驗證請求來源
  • 驗證請求的referer地址,禁止來自第三方網站的請求

點擊劫持

B網站使用iframe將A網站嵌入,誘導用戶點擊A網站產生交互。用戶不知情,可是親手操做。

如何防禦點擊劫持?

  • 使用JStop.location === window.location,禁止內嵌
  • 設置X-FRAME-OPTIONS,禁止內嵌
  • 驗證碼等其餘輔助手段

其餘安全

針對HTTP傳輸竊聽等安全問題,使用更安全的協議HTTPS

Cookie經常使用於保留登陸態,如何針保證cookie安全?

  • 設置http-only禁止JS操做cookie
  • 設置same-site避免跨站請求僞造

密碼用於證實「你是你」,嚴禁密碼明文存儲!

  • 密碼泄露渠道

    • 服務器被入侵
    • 通信被竊聽,http竊聽
    • 內部人員泄露數據
    • 撞庫
  • 哈希算法

    使用複雜密碼對抗彩虹表,md5(sha1(md5(id+ab83kd+原始密碼+81kdso+鹽+1lso;$2))) 變化次數越多,密碼越複雜,越安全。

  • 傳輸的安全性

    • https傳輸
    • 登陸頻率限制
    • 前端加密意義有限
  • 生物特徵密碼

    • 私密性-容易泄露
    • 安全性-碰撞
    • 惟一性,終身惟一,沒法修改

還有文件上傳安全?

避免上傳的文件被當成程序進行執行!

HTTP2

基於RestfulAPi,HTTP/1.1引入「資源」概念,將HTTP從一種面向文檔的協議完全轉變爲一種面向資源的協議。而HTTP-2的影響,主要在於更快的速度、更安全的傳輸。

http2如何更快?

分析HTTP請求響應流程圖,尋找關鍵性能指標:

通過分析,得出關鍵性能指標:

  • 網絡指標:延遲、帶寬、DNS查詢、創建鏈接時間(TCP三次握手)、TLS協商時間(HTTPS鏈接)

  • 服務器的優化:首字節時間(TTFB,瀏覽器從發起請求到接受到第一個字節之間的耗時)、內容下載時間(請求資源隨後到達時間TTLB)、開始渲染時間(屏幕何時開始顯示內容,即用戶看到空白頁面的時長)、文檔加載完成時間(瀏覽器認爲頁面加載完畢的時間)

  • 網絡的趨勢:更多的字節(web內容增加)、更多的資源(引用的資源愈來愈多)、更高的複雜度(web頁面渲染複雜度)、更多的域名、更多的TCP連接

HTTP/1缺陷和優化

缺陷:

  • 隊頭阻塞:持久鏈接時,chrome對單個域名開啓6個鏈接,按順序依次獲取資源。若是獲取某個資源發生意外,會影響網絡傳輸和web頁面渲染。
  • 低效TCP利用:TCP慢啓動(擁塞控制),須要屢次數據交互才能實現最大致量數據包傳輸,TCP協議保證了鏈接正常工做,可是不能保證性能最優。
  • 臃腫的消息首部:資源多請求多,每次都會攜帶消息首部,消耗資源。
  • 受限制的優先級:HTTP/1主要爲請求響應機制,瀏覽器會先請求優先級較高資源,而優先級低的資源須要等待高優先級請求並處理完成,中間的空檔時間浪費了。
  • 可任意選擇數據壓縮格式,非強制壓縮方式
  • 不可控性:第三方資源若是發生問題,會延遲阻塞頁面渲染。

優化:

  • DNS查詢優化:限制域名數量(合理的拆分域名);dns預解析:<link rel="dns-prefetch" href="//ajax.googlepis.com">
  • 優化TCP鏈接:preconnect指令:<link rel="preconnect" href="" crossorigin>
  • 避免重定向:重定向可能致使數百毫秒的延遲,請求在雲端中重定向
  • 緩存:使用客戶端緩存(cache-control控制緩存);CDN緩存。
  • 壓縮:代碼壓縮(空格等);傳輸壓縮gzip等。
  • 避免js阻塞頁面:設置async、defeer屬性;放在處。
  • 圖片優化:圖片壓縮;響應式圖片

HTTP/2反模式

部分針對於HTTP/1的優化,在HTTP/2下多是反優化:

  • HTTP/2的請求再也不是阻塞式的,多請求能夠並行處理,就性能而言精靈圖失去了意義
  • 不須要進行域名拆分,HTTP/2支持多路複用(HTTP/1爲每一個域名開啓6個請求進程,合理的拆分有利於更多請求能力;可是HTTP/2只開啓一個鏈接,請求多路複用)
  • 圖片等再也不須要單獨設置域名,節省DNS、TCP的鏈接時間(HTTP/1請求會攜帶cookie,所以圖片等靜態資源採用不用的域名避免攜帶無用cookie;可是在HTTP/2中,首部進行了壓縮,同時客戶端和服務端會保留「首部歷史」,在請求圖片時再也不每次攜帶cookie。)

HTTP/2協議介紹

HTTP/2協議在設計時考慮考兼容性,任何不支持HTTP/2的客戶端都會簡單回退到HTTP/1,通常來講HTTP/2就意味HTTPS,默認開啓443端口。

HTTP/2協議大體分爲兩個部分:分幀層,即h2多路複用能力;數據層,即HTTP數據部分。主要特色:二進制協議、首部壓縮、多路複用、加密傳輸。

  • 鏈接:初始化一個TCP鏈接,幀和流在上面傳輸

  • 幀:請求和響應能夠交錯甚至多路複用,有利於解決隊頭阻塞

  • 流:h2連接上獨立的、雙向的幀序列交換。客戶端發起請求,會開啓一個流,服務器在這個流上回復。因爲有分幀存在,多個請求和響應能夠交錯,而不會阻塞。

  • 消息:流是用來傳輸一對請求/響應消息的,h2消息包含HEADERS幀和DATA幀

  • 優先級:h2會分析依賴關係,優先請求最重要的資源

  • 服務端推送:提高單個對象性能的最佳方式,就是在它被用到以前就放到瀏覽器的緩存裏

  • 首部壓縮:hpack壓縮算法

影響h2性能的要素?

h2的設計目標是提高性能,可是HTTP/2的速度也有命脈:

  • 延遲:h2受影響的增加低於h1
  • 丟包:丟包擁塞致使TCP擁塞窗口波動,h2只開啓一個tcp連接,所受影響很大(丟包是h2的命門)。

RestfulApi

RestfulApi內容源自這篇文章:imweb.io/topic/57075…

RestFulApi的主要意義在於將HTTP從面向文檔 轉爲 面向資源

1. 每個URI表明一種資源
2. 客戶端和服務器之間,傳遞這種資源的某種表現層(客戶端想要操做服務器,必須經過某種手段,讓服務器發生「狀態轉化」,這種轉化是創建在變現層之上的,即Representational State Transfer---RESTfulApi)
3. 客戶端經過四個HTTP動詞,對服務器資源進行操做,實現「變現層狀態轉化」
複製代碼
  • 狀態碼

    • 使用http狀態碼(http狀態碼預約義了錯誤信息)
    • 自定義,參考微信(0爲成功,其他爲錯誤代碼):mp.weixin.qq.com/wiki?t=reso…
  • 接口要求

    • 冪等性:對同一個接口,使用一樣的條件,一次請求和重複的屢次請求對系統資源的影響是一致的。
    • 安全性:如何保證接口的安全性?
  • 實戰

    • 版本號參考以下形式:http://api.example.com/v1/zoos
    • 操做方法:GET獲取資源、POST新建資源、PUT更新資源(完整)、DELETE刪除資源、PATCH更新資源

GraphQL

待學習補充。

緩存

緩存命中流程圖:

資源提示與指令

在資源加載方面瀏覽器提供了些新的方案---資源提示與指令:

  • preload:不一樣於瀏覽器預加載,preload能夠預加載css和js中定義的資源,並容許決定什麼時候應用每一個資源;preload不會阻塞window的onload事件。

    <link rel="preload">

  • prefetch:低優先級的資源提示,容許瀏覽器在後臺(空閒時)獲取未來可能用獲得的資源,而且將他們存儲在瀏覽器的緩存中。

    • <link rel="prefetch" href="pic.png">
    • <link re="dns-prefetch" href="//baidu.com">
  • prerendering:相似於prefetch,prerendering在後臺渲染了整個頁面 <link rel="prerender" href="https://www.baidu.com">

  • preconnect:預先瀏覽器在一個http請求正式發給服務器前預先執行一些操做,包括DNS解析、TLS協商、TCP握手,這消除了往返延遲併爲用戶節省了時間。<link rel="preconnect" href="//baidu.com" crossorigin>

資源提示與指令

Ajax請求類型

先後端使用ajax進行數據傳輸,經過Content-type定義數據格式,經常使用的方式以下:

  1. application/x-www-form-urlencoded

元素標籤form的默認編碼形式,數據須要轉爲name=jj&age=17形式傳輸,推薦第三方庫qs進行數據處理。

// application/www-form-urlencode
function ajaxBy1 () {
    let xhr = new XMLHttpRequest()
    xhr.open('POST', 'http://localhost')
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
    xhr.send('name=jj&age=17')
}
複製代碼
  1. application/form-data

元素標籤form能夠修改enctype=application/form-data,也能夠new FormData()新建FormData實例對象,這種方案還支持文件上傳。

// multipart/form-data
function ajaxBy2 () {
    const data = new FormData()
    data.append('name', 'jj')
    data.append('age', 18)

    let xhr = new XMLHttpRequest()
    xhr.open('POST', 'http://localhost')
    xhr.send(data)
}
複製代碼
  1. application/json

若是數據結構比較複雜,推薦使用application/json方式,能夠直接傳輸json對象。

// application/json
function ajaxBy3 () {
    const data = {
        "name": "jj",
        "age": 18
    }
    let xhr = new XMLHttpRequest()
    xhr.open('POST', 'http://localhost:5501')
    xhr.setRequestHeader("Content-type","application/json")
    xhr.send(JSON.stringify(data))
}

// 斷點續傳https://cloud.tencent.com/developer/article/1326932
複製代碼

若是在業務中使用如axios的庫進行請求,又該如何實現呢?

推薦

本文大多內容來自下面的資源,推薦閱讀。不知道截圖是否侵權,若有侵權聯繫刪除。

  1. 圖書:《圖解HTTP》
  2. Web先後端漏洞分析與防護
相關文章
相關標籤/搜索