http1.1科普

由於工做碰到了一些疑惑因此看了火狐的http文檔, 簡單地看, 簡單地總結了一下, 本文只介紹http1.1的概念, 不介紹具體讓人心煩的細節(配置和行爲).css

什麼是http

概念

全稱是超文本傳輸協議. 何爲超文本? 超文本就是文本(文本不必定是超文本).html

http的本體是文本. 而且http2以前的版本(包含如今正在用的1.1)都是人類可讀的文本.web

再說一下什麼是協議? 協議就是雙方約定一些東西, 使用的時候你們都遵守規則執行.canvas

咱們來類比html, 超文本標記語言. 自己是文本(div, p, img). 放到瀏覽器裏解析的時候就會被畫成一個塊, 一個圖片等. 那麼http也是如此, 普通的人類可讀的文本, 進行了一系列約定, 協議雙方根據一些關鍵詞來執行某些約定的行爲, 即是http了.api

環境

那麼http究竟是在哪裏發生的, http的三個屬性:跨域

高中就學過了osi七層協議, http是最上層的協議, 下面是基於傳輸層的(不只限於tcp/ip).瀏覽器

客戶端指瀏覽器, 服務端指服務器. 順序是瀏覽器的某些動做(好比輸入url並敲回車)觸發http請求, 服務器接到請求返回, 造成了一次完整的http請求. http請求每次都是獨立的, 因此是無狀態協議.緩存

總結

http就是瀏覽器使用傳輸層協議向服務器發出一些文本, 這些文本帶有約定的東西, 服務器根據約定的規則來分析內容並做出響應. 學習http就是學習這些約定.安全

http消息

就像html是div, p, img同樣, http長啥樣, 平時使用瀏覽器的調試工具或是http抓包工具都能看到. (固然都是進行過可視化處理的).服務器

http消息分爲請求(request)消息和響應(response)消息. 即瀏覽器發出請求的消息和服務器響應的消息.

消息組成

request和response的消息組成是同樣的.

  1. start-line: 請求/響應的基本信息.
  2. http header: 請求/響應的頭信息.
  3. 空行: 做爲分隔符.
  4. body: 請求/響應的主體內容.

request和response的每一個部分的消息內容不一樣. 下面介紹每一個部分的具體內容.

request

  1. start-line: 方法(get/post等), 目標(一般是url), 協議版本. 例: GET /background.png HTTP/1.1
  2. header, 用冒號/換行隔開的鍵值對, request和response擁有不一樣的有效header鍵值, 詳見文末連接.
  3. 大多數request的body爲空, 好比get, delete, options方法. 一些須要上傳數據的方法如post, put會有body.

    body有兩種狀況: 單個資源: 此時header要定義content-typecontent-length. 多個資源: 在content-type裏定義boundary, 而後在body中用boundary來分隔多個資源. 例子連接

response

  1. start-line: 協議版本, 狀態碼, 狀態描述. 例: HTTP/1.1 404 Not Found.
  2. header, 同request.
  3. response的body也不是必須的, 與request相似, 也分爲單個資源和多個資源. 多了一個狀況, 不知道文件長度的時候能夠把transfer-encoding設爲chunked.

總結

至此, http已經介紹完了. 我來舉一個簡單的http的例子.

我打開了瀏覽器, 敲入yo-cwj.com. 瀏覽器發出了http request.

GET https://yo-cwj.com HTTP/1.1
Host: yo-cwj.com
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive

這個簡單的get請求沒有body, header都是瀏覽器默認帶上的.

而後收到了回覆:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61 
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

<html>陳文俊的博客</html>

200, ok 表明請求成功, 倒數第二行空行表明header和body的分隔, 具體返回內容是<html>xxx</html>, 瀏覽器得到結果就能夠去渲染頁面啦, 完美.

是的, http就是這麼簡單, http的結構就是start-line, header, body三部分. 而協議複雜的地方大部分就在header了. header有一萬個字段, 每一個字段能研究一年. (因此要搞懂http須要一萬年). 那麼下面的章節簡述一下常常接觸的協議規則.

Cookie

介紹

http是無狀態協議, 但網站的登陸狀態/購物車等是有狀態的, 就要藉助cookie來實現. cookie是儲存在瀏覽器上的信息. 會在向服務器發起請求的時候帶着, 以表明瀏覽器當前的狀態.

cookie原先的做用除了登陸/購物車, 還有儲存用戶主題, 分析用戶行爲等. 但瀏覽器的行爲會將cookie都帶到http請求中, 因此如今推薦使用現代storage api來儲存部分信息.

實現

兩個關鍵點: cookie傳輸是經過http的header, cookie的儲存的地方是瀏覽器.

response header能夠設置cookie:

Set-Cookie: <cookie-name>=<cookie-value>

而後瀏覽器收到set-cookie頭之後會儲存cookie, 在發送請求時把對應的cookie帶在request header的Cookie中, 格式是: k=v; k2=v2:

Cookie: yummy_cookie=choco; tasty_cookie=strawberry

那麼瀏覽器中會有不少cookie, 由於咱們常常同時瀏覽不一樣的網頁. 瀏覽器進行request的時候把全部cookie帶上是不對的, 那麼會帶上哪些cookie呢, 就涉及到cookie的做用範圍.

做用範圍

控制cookie做用範圍的關鍵字是Domain和Path, 若是都沒設置默認行爲是只向當前路由發送cookie, 個人理解是什麼路由接到set-cookie的就只向這個路由發送.

domain和path的語法是Domain=mozilla.org, Path=/docs. domain被設置的時候會向domain的全部子domain發送, 因此但願發送範圍越小就要設置得越細. path相同.

生命週期

cookie的生命週期是瀏覽器關閉, 也能夠在response header裏經過設置expire來改變cookie的過時時間.

xss與csrf

由於瀏覽器經過document.cookie能夠獲取本身的cookie. 經過一些手段發出一些請求並帶上cookie就能夠獲取cookie來作很差的事情. 這也是http的特色: 無狀態. 因此理論上一切請求都是能夠模擬的. (只要獲取了關鍵信息, 任何人均可以在他的電腦上模擬你正在登錄某網上銀行甚至進行操做).

這些操做有: 讓頁面執行一段js, 讓頁面append一個img, src的target是惡意網站. 因此防止xss攻擊只要作到控制用戶可進行的操做或轉移用戶輸入就能夠了.

題外話, 由於js和css和html都是明文的, 因此安全必須經過加密手段來強化.

跨域請求

跨域好像是每隔一段時間都會被問到的問題, 先來定義一下什麼是跨域請求.

定義

違反同源策略的請求就叫跨域. 同源策略一句話就能說完: 協議, 主機, 端口都相同的url是同源url. 強調是相同, 即便httphttps的區別也算跨域. 左邊的連接舉了一些例子, 一看就明白.

那麼從一個頁面向一個非同源的target發起了http請求, 這個請求就是跨域請求了.

觸發對象

那麼什麼狀況下會發起跨域請求呢? 個人印象裏百分之90的狀況是js代碼發起的, 也就是或通過框架包裝的xmlhttprequest. 下面這些都會觸發http請求:

  • js代碼發起的, xmlhttprequest, fetch. 由於fetch存在兼容問題, 基本全部的框架封裝都是經過前者的.
  • web字體. 經過@font-face.
  • webgl texture.
  • canvas用drawImage畫的Image或者Video.
  • css和script標籤.

跨域請求須要作的事情

說了半天什麼狀況是跨域, 那麼爲何要討論跨域呢? 固然是報錯了纔會討論了.

由於安全關係, http是默認阻止跨域請求的, 想要順利地進行跨域請求, 必須在瀏覽器和服務器都進行一些header設置, 來確認此次跨域請求是雙方都認同的. 就像你要刪除社交工具的好友前會進行提示: 你是否要刪除好友xxx.

跨域相關的request和response的header都在左邊的連接裏了, 這裏只提一個做爲例子:

(開始講故事)

個人博客(https://yo-cwj.com)須要加載一... 由於博客託管的服務器對博客大小有限制, 因此我把圖片放在了另一個圖庫(https://picture-cwj.com). (下文就用博客圖庫來表明2個地址).

博客使用了img標籤來請求了圖庫的圖片. 圖庫返回的圖片response header 帶有:

Access-Control-Allow-Origin: https://yo-cwj.com

博客進行請求的request header帶有:

Origin: https://yo-cwj.com

圖庫的response header告訴全部過來的請求: 我只給yo-cwj.com跨域. 博客的request header帶着代表身份的Origin header. 這樣一次不被阻止的跨域就完成了.

(故事完)

故事講完了, 博客是存在的, picture-cwj.com是不存在的. 簡單的2個header就讓瀏覽器放行了跨域請求. 別的header都在故事前貼出來的連接中.

preflight request

強行翻譯: 跨域準備請求.

當跨域請求知足了某些條件之後, 瀏覽器在跨域請求前會發起一次preflight request, 用來確認即將發送的請求是否被容許.

preflight請求的method是options, 以前說的跨域相關的header大部分是和preflight相關的.

下面介紹發起preflight請求的觸發條件:

  1. method不是get, post, head的.
  2. request header 帶有指定字段以外的.
  3. cotent-type頭的值在指定範圍以外的.

只要知足任何一個條件就會發起preflight請求. 具體條件在左邊的連接中.

緩存

關於緩存暫時只作概念介紹, 緩存的控制也都是header控制的.

概念

什麼是緩存? 當同一個請求進行了2次以上, 瀏覽器不真正向瀏覽器發起請求而直接返回以前儲存的結果.

緩存哲學

緩存的好處是: 提升瀏覽器響應速度, 節省服務器帶寬. 由於沒有與服務器真正數據交互, 也得到了指望裏的數據.

緩存的問題也很是明顯, 得到的數據是緩存裏的, 而不是最新的. 因此緩存的關鍵就在於猜想哪些數據是不常常更新的. 猜想什麼類型的數據的更新頻率是多少, 並使用緩存相關的header來控制. 好比某門戶網站的首頁html是不常常更新的, 或者是每小時一更新, 而首頁輪播的圖片是十分鐘更新的.

緩存類型

緩存類型分爲本地緩存和共享緩存.

咱們概念中的, 或者說咱們常用的都是本地緩存.

共享緩存是指ISP對服務器的緩存, 以前據說淘寶怎麼能讓網速更快, 離用戶最近的地方是ISP機房, 因此把淘寶首頁放在ISP機房就好了.

新鮮度檢查

有一種緩存的機制是新鮮度檢查. 以前說的緩存response是: 200 OK (from disk cache). 新鮮度檢查是根據cache-control: max-age=xxx向服務器發起新鮮度檢查. 若是返回結果是304(not modified), 服務器將不返回數據, 使用瀏覽器緩存的數據, 從而節省數據下載時間和帶寬.

參考連接

原文地址

相關文章
相關標籤/搜索