HTTP 【值得你看個究竟】

Talent、茂ღ茂發表於2020-09-18

我是一名程式設計師,我的主要程式語言是 Python,我更是一名 Web 開發人員,所以我必須要了解 HTTP,所以本篇文章就來帶你從 HTTP 入門到進階,看完讓你有一種恍然大悟、醍醐灌頂的感覺。

HTTP


 

認識 HTTP

首先你聽的最多的應該就是 HTTP 是一種 超文字傳輸協議(Hypertext Transfer Protocol),這你一定能說出來,但是這樣還不夠,假如你是大廠面試官,這不可能是他想要的最終結果,我們在面試的時候往往把自己知道的儘可能多的說出來,才有和麵試官談價錢的資本。那麼什麼是超文字傳輸協議?

超文字傳輸協議可以進行文字分割:超文字(Hypertext)傳輸(Transfer)協議(Protocol),它們之間的關係如下

HTTP

按照範圍的大小 協議 > 傳輸 > 超文字。下面就分別對這三個名次做一個解釋。

什麼是超文字
在網際網路早期的時候,我們輸入的資訊只能儲存在本地,無法和其他電腦進行互動。我們儲存的資訊通常都以文字即簡單字元的形式存在,文字是一種能夠被計算機解析的有意義的二進位制資料包。而隨著網際網路的高速發展,兩臺電腦之間能夠進行資料的傳輸後,人們不滿足只能在兩臺電腦之間傳輸文字,還想要傳輸圖片、音訊、視訊,甚至點選文字或圖片能夠進行超連結的跳轉,那麼文字的語義就被擴大了,這種語義擴大後的文字就被稱為超文字(Hypertext)

什麼是傳輸
那麼我們上面說到,兩臺計算機之間會形成互聯關係進行通訊,我們儲存的超文字會被解析成為二進位制資料包,由傳輸載體(例如同軸電纜,電話線,光纜)負責把二進位制資料包由計算機終端傳輸到另一個終端的過程 稱為傳輸(transfer)

通常我們把傳輸資料包的一方稱為請求方,把接到二進位制資料包的一方稱為應答方。請求方和應答方可以進行互換,請求方也可以作為應答方接受資料,應答方也可以作為請求方請求資料,它們之間的關係如下

HTTP

如圖所示,A 和 B 是兩個不同的端系統,它們之間可以作為資訊交換的載體存在,剛開始的時候是 A 作為請求方請求與 B 交換資訊,B 作為響應的一方提供資訊;隨著時間的推移,B 也可以作為請求方請求 A 交換資訊,那麼 A 也可以作為響應方響應 B 請求的資訊。

什麼是協議
協議這個名詞不僅侷限於網際網路範疇,也體現在日常生活中,比如情侶雙方約定好在哪個地點吃飯,這個約定也是一種協議,比如你應聘成功了,企業會和你簽訂勞動合同,這種雙方的僱傭關係也是一種 協議。注意自己一個人對自己的約定不能成為協議,協議的前提條件必須是多人約定。

那麼網路協議是什麼呢?

網路協議就是網路中(包括網際網路)傳遞、管理資訊的一些規範。如同人與人之間相互交流是需要遵循一定的規矩一樣,計算機之間的相互通訊需要共同遵守一定的規則,這些規則就稱為網路協議。

沒有網路協議的網際網路是混亂的,就和人類社會一樣,人不能想怎麼樣就怎麼樣,你的行為約束是受到法律的約束的;那麼網際網路中的端系統也不能自己想發什麼發什麼,也是需要受到通訊協議約束的。

那麼我們就可以總結一下,什麼是 HTTP?可以用下面這個經典的總結回答一下: HTTP 是一個在計算機世界裡專門在兩點之間傳輸文字、圖片、音訊、視訊等超文字資料的約定和規範

 

與 HTTP 有關的元件

隨著網路世界演進,HTTP 協議已經幾乎成為不可替代的一種協議,在瞭解了 HTTP 的基本組成後,下面再來帶你進一步認識一下 HTTP 協議。

網路模型
網路是一個複雜的系統,不僅包括大量的應用程式、端系統、通訊鏈路、分組交換機等,還有各種各樣的協議組成,那麼現在我們就來聊一下網路中的協議層次。

為了給網路協議的設計提供一個結構,網路設計者以分層(layer)的方式組織協議,每個協議屬於層次模型之一。每一層都是向它的上一層提供服務(service),即所謂的服務模型(service model)。每個分層中所有的協議稱為 協議棧(protocol stack)。因特網的協議棧由五個部分組成:物理層、鏈路層、網路層、運輸層和應用層。我們採用自上而下的方法研究其原理,也就是應用層 -> 物理層的方式。

應用層
應用層是網路應用程式和網路協議存放的分層,因特網的應用層包括許多協議,例如我們學 web 離不開的 HTTP,電子郵件傳送協議 SMTP、端系統檔案上傳協議 FTP、還有為我們進行域名解析的 DNS 協議。應用層協議分佈在多個端系統上,一個端系統應用程式與另外一個端系統應用程式交換資訊分組,我們把位於應用層的資訊分組稱為 報文(message)

運輸層
因特網的運輸層在應用程式斷點之間傳送應用程式報文,在這一層主要有兩種傳輸協議 TCPUDP,利用這兩者中的任何一個都能夠傳輸報文,不過這兩種協議有巨大的不同。

TCP 向它的應用程式提供了面向連線的服務,它能夠控制並確認報文是否到達,並提供了擁塞機制來控制網路傳輸,因此當網路擁塞時,會抑制其傳輸速率。

UDP 協議向它的應用程式提供了無連線服務。它不具備可靠性的特徵,沒有流量控制,也沒有擁塞控制。我們把運輸層的分組稱為 報文段(segment)

網路層
因特網的網路層負責將稱為 資料包(datagram) 的網路分層從一臺主機移動到另一臺主機。網路層一個非常重要的協議是 IP 協議,所有具有網路層的因特網元件都必須執行 IP 協議,IP 協議是一種網際協議,除了 IP 協議外,網路層還包括一些其他網際協議和路由選擇協議,一般把網路層就稱為 IP 層,由此可知 IP 協議的重要性。

鏈路層
現在我們有應用程式通訊的協議,有了給應用程式提供運輸的協議,還有了用於約定傳送位置的 IP 協議,那麼如何才能真正的傳送資料呢?為了將分組從一個節點(主機或路由器)運輸到另一個節點,網路層必須依靠鏈路層提供服務。鏈路層的例子包括乙太網、WiFi 和電纜接入的 DOCSIS 協議,因為資料從源目的地傳送通常需要經過幾條鏈路,一個資料包可能被沿途不同的鏈路層協議處理,我們把鏈路層的分組稱為 幀(frame)

物理層
雖然鏈路層的作用是將幀從一個端系統運輸到另一個端系統,而物理層的作用是將幀中的一個個 位元 從一個節點運輸到另一個節點,物理層的協議仍然使用鏈路層協議,這些協議與實際的物理傳輸介質有關,例如,乙太網有很多物理層協議:關於雙絞銅線、關於同軸電纜、關於光纖等等。

五層網路協議的示意圖如下

HTTP

OSI 模型
我們上面討論的計算網路協議模型不是唯一的 協議棧,ISO(國際標準化組織)提出來計算機網路應該按照7層來組織,那麼7層網路協議棧與5層的區別在哪裡?

HTTP

從圖中可以一眼看出,OSI 要比上面的網路模型多了 表示層會話層,其他層基本一致。表示層主要包括資料壓縮和資料加密以及資料描述,資料描述使得應用程式不必擔心計算機內部儲存格式的問題,而會話層提供了資料交換的定界和同步功能,包括建立檢查點和恢復方案。

瀏覽器
就如同各大郵箱使用電子郵件傳送協議 SMTP 一樣,瀏覽器是使用 HTTP 協議的主要載體,說到瀏覽器,你能想起來幾種?是的,隨著網景大戰結束後,瀏覽器迅速發展,至今已經出現過的瀏覽器主要有

HTTP

瀏覽器正式的名字叫做 Web Broser,顧名思義,就是檢索、檢視網際網路上網頁資源的應用程式,名字裡的 Web,實際上指的就是 World Wide Web,也就是全球資訊網。

我們在位址列輸入URL(即網址),瀏覽器會向DNS(域名伺服器,後面會說)提供網址,由它來完成 URL 到 IP 地址的對映。然後將請求你的請求提交給具體的伺服器,在由伺服器返回我們要的結果(以HTML編碼格式返回給瀏覽器),瀏覽器執行HTML編碼,將結果顯示在瀏覽器的正文。這就是一個瀏覽器發起請求和接受響應的過程。

Web 伺服器
Web 伺服器的正式名稱叫做 Web Server,Web 伺服器一般指的是網站伺服器,上面說到瀏覽器是 HTTP 請求的發起方,那麼 Web 伺服器就是 HTTP 請求的應答方,Web 伺服器可以向瀏覽器等 Web 客戶端提供文件,也可以放置網站檔案,讓全世界瀏覽;可以放置資料檔案,讓全世界下載。目前最主流的三個Web伺服器是Apache、 Nginx 、IIS。

CDN
CDN的全稱是Content Delivery Network,即內容分發網路,它應用了 HTTP 協議裡的快取和代理技術,代替源站響應客戶端的請求。CDN 是構建在現有網路基礎之上的網路,它依靠部署在各地的邊緣伺服器,通過中心平臺的負載均衡、內容分發、排程等功能模組,使使用者就近獲取所需內容,降低網路擁塞,提高使用者訪問響應速度和命中率。CDN的關鍵技術主要有內容儲存分發技術

打比方說你要去亞馬遜上買書,之前你只能通過購物網站購買後從美國發貨過海關等重重關卡送到你的家裡,現在在中國建立一個亞馬遜分基地,你就不用通過美國進行郵寄,從中國就能把書儘快給你送到。

WAF
WAF 是一種 Web 應用程式防護系統(Web Application Firewall,簡稱 WAF),它是一種通過執行一系列針對HTTP / HTTPS的安全策略來專門為Web應用提供保護的一款產品,它是應用層面的防火牆,專門檢測 HTTP 流量,是防護 Web 應用的安全技術。

WAF 通常位於 Web 伺服器之前,可以阻止如 SQL 注入、跨站指令碼等攻擊,目前應用較多的一個開源專案是 ModSecurity,它能夠完全整合進 Apache 或 Nginx。

WebService
WebService 是一種 Web 應用程式,WebService是一種跨程式語言和跨作業系統平臺的遠端呼叫技術。

Web Service 是一種由 W3C 定義的應用服務開發規範,使用 client-server 主從架構,通常使用 WSDL 定義服務介面,使用 HTTP 協議傳輸 XML 或 SOAP 訊息,它是一個基於 Web(HTTP)的服務架構技術,既可以執行在內網,也可以在適當保護後執行在外網。

HTML
HTML 稱為超文字標記語言,是一種標識性的語言。它包括一系列標籤.通過這些標籤可以將網路上的文件格式統一,使分散的 Internet 資源連線為一個邏輯整體。HTML 文字是由 HTML 命令組成的描述性文字,HTML 命令可以說明文字,圖形、動畫、聲音、表格、連結等。

Web 頁面構成
Web 頁面(Web page)也叫做文件,是由一個個物件組成的。一個物件(Objecy) 只是一個檔案,比如一個 HTML 檔案、一個 JPEG 圖形、一個 Java 小程式或一個視訊片段,它們在網路中可以通過 URL 地址定址。多數的 Web 頁面含有一個 HTML 基本檔案 以及幾個引用物件。

舉個例子,如果一個 Web 頁面包含 HTML 檔案和5個 JPEG 圖形,那麼這個 Web 頁面就有6個物件:一個 HTML 檔案和5個 JPEG 圖形。HTML 基本檔案通過 URL 地址引用頁面中的其他物件。

 

與 HTTP 有關的協議

在網際網路中,任何協議都不會單獨的完成資訊交換,HTTP 也一樣。雖然 HTTP 屬於應用層的協議,但是它仍然需要其他層次協議的配合完成資訊的交換,那麼在完成一次 HTTP 請求和響應的過程中,需要哪些協議的配合呢?一起來看一下

TCP/IP
TCP/IP 協議你一定聽過,TCP/IP 我們一般稱之為協議簇,什麼意思呢?就是 TCP/IP 協議簇中不僅僅只有 TCP 協議和 IP 協議,它是一系列網路通訊協議的統稱。而其中最核心的兩個協議就是 TCP / IP 協議,其他的還有 UDP、ICMP、ARP 等等,共同構成了一個複雜但有層次的協議棧。

TCP 協議的全稱是 Transmission Control Protocol 的縮寫,意思是傳輸控制協議,HTTP 使用 TCP 作為通訊協議,這是因為 TCP 是一種可靠的協議,而可靠能保證資料不丟失。

IP 協議的全稱是 Internet Protocol 的縮寫,它主要解決的是通訊雙方定址的問題。IP 協議使用 IP 地址 來標識網際網路上的每一臺計算機,可以把 IP 地址想象成為你手機的電話號碼,你要與他人通話必須先要知道他人的手機號碼,計算機網路中資訊交換必須先要知道對方的 IP 地址。(關於 TCP 和 IP 更多的討論我們會在後面詳解)

DNS
你有沒有想過為什麼你可以通過鍵入 www.google.com 就能夠獲取你想要的網站?我們上面說到,計算機網路中的每個端系統都有一個 IP 地址存在,而把 IP 地址轉換為便於人類記憶的協議就是 DNS 協議

DNS 的全稱是域名系統(Domain Name System,縮寫:DNS),它作為將域名和 IP 地址相互對映的一個分散式資料庫,能夠使人更方便地訪問網際網路。

URI / URL
我們上面提到,你可以通過輸入 www.google.com 地址來訪問谷歌的官網,那麼這個地址有什麼規定嗎?我怎麼輸都可以?AAA.BBB.CCC 是不是也行?當然不是的,你輸入的地址格式必須要滿足 URI 的規範。

URI的全稱是(Uniform Resource Identifier),中文名稱是統一資源識別符號,使用它就能夠唯一地標記網際網路上資源。

URL的全稱是(Uniform Resource Locator),中文名稱是統一資源定位符,也就是我們俗稱的網址,它實際上是 URI 的一個子集。

URI 不僅包括 URL,還包括 URN(統一資源名稱),它們之間的關係如下

HTTP

HTTPS
HTTP 一般是明文傳輸,很容易被攻擊者竊取重要資訊,鑑於此,HTTPS 應運而生。HTTPS 的全稱為 (Hyper Text Transfer Protocol over SecureSocket Layer),全稱有點長,HTTPS 和 HTTP 有很大的不同在於 HTTPS 是以安全為目標的 HTTP 通道,在 HTTP 的基礎上通過傳輸加密和身份認證保證了傳輸過程的安全性。HTTPS 在 HTTP 的基礎上增加了 SSL 層,也就是說 HTTPS = HTTP + SSL。(這塊我們後面也會詳談 HTTPS)

 

HTTP 請求響應過程

你是不是很好奇,當你在瀏覽器中輸入網址後,到底發生了什麼事情?你想要的內容是如何展現出來的?讓我們通過一個例子來探討一下,我們假設訪問的 URL 地址為http://www.someSchool.edu/someDepartment/home.index,當我們輸入網址並點選回車時,瀏覽器內部會進行如下操作

  • DNS伺服器會首先進行域名的對映,找到訪問www.someSchool.edu所在的地址,然後HTTP 客戶端程式在 80 埠發起一個到伺服器 www.someSchool.edu 的 TCP 連線(80 埠是 HTTP 的預設埠)。在客戶和伺服器程式中都會有一個套接字與其相連。
  • HTTP 客戶端通過它的套接字向伺服器傳送一個 HTTP 請求報文。該報文中包含了路徑 someDepartment/home.index 的資源,我們後面會詳細討論 HTTP 請求報文。
  • HTTP 伺服器通過它的套接字接受該報文,進行請求的解析工作,並從其儲存器(RAM 或磁碟)中檢索出物件 www.someSchool.edu/someDepartment/home.index,然後把檢索出來的物件進行封裝,封裝到 HTTP 響應報文中,並通過套接字向客戶進行傳送。
  • HTTP 伺服器隨即通知 TCP 斷開 TCP 連線,實際上是需要等到客戶接受完響應報文後才會斷開 TCP 連線。
  • HTTP 客戶端接受完響應報文後,TCP 連線會關閉。HTTP 客戶端從響應中提取出報文中是一個 HTML 響應檔案,並檢查該 HTML 檔案,然後迴圈檢查報文中其他內部物件。
  • 檢查完成後,HTTP 客戶端會把對應的資源通過顯示器呈現給使用者。

至此,鍵入網址再按下回車的全過程就結束了。上述過程描述的是一種簡單的請求-響應全過程,真實的請求-響應情況可能要比上面描述的過程複雜很多。

 

HTTP 請求特徵

從上面整個過程中我們可以總結出 HTTP 進行分組傳輸是具有以下特徵

  • 支援客戶-伺服器模式
  • 簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有 GET、HEAD、POST。每種方法規定了客戶與伺服器聯絡的型別不同。由於 HTTP 協議簡單,使得 HTTP 伺服器的程式規模小,因而通訊速度很快。
  • 靈活:HTTP 允許傳輸任意型別的資料物件。正在傳輸的型別由 Content-Type 加以標記。
  • 無連線:無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。
  • 無狀態:HTTP 協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。

 

詳解 HTTP 報文

我們上面描述了一下 HTTP 的請求響應過程,流程比較簡單,但是凡事就怕認真,你這一認真,就能擴充出很多東西,比如 HTTP 報文是什麼樣的,它的組成格式是什麼? 下面就來探討一下

HTTP 協議主要由三大部分組成:

  • 起始行(start line):描述請求或響應的基本資訊;
  • 頭部欄位(header):使用 key-value 形式更詳細地說明報文;
  • 訊息正文(entity):實際傳輸的資料,它不一定是純文字,可以是圖片、視訊等二進位制資料。

其中起始行和頭部欄位併成為 請求頭 或者 響應頭,統稱為 Header;訊息正文也叫做實體,稱為 body。HTTP 協議規定每次傳送的報文必須要有 Header,但是可以沒有 body,也就是說頭資訊是必須的,實體資訊可以沒有。而且在 header 和 body 之間必須要有一個空行(CRLF),如果用一幅圖來表示一下的話,我覺得應該是下面這樣

HTTP

我們使用上面的那個例子來看一下 http 的請求報文

HTTP

如圖,這是 http://www.someSchool.edu/someDepartment/home.index 請求的請求頭,通過觀察這個 HTTP 報文我們就能夠學到很多東西,首先,我們看到報文是用普通 ASCII 文字書寫的,這樣保證人能夠可以看懂。然後,我們可以看到每一行和下一行之間都會有換行,而且最後一行(請求頭部後)再加上一個回車換行符。

每個報文的起始行都是由三個欄位組成:方法、URL 欄位和 HTTP 版本欄位

HTTP

HTTP 請求方法
HTTP 請求方法一般分為 8 種,它們分別是

  • GET 獲取資源,GET 方法用來請求訪問已被 URI 識別的資源。指定的資源經伺服器端解析後返回響應內容。也就是說,如果請求的資源是文字,那就保持原樣返回;
  • POST 傳輸實體,雖然 GET 方法也可以傳輸主體資訊,但是便於區分,我們一般不用 GET 傳輸實體資訊,反而使用 POST 傳輸實體資訊,
  • PUT 傳輸檔案,PUT 方法用來傳輸檔案。就像 FTP 協議的檔案上傳一樣,要求在請求報文的主體中包含檔案內容,然後儲存到請求 URI 指定的位置。但是,鑑於 HTTP 的 PUT 方法自身不帶驗證機制,任何人都可以上傳檔案 , 存在安全性問題,因此一般的 W eb 網站不使用該方法。若配合 W eb 應用程式的驗證機制,或架構設計採用REST(REpresentational State Transfer,表徵狀態轉移)標準的同類 Web 網站,就可能會開放使用 PUT 方法。
  • HEAD 獲得響應首部,HEAD 方法和 GET 方法一樣,只是不返回報文主體部分。用於確認 URI 的有效性及資源更新的日期時間等。
  • DELETE 刪除檔案,DELETE 方法用來刪除檔案,是與 PUT 相反的方法。DELETE 方法按請求 URI 刪除指定的資源。
  • OPTIONS 詢問支援的方法,OPTIONS 方法用來查詢針對請求 URI 指定的資源支援的方法。
  • TRACE 追蹤路徑,TRACE 方法是讓 Web 伺服器端將之前的請求通訊環回給客戶端的方法。
  • CONNECT 要求用隧道協議連線代理,CONNECT 方法要求在與代理伺服器通訊時建立隧道,實現用隧道協議進行 TCP 通訊。主要使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協議把通訊內容加 密後經網路隧道傳輸。

我們一般最常用的方法也就是 GET 方法和 POST 方法,其他方法暫時瞭解即可。下面是 HTTP1.0 和 HTTP1.1 支援的方法清單HTTP

HTTP 請求 URL

HTTP 協議使用 URI 定位網際網路上的資源。正是因為 URI 的特定功能,在網際網路上任意位置的資源都能訪問到。URL 帶有請求物件的識別符號。在上面的例子中,瀏覽器正在請求物件 /somedir/page.html 的資源。

我們再通過一個完整的域名解析一下 URL

比如 http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument 這個 URL 比較繁瑣了吧,你把這個 URL 搞懂了其他的 URL 也就不成問題了。

首先出場的是 http

HTTP

http://告訴瀏覽器使用何種協議。對於大部分 Web 資源,通常使用 HTTP 協議或其安全版本,HTTPS 協議。另外,瀏覽器也知道如何處理其他協議。例如, mailto: 協議指示瀏覽器開啟郵件客戶端;ftp:協議指示瀏覽器處理檔案傳輸。

第二個出場的是 主機

HTTP

www.example.com 既是一個域名,也代表管理該域名的機構。它指示了需要向網路上的哪一臺主機發起請求。當然,也可以直接向主機的 IP address 地址發起請求。但直接使用 IP 地址的場景並不常見。

第三個出場的是 

HTTP

我們前面說到,兩個主機之間要發起 TCP 連線需要兩個條件,主機 + 埠。它表示用於訪問 Web 伺服器上資源的入口。如果訪問的該 Web 伺服器使用HTTP協議的標準埠(HTTP為80,HTTPS為443)授予對其資源的訪問許可權,則通常省略此部分。否則埠就是 URI 必須的部分。

上面是請求 URL 所必須包含的部分,下面就是 URL 具體請求資源路徑

第四個出場的是 路徑

HTTP

/path/to/myfile.html 是 Web 伺服器上資源的路徑。以埠後面的第一個 / 開始,到 ? 號之前結束,中間的 每一個/ 都代表了層級(上下級)關係。這個 URL 的請求資源是一個 html 頁面。

緊跟著路徑後面的是 查詢引數

HTTP

?key1=value1&key2=value2 是提供給 Web 伺服器的額外引數。如果是 GET 請求,一般帶有請求 URL 引數,如果是 POST 請求,則不會在路徑後面直接加引數。這些引數是用 & 符號分隔的鍵/值對列表。key1 = value1 是第一對,key2 = value2 是第二對引數

緊跟著引數的是錨點

HTTP

#SomewhereInTheDocument 是資源本身的某一部分的一個錨點。錨點代表資源內的一種“書籤”,它給予瀏覽器顯示位於該“加書籤”點的內容的指示。 例如,在HTML文件上,瀏覽器將滾動到定義錨點的那個點上;在視訊或音訊文件上,瀏覽器將轉到錨點代表的那個時間。值得注意的是 # 號後面的部分,也稱為片段識別符號,永遠不會與請求一起傳送到伺服器。

HTTP 版本

表示報文使用的 HTTP 協議版本。

請求頭部

這部分內容只是大致介紹一下,內容較多,後面會再以一篇文章詳述

在表述完了起始行之後我們再來看一下請求頭部,現在我們向上找,找到http://www.someSchool.edu/someDepartment/home.index,來看一下它的請求頭部

Host: www.someschool.edu
Connection: close
User-agent: Mozilla/5.0
Accept-language: fr

這個請求頭資訊比較少,首先 Host 表示的是物件所在的主機。你也許認為這個 Host 是不需要的,因為 URL 不是已經指明瞭請求物件的路徑了嗎?這個首部行提供的資訊是 Web 代理快取記憶體所需要的。Connection: close 表示的是瀏覽器需要告訴伺服器使用的是非持久連線。它要求伺服器在傳送完響應的物件後就關閉連線。User-agent: 這是請求頭用來告訴 Web 伺服器,瀏覽器使用的型別是 Mozilla/5.0,即 Firefox 瀏覽器。Accept-language 告訴 Web 伺服器,瀏覽器想要得到物件的法語版本,前提是伺服器需要支援法語型別,否則將會傳送伺服器的預設版本。下面我們針對主要的實體欄位進行介紹(具體的可以參考 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers MDN 官網學習)

HTTP 的請求標頭分為四種: 通用標頭請求標頭響應標頭 和 實體標頭,依次來進行詳解。

通用標頭

通用標頭主要有三個,分別是 DateCache-Control 和 Connection

Date

Date 是一個通用標頭,它可以出現在請求標頭和響應標頭中,它的基本表示如下

Date: Wed, 21 Oct 2015 07:28:00 GMT 

表示的是格林威治標準時間,這個時間要比北京時間慢八個小時

HTTP

Cache-Control

Cache-Control 是一個通用標頭,他可以出現在請求標頭和響應標頭中,Cache-Control 的種類比較多,雖然說這是一個通用標頭,但是又一些特性是請求標頭具有的,有一些是響應標頭才有的。主要大類有 可快取性閾值性、 重新驗證並重新載入 和其他特性

可快取性是唯一響應標頭才具有的特性,我們會在響應標頭中詳述。

閾值性,這個我翻譯可能不準確,它的原英文是 Expiration,我是根據它的值來翻譯的,你看到這些值可能會覺得我翻譯的有點道理

  • max-age: 資源被認為仍然有效的最長時間,與 Expires 不同,這個請求是相對於 request標頭的時間,而 Expires 是相對於響應標頭。(請求標頭)
  • s-maxage: 重寫了 max-age 和 Expires 請求頭,僅僅適用於共享快取,被私有快取所忽略(這塊不理解,看完響應頭的 Cache-Control 再進行理解)(請求標頭)
  • max-stale:表示客戶端將接受的最大響應時間,以秒為單位。(響應標頭)
  • min-fresh: 表示客戶端希望響應在指定的最小時間內有效。(響應標頭)

Connection

Connection 決定當前事務(一次三次握手和四次揮手)完成後,是否會關閉網路連線。Connection 有兩種,一種是永續性連線,即一次事務完成後不關閉網路連線

Connection: keep-alive

另一種是非永續性連線,即一次事務完成後關閉網路連線

Connection: close

HTTP1.1 其他通用標頭如下

HTTP

實體標頭

實體標頭是描述訊息正文內容的 HTTP 標頭。實體標頭用於 HTTP 請求和響應中。頭部Content-Length、 Content-Language、 Content-Encoding 是實體頭。

  • Content-Length 實體報頭指示實體主體的大小,以位元組為單位,傳送到接收方。
  • Content-Language 實體報頭描述了客戶端或者服務端能夠接受的語言,例如
Content-Language: de-DE
Content-Language: en-US
Content-Language: de-DE, en-CA
  • Content-Encoding 這又是一個比較麻煩的屬性,這個實體報頭用來壓縮媒體型別。Content-Encoding 指示對實體應用了何種編碼。

    常見的內容編碼有這幾種: gzip、compress、deflate、identity ,這個屬性可以應用在請求報文和響應報文中

Accept-Encoding: gzip, deflate //請求頭
Content-Encoding: gzip  //響應頭

下面是一些實體標頭欄位

HTTP

請求標頭

上面給出的例子請求報文的屬性比較少,下面給出一個 MDN 官網的例子

GET /home.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
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, br
Referer: https://developer.mozilla.org/testpage.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 18 Jul 2016 02:36:04 GMT
If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
Cache-Control: max-age=0  

Host

Host 請求頭指明瞭伺服器的域名(對於虛擬主機來說),以及(可選的)伺服器監聽的TCP埠號。如果沒有給定埠號,會自動使用被請求服務的預設埠(比如請求一個 HTTP 的 URL 會自動使用80作為埠)。

Host: developer.mozilla.org

上面的 Accpet、 Accept-LanguageAccept-Encoding 都是屬於內容協商的請求標頭,我們會在下面說明

Referer

HTTP Referer 屬性是請求標頭的一部分,當瀏覽器向 web 伺服器傳送請求的時候,一般會帶上 Referer,告訴伺服器該網頁是從哪個頁面連結過來的,伺服器因此可以獲得一些資訊用於處理。

Referer: https://developer.mozilla.org/testpage.html

Upgrade-Insecure-Requests

Upgrade-Insecure-Requests 是一個請求標頭,用來向伺服器端傳送訊號,表示客戶端優先選擇加密及帶有身份驗證的響應。

Upgrade-Insecure-Requests: 1

If-Modified-Since

HTTP 的 If-Modified-Since 使其成為條件請求

  • 返回200,只有在給定日期的最後一次修改資源後,伺服器才會以200狀態傳送回請求的資源。
  • 如果請求從開始以來沒有被修改過,響應會返回304並且沒有任何響應體

If-Modified-Since 通常會與 If-None-Match 搭配使用,If-Modified-Since 用於確認代理或客戶端擁有的本地資源的有效性。獲取資源的更新日期時間,可通過確認首部欄位 Last-Modified 來確定。

大白話說就是如果在 Last-Modified 之後更新了伺服器資源,那麼伺服器會響應200,如果在 Last-Modified 之後沒有更新過資源,則返回 304。

If-Modified-Since: Mon, 18 Jul 2016 02:36:04 GMT

If-None-Match

If-None-Match HTTP請求標頭使請求成為條件請求。 對於 GET 和 HEAD 方法,僅當伺服器沒有與給定資源匹配的 ETag 時,伺服器才會以200狀態傳送回請求的資源。 對於其他方法,僅當最終現有資源的ETag與列出的任何值都不匹配時,才會處理請求。

If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"

ETag 屬於響應標頭,後面進行介紹。

內容協商

內容協商機制是指客戶端和伺服器端就響應的資源內容進行交涉,然後提供給客戶端最為適合的資源。內容協商會以響應資源的語言、字符集、編碼方式等作為判斷的標準。 

HTTP

內容協商主要有以下3種型別:

  • 伺服器驅動協商(Server-driven Negotiation)

這種協商方式是由伺服器端進行內容協商。伺服器端會根據請求首部欄位進行自動處理

  • 客戶端驅動協商(Agent-driven Negotiation)

這種協商方式是由客戶端來進行內容協商。

  • 透明協商(Transparent Negotiation)

是伺服器驅動和客戶端驅動的結合體,是由伺服器端和客戶端各自進行內容協商的一種方法。

內容協商的分類有很多種,主要的幾種型別是 Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language。

Accept

接受請求 HTTP 標頭會通告客戶端其能夠理解的 MIME 型別

那麼什麼是 MIME 型別呢?在回答這個問題前你應該先了解一下什麼是 MIME

# MIME: MIME (Multipurpose Internet Mail Extensions) 是描述訊息內容型別的因特網標準。
MIME 訊息能包含文字、影像、音訊、視訊以及其他應用程式專用的資料。

也就是說,MIME 型別其實就是一系列訊息內容型別的集合。那麼 MIME 型別都有哪些呢?

文字檔案: text/html、text/plain、text/css、application/xhtml+xml、application/xml

圖片檔案: image/jpeg、image/gif、image/png

視訊檔案: video/mpeg、video/quicktime

應用程式二進位制檔案: application/octet-stream、application/zip

比如,如果瀏覽器不支援 PNG 圖片的顯示,那 Accept 就不指定image/png,而指定可處理的 image/gif 和 image/jpeg 等圖片型別。

一般 MIME 型別也會和 q 這個屬性一起使用,q 是什麼?q 表示的是權重,來看一個例子

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

這是什麼意思呢?若想要給顯示的媒體型別增加優先順序,則使用 q= 來額外表示權重值,沒有顯示權重的時候預設值是1.0 ,我給你列個表格你就明白了

qMIME
1.0 text/html
1.0 application/xhtml+xml
0.9 application/xml
0.8 * / *

也就是說,這是一個放置順序,權重高的在前,低的在後,application/xml;q=0.9 是不可分割的整體。

Accept-Charset

accept-charset 屬性規定伺服器處理表單資料所接受的字符集。

accept-charset 屬性允許您指定一系列字符集,伺服器必須支援這些字符集,從而得以正確解釋表單中的資料。

該屬性的值是用引號包含字符集名稱列表。如果可接受字符集與使用者所使用的字元即不相匹配的話,瀏覽器可以選擇忽略表單或是將該表單區別對待。

此屬性的預設值是 unknown,表示表單的字符集與包含表單的文件的字符集相同。

常用的字符集有: UTF-8 - Unicode 字元編碼 ; ISO-8859-1 - 拉丁字母表的字元編碼

Accept-Language

首部欄位 Accept-Language 用來告知伺服器使用者代理能夠處理的自然語言集(指中文或英文等),以及自然語言集的相對優先順序。可一次指定多種自然語言集。
和 Accept 首部欄位一樣,按權重值 q來表示相對優先順序。

Accept-Language: en-US,en;q=0.5

請求標頭我們大概就介紹這幾種,後面會有一篇文章詳細深挖所有的響應頭的,下面是一個響應頭的彙總,基於 HTTP 1.1

HTTP

響應標頭

響應標頭是可以在 HTTP 響應種使用的 HTTP 標頭,這聽起來是像一句廢話,不過確實是這樣解釋。並不是所有出現在響應中的標頭都是響應標頭。還有一些特殊的我們上面說過,有通用標頭和實體標頭也會出現在響應標頭中,比如 Content-Length 就是一個實體標頭,但是,在這種情況下,這些實體請求通常稱為響應頭。下面以一個例子為例和你探討一下響應頭

200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jul 2016 16:06:00 GMT
Etag: "c561c68d0ba92bbeb8b0f612a9199f722e3a621a"
Keep-Alive: timeout=5, max=997
Last-Modified: Mon, 18 Jul 2016 02:36:04 GMT
Server: Apache
Set-Cookie: mykey=myvalue; expires=Mon, 17-Jul-2017 16:06:00 GMT; Max-Age=31449600; Path=/; secure
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
x-frame-options: DENY

 

響應狀態碼

首先出現的應該就是 200 OK,這是 HTTP 響應標頭的狀態碼,它表示著響應成功完成。HTTP 響應標頭的狀態碼有很多,並做了如下規定

以 2xx 為開頭的都表示請求成功響應。

狀態碼含義
200 成功響應
204 請求處理成功,但是沒有資源可以返回
206 對資源某一部分進行響應,由Content-Range 指定範圍的實體內容。

以 3xx 為開頭的都表示需要進行附加操作以完成請求

狀態碼含義
301 永久性重定向,該狀態碼錶示請求的資源已經重新分配 URI,以後應該使用資源現有的 URI
302 臨時性重定向。該狀態碼錶示請求的資源已被分配了新的 URI,希望使用者(本次)能使用新的 URI 訪問。
303 該狀態碼錶示由於請求對應的資源存在著另一個 URI,應使用 GET 方法定向獲取請求的資源。
304 該狀態碼錶示客戶端傳送附帶條件的請求時,伺服器端允許請求訪問資源,但未滿足條件的情況。
307 臨時重定向。該狀態碼與 302 Found 有著相同的含義。

以 4xx 的響應結果表明客戶端是發生錯誤的原因所在。

狀態碼含義
400 該狀態碼錶示請求報文中存在語法錯誤。當錯誤發生時,需修改請求的內容後再次傳送請求。
401 該狀態碼錶示傳送的請求需要有通過 HTTP 認證(BASIC 認證、DIGEST 認證)的認證資訊。
403 該狀態碼錶明對請求資源的訪問被伺服器拒絕了。
404 該狀態碼錶明伺服器上無法找到請求的資源。

 5xx 為開頭的響應標頭都表示伺服器本身發生錯誤

狀態碼含義
500 該狀態碼錶明伺服器端在執行請求時發生了錯誤。
503 該狀態碼錶明伺服器暫時處於超負載或正在進行停機維護,現在無法處理請求。

Access-Control-Allow-Origin

一個返回的 HTTP 標頭可能會具有 Access-Control-Allow-Origin ,Access-Control-Allow-Origin 指定一個來源,它告訴瀏覽器允許該來源進行資源訪問。 否則-對於沒有憑據的請求 *萬用字元,告訴瀏覽器允許任何源訪問資源。例如,要允許源 https://mozilla.org 的程式碼訪問資源,可以指定:

Access-Control-Allow-Origin: https://mozilla.org
Vary: Origin

如果伺服器指定單個來源而不是 *萬用字元的話 ,則伺服器還應在 Vary 響應標頭中包含 Origin ,以向客戶端指示 伺服器響應將根據原始請求標頭的值而有所不同。

Keep-Alive

上面我們提到,HTTP 報文標頭會分為四種,這其實是按著上下文來分類的

還有一種分類是根據代理進行分類,根據代理會分為端到端頭 和 逐跳標頭

而 Keep-Alive 表示的是 Connection 非持續連線的存活時間,如下

Connection: Keep-Alive
Keep-Alive: timeout=5, max=997 

Keep-Alive 有兩個引數,它們是以逗號分隔的引數列表,每個引數由一個識別符號和一個由等號 = 分隔的值組成。

timeout:指示空閒連線必須保持開啟狀態的最短時間(以秒為單位)。

max:指示在關閉連線之前可以在此連線上傳送的最大請求數。

上述 HTTP 程式碼的意思就是限制最大的超時時間是 5s 和 最大的連線請求是 997 個。

Server

伺服器標頭包含有關原始伺服器用來處理請求的軟體的資訊。

應該避免使用過於冗長和詳細的 Server 值,因為它們可能會洩露內部實施細節,這可能會使攻擊者容易地發現並利用已知的安全漏洞。例如下面這種寫法

Server: Apache/2.4.1 (Unix)

Set-Cookie

Cookie 又是另外一個領域的內容了,我們後面文章會說道 Cookie,這裡需要記住 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部欄位,它們不是屬於 HTTP 1.1 的首部欄位,但是使用率仍然很高。

Transfer-Encoding

首部欄位 Transfer-Encoding 規定了傳輸報文主體時採用的編碼方式。

Transfer-Encoding: chunked

HTTP /1.1 的傳輸編碼方式僅對分塊傳輸編碼有效。

X-Frame-Options

HTTP 首部欄位是可以自行擴充套件的。所以在 Web 伺服器和瀏覽器的應用上,會出現各種非標準的首部欄位。

首部欄位 X-Frame-Options 屬於 HTTP 響應首部,用於控制網站內容在其他 Web 網站的 Frame 標籤內的顯示問題。其主要目的是為了防止點選劫持(clickjacking)攻擊。

下面是一個響應頭的彙總,基於 HTTP 1.1

HTTP

非 HTTP/1.1 首部欄位

在 HTTP 協議通訊互動中使用到的首部欄位,不限於 RFC2616 中定義的 47 種首部欄位。還有 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部欄位,它們的使用頻率也很高。
這些非正式的首部欄位統一歸納在 RFC4229 HTTP Header Field Registrations 中。

End-to-end 首部和 Hop-by-hop 首部

HTTP 首部欄位將定義成快取代理和非快取代理的行為,分成 2 種型別。

一種是 End-to-end 首部 和 Hop-by-hop 首部

End-to-end(端到端) 首部

這些標頭必須傳送給訊息的最終接收者 : 請求的伺服器,或響應的客戶端。中間代理必須重新傳輸未經修改的標頭,並且快取必須儲存這些資訊

Hop-by-hop(逐跳) 首部

分在此類別中的首部只對單次轉發有效,會因通過快取或代理而不再轉發。

下面列舉了 HTTP/1.1 中的逐跳首部欄位。除這 8 個首部欄位之外,其他所有欄位都屬於端到端首部。

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

 

HTTP 的優點和缺點

HTTP 的優點

簡單靈活易擴充套件

HTTP 最重要也是最突出的優點是 簡單、靈活、易於擴充套件

HTTP 的協議比較簡單,它的主要組成就是 header + body,頭部資訊也是簡單的文字格式,而且 HTTP 的請求報文根據英文也能猜出來個大概的意思,降低學習門檻,能夠讓更多的人研究和開發 HTTP 應用。

所以,在簡單的基礎上,HTTP 協議又多了靈活 和 易擴充套件 的優點。

HTTP 協議裡的請求方法、URI、狀態碼、原因短語、頭欄位等每一個核心組成要素都沒有被制定死,允許開發者任意定製、擴充或解釋,給予了瀏覽器和伺服器最大程度的信任和自由。

應用廣泛、環境成熟

因為過於簡單,普及,因此應用很廣泛。因為 HTTP 協議本身不屬於一種語言,它並不限定某種程式語言或者作業系統,所以天然具有跨語言、跨平臺的優越性。而且,因為本身的簡單特性很容易實現,所以幾乎所有的程式語言都有 HTTP 呼叫庫和外圍的開發測試工具。

隨著移動網際網路的發展, HTTP 的觸角已經延伸到了世界的每一個角落,從簡單的 Web 頁面到複雜的 JSON、XML 資料,從桌上型電腦上的瀏覽器到手機上的各種 APP、新聞、論壇、購物、手機遊戲,你很難找到一個沒有使用 HTTP 的地方。

無狀態

無狀態其實既是優點又是缺點。因為伺服器沒有記憶能力,所以就不需要額外的資源來記錄狀態資訊,不僅實現上會簡單一些,而且還能減輕伺服器的負擔,能夠把更多的 CPU 和記憶體用來對外提供服務。

HTTP 的缺點

無狀態

既然伺服器沒有記憶能力,它就無法支援需要連續多個步驟的事務操作。每次都得問一遍身份資訊,不僅麻煩,而且還增加了不必要的資料傳輸量。由此出現了 Cookie 技術。

明文

HTTP 協議裡還有一把優缺點一體的雙刃劍,就是明文傳輸。明文意思就是協議裡的報文(準確地說是 header 部分)不使用二進位制資料,而是用簡單可閱讀的文字形式。

對比 TCP、UDP 這樣的二進位制協議,它的優點顯而易見,不需要藉助任何外部工具,用瀏覽器、Wireshark 或者 tcpdump 抓包後,直接用肉眼就可以很容易地檢視或者修改,為我們的開發除錯工作帶來極大的便利。

當然缺點也是顯而易見的,就是不安全,可以被監聽和被窺探。因為無法判斷通訊雙方的身份,不能判斷報文是否被更改過。

效能

HTTP 的效能不算差,但不完全適應現在的網際網路,還有很大的提升空間。


 

關注、留言,我們一起學習,您的收藏是我持續更新的動力!

 

===============Talk is cheap, show me the code,bye-bye================

相關文章