整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          看完這篇 HTTP,跟面試官扯皮就沒問題了

          者 | cxuan

          責(zé)編 | 屠敏

          頭圖 | CSDN 下載自視覺中國

          我是一名程序員,我的主要編程語言是 Java,我更是一名 Web 開發(fā)人員,所以我必須要了解 HTTP,所以本篇文章就來帶你從 HTTP 入門到進階,看完讓你有一種恍然大悟、醍醐灌頂?shù)母杏X。

          最初在有網(wǎng)絡(luò)之前,我們的電腦都是單機的,單機系統(tǒng)是孤立的,我還記得 05 年前那會兒家里有個電腦,想打電腦游戲還得兩個人在一個電腦上玩兒,及其不方便。我就想為什么家里人不讓上網(wǎng),我的同學(xué) xxx 家里有網(wǎng),每次一提這個就落一通批評:xxx上xxx什xxxx么xxxx網(wǎng)xxxx看xxxx你xxxx考xxxx的xxxx那xxxx點xxxx分。雖然我家里沒有上網(wǎng),但是此時互聯(lián)網(wǎng)已經(jīng)在高速發(fā)展了,HTTP 就是高速發(fā)展的一個產(chǎn)物。

          認識 HTTP

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

          超文本傳輸協(xié)議可以進行文字分割:超文本(Hypertext)、傳輸(Transfer)、協(xié)議(Protocol),它們之間的關(guān)系如下

          按照范圍的大小 協(xié)議 > 傳輸 > 超文本。下面就分別對這三個名次做一個解釋。

          什么是超文本

          在互聯(lián)網(wǎng)早期的時候,我們輸入的信息只能保存在本地,無法和其他電腦進行交互。我們保存的信息通常都以文本即簡單字符的形式存在,文本是一種能夠被計算機解析的有意義的二進制數(shù)據(jù)包。而隨著互聯(lián)網(wǎng)的高速發(fā)展,兩臺電腦之間能夠進行數(shù)據(jù)的傳輸后,人們不滿足只能在兩臺電腦之間傳輸文字,還想要傳輸圖片、音頻、視頻,甚至點擊文字或圖片能夠進行超鏈接的跳轉(zhuǎn),那么文本的語義就被擴大了,這種語義擴大后的文本就被稱為超文本(Hypertext)。

          什么是傳輸

          那么我們上面說到,兩臺計算機之間會形成互聯(lián)關(guān)系進行通信,我們存儲的超文本會被解析成為二進制數(shù)據(jù)包,由傳輸載體(例如同軸電纜,電話線,光纜)負責(zé)把二進制數(shù)據(jù)包由計算機終端傳輸?shù)搅硪粋€終端的過程(對終端的詳細解釋可以參考《你說你懂互聯(lián)網(wǎng),那這些你知道么?》這篇文章)稱為傳輸(transfer)。

          通常我們把傳輸數(shù)據(jù)包的一方稱為請求方,把接到二進制數(shù)據(jù)包的一方稱為應(yīng)答方。請求方和應(yīng)答方可以進行互換,請求方也可以作為應(yīng)答方接受數(shù)據(jù),應(yīng)答方也可以作為請求方請求數(shù)據(jù),它們之間的關(guān)系如下

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

          什么是協(xié)議

          協(xié)議這個名詞不僅局限于互聯(lián)網(wǎng)范疇,也體現(xiàn)在日常生活中,比如情侶雙方約定好在哪個地點吃飯,這個約定也是一種協(xié)議,比如你應(yīng)聘成功了,企業(yè)會和你簽訂勞動合同,這種雙方的雇傭關(guān)系也是一種 協(xié)議。注意自己一個人對自己的約定不能成為協(xié)議,協(xié)議的前提條件必須是多人約定。

          那么網(wǎng)絡(luò)協(xié)議是什么呢?

          網(wǎng)絡(luò)協(xié)議就是網(wǎng)絡(luò)中(包括互聯(lián)網(wǎng))傳遞、管理信息的一些規(guī)范。如同人與人之間相互交流是需要遵循一定的規(guī)矩一樣,計算機之間的相互通信需要共同遵守一定的規(guī)則,這些規(guī)則就稱為網(wǎng)絡(luò)協(xié)議。

          沒有網(wǎng)絡(luò)協(xié)議的互聯(lián)網(wǎng)是混亂的,就和人類社會一樣,人不能想怎么樣就怎么樣,你的行為約束是受到法律的約束的;那么互聯(lián)網(wǎng)中的端系統(tǒng)也不能自己想發(fā)什么發(fā)什么,也是需要受到通信協(xié)議約束的。

          那么我們就可以總結(jié)一下,什么是 HTTP?可以用下面這個經(jīng)典的總結(jié)回答一下:HTTP 是一個在計算機世界里專門在兩點之間傳輸文字、圖片、音頻、視頻等超文本數(shù)據(jù)的約定和規(guī)范。

          與 HTTP 有關(guān)的組件

          隨著網(wǎng)絡(luò)世界演進,HTTP 協(xié)議已經(jīng)幾乎成為不可替代的一種協(xié)議,在了解了 HTTP 的基本組成后,下面再來帶你進一步認識一下 HTTP 協(xié)議。

          網(wǎng)絡(luò)模型

          網(wǎng)絡(luò)是一個復(fù)雜的系統(tǒng),不僅包括大量的應(yīng)用程序、端系統(tǒng)、通信鏈路、分組交換機等,還有各種各樣的協(xié)議組成,那么現(xiàn)在我們就來聊一下網(wǎng)絡(luò)中的協(xié)議層次。

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

          應(yīng)用層

          應(yīng)用層是網(wǎng)絡(luò)應(yīng)用程序和網(wǎng)絡(luò)協(xié)議存放的分層,因特網(wǎng)的應(yīng)用層包括許多協(xié)議,例如我們學(xué) web 離不開的 HTTP,電子郵件傳送協(xié)議 SMTP、端系統(tǒng)文件上傳協(xié)議 FTP、還有為我們進行域名解析的 DNS 協(xié)議。應(yīng)用層協(xié)議分布在多個端系統(tǒng)上,一個端系統(tǒng)應(yīng)用程序與另外一個端系統(tǒng)應(yīng)用程序交換信息分組,我們把位于應(yīng)用層的信息分組稱為 報文(message)。

          運輸層

          因特網(wǎng)的運輸層在應(yīng)用程序斷點之間傳送應(yīng)用程序報文,在這一層主要有兩種傳輸協(xié)議 TCP和 UDP,利用這兩者中的任何一個都能夠傳輸報文,不過這兩種協(xié)議有巨大的不同。

          TCP 向它的應(yīng)用程序提供了面向連接的服務(wù),它能夠控制并確認報文是否到達,并提供了擁塞機制來控制網(wǎng)絡(luò)傳輸,因此當網(wǎng)絡(luò)擁塞時,會抑制其傳輸速率。

          UDP 協(xié)議向它的應(yīng)用程序提供了無連接服務(wù)。它不具備可靠性的特征,沒有流量控制,也沒有擁塞控制。我們把運輸層的分組稱為 報文段(segment)

          網(wǎng)絡(luò)層

          因特網(wǎng)的網(wǎng)絡(luò)層負責(zé)將稱為 數(shù)據(jù)報(datagram) 的網(wǎng)絡(luò)分層從一臺主機移動到另一臺主機。網(wǎng)絡(luò)層一個非常重要的協(xié)議是 IP 協(xié)議,所有具有網(wǎng)絡(luò)層的因特網(wǎng)組件都必須運行 IP 協(xié)議,IP 協(xié)議是一種網(wǎng)際協(xié)議,除了 IP 協(xié)議外,網(wǎng)絡(luò)層還包括一些其他網(wǎng)際協(xié)議和路由選擇協(xié)議,一般把網(wǎng)絡(luò)層就稱為 IP 層,由此可知 IP 協(xié)議的重要性。

          鏈路層

          現(xiàn)在我們有應(yīng)用程序通信的協(xié)議,有了給應(yīng)用程序提供運輸?shù)膮f(xié)議,還有了用于約定發(fā)送位置的 IP 協(xié)議,那么如何才能真正的發(fā)送數(shù)據(jù)呢?為了將分組從一個節(jié)點(主機或路由器)運輸?shù)搅硪粋€節(jié)點,網(wǎng)絡(luò)層必須依靠鏈路層提供服務(wù)。鏈路層的例子包括以太網(wǎng)、WiFi 和電纜接入的 DOCSIS 協(xié)議,因為數(shù)據(jù)從源目的地傳送通常需要經(jīng)過幾條鏈路,一個數(shù)據(jù)包可能被沿途不同的鏈路層協(xié)議處理,我們把鏈路層的分組稱為 幀(frame)

          物理層

          雖然鏈路層的作用是將幀從一個端系統(tǒng)運輸?shù)搅硪粋€端系統(tǒng),而物理層的作用是將幀中的一個個 比特 從一個節(jié)點運輸?shù)搅硪粋€節(jié)點,物理層的協(xié)議仍然使用鏈路層協(xié)議,這些協(xié)議與實際的物理傳輸介質(zhì)有關(guān),例如,以太網(wǎng)有很多物理層協(xié)議:關(guān)于雙絞銅線、關(guān)于同軸電纜、關(guān)于光纖等等。

          五層網(wǎng)絡(luò)協(xié)議的示意圖如下

          OSI 模型

          我們上面討論的計算網(wǎng)絡(luò)協(xié)議模型不是唯一的 協(xié)議棧,ISO(國際標準化組織)提出來計算機網(wǎng)絡(luò)應(yīng)該按照7層來組織,那么7層網(wǎng)絡(luò)協(xié)議棧與5層的區(qū)別在哪里?

          從圖中可以一眼看出,OSI 要比上面的網(wǎng)絡(luò)模型多了 表示層 和 會話層,其他層基本一致。表示層主要包括數(shù)據(jù)壓縮和數(shù)據(jù)加密以及數(shù)據(jù)描述,數(shù)據(jù)描述使得應(yīng)用程序不必擔(dān)心計算機內(nèi)部存儲格式的問題,而會話層提供了數(shù)據(jù)交換的定界和同步功能,包括建立檢查點和恢復(fù)方案。

          瀏覽器

          就如同各大郵箱使用電子郵件傳送協(xié)議 SMTP 一樣,瀏覽器是使用 HTTP 協(xié)議的主要載體,說到瀏覽器,你能想起來幾種?是的,隨著網(wǎng)景大戰(zhàn)結(jié)束后,瀏覽器迅速發(fā)展,至今已經(jīng)出現(xiàn)過的瀏覽器主要有:

          瀏覽器正式的名字叫做 Web Broser,顧名思義,就是檢索、查看互聯(lián)網(wǎng)上網(wǎng)頁資源的應(yīng)用程序,名字里的 Web,實際上指的就是 World Wide Web,也就是萬維網(wǎng)。

          我們在地址欄輸入URL(即網(wǎng)址),瀏覽器會向DNS(域名服務(wù)器,后面會說)提供網(wǎng)址,由它來完成 URL 到 IP 地址的映射。然后將請求你的請求提交給具體的服務(wù)器,在由服務(wù)器返回我們要的結(jié)果(以HTML編碼格式返回給瀏覽器),瀏覽器執(zhí)行HTML編碼,將結(jié)果顯示在瀏覽器的正文。這就是一個瀏覽器發(fā)起請求和接受響應(yīng)的過程。

          Web 服務(wù)器

          Web 服務(wù)器的正式名稱叫做 Web Server,Web 服務(wù)器一般指的是網(wǎng)站服務(wù)器,上面說到瀏覽器是 HTTP 請求的發(fā)起方,那么 Web 服務(wù)器就是 HTTP 請求的應(yīng)答方,Web 服務(wù)器可以向瀏覽器等 Web 客戶端提供文檔,也可以放置網(wǎng)站文件,讓全世界瀏覽;可以放置數(shù)據(jù)文件,讓全世界下載。目前最主流的三個Web服務(wù)器是Apache、 Nginx 、IIS。

          CDN

          CDN的全稱是Content Delivery Network,即內(nèi)容分發(fā)網(wǎng)絡(luò),它應(yīng)用了 HTTP 協(xié)議里的緩存和代理技術(shù),代替源站響應(yīng)客戶端的請求。CDN 是構(gòu)建在現(xiàn)有網(wǎng)絡(luò)基礎(chǔ)之上的網(wǎng)絡(luò),它依靠部署在各地的邊緣服務(wù)器,通過中心平臺的負載均衡、內(nèi)容分發(fā)、調(diào)度等功能模塊,使用戶就近獲取所需內(nèi)容,降低網(wǎng)絡(luò)擁塞,提高用戶訪問響應(yīng)速度和命中率。CDN的關(guān)鍵技術(shù)主要有內(nèi)容存儲和分發(fā)技術(shù)。

          打比方說你要去亞馬遜上買書,之前你只能通過購物網(wǎng)站購買后從美國發(fā)貨過海關(guān)等重重關(guān)卡送到你的家里,現(xiàn)在在中國建立一個亞馬遜分基地,你就不用通過美國進行郵寄,從中國就能把書盡快給你送到。

          WAF

          WAF 是一種 Web 應(yīng)用程序防護系統(tǒng)(Web Application Firewall,簡稱 WAF),它是一種通過執(zhí)行一系列針對HTTP / HTTPS的安全策略來專門為Web應(yīng)用提供保護的一款產(chǎn)品,它是應(yīng)用層面的防火墻,專門檢測 HTTP 流量,是防護 Web 應(yīng)用的安全技術(shù)。

          WAF 通常位于 Web 服務(wù)器之前,可以阻止如 SQL 注入、跨站腳本等攻擊,目前應(yīng)用較多的一個開源項目是 ModSecurity,它能夠完全集成進 Apache 或 Nginx。

          WebService

          WebService 是一種 Web 應(yīng)用程序,WebService是一種跨編程語言和跨操作系統(tǒng)平臺的遠程調(diào)用技術(shù)。

          Web Service 是一種由 W3C 定義的應(yīng)用服務(wù)開發(fā)規(guī)范,使用 client-server 主從架構(gòu),通常使用 WSDL 定義服務(wù)接口,使用 HTTP 協(xié)議傳輸 XML 或 SOAP 消息,它是一個基于 Web(HTTP)的服務(wù)架構(gòu)技術(shù),既可以運行在內(nèi)網(wǎng),也可以在適當保護后運行在外網(wǎng)。

          HTML

          HTML 稱為超文本標記語言,是一種標識性的語言。它包括一系列標簽.通過這些標簽可以將網(wǎng)絡(luò)上的文檔格式統(tǒng)一,使分散的 Internet 資源連接為一個邏輯整體。HTML 文本是由 HTML 命令組成的描述性文本,HTML 命令可以說明文字,圖形、動畫、聲音、表格、鏈接等。

          Web 頁面構(gòu)成

          Web 頁面(Web page)也叫做文檔,是由一個個對象組成的。一個對象(Objecy) 只是一個文件,比如一個 HTML 文件、一個 JPEG 圖形、一個 Java 小程序或一個視頻片段,它們在網(wǎng)絡(luò)中可以通過 URL 地址尋址。多數(shù)的 Web 頁面含有一個 HTML 基本文件 以及幾個引用對象。

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

          與 HTTP 有關(guān)的協(xié)議

          在互聯(lián)網(wǎng)中,任何協(xié)議都不會單獨的完成信息交換,HTTP 也一樣。雖然 HTTP 屬于應(yīng)用層的協(xié)議,但是它仍然需要其他層次協(xié)議的配合完成信息的交換,那么在完成一次 HTTP 請求和響應(yīng)的過程中,需要哪些協(xié)議的配合呢?一起來看一下

          TCP/IP

          TCP/IP 協(xié)議你一定聽過,TCP/IP 我們一般稱之為協(xié)議簇,什么意思呢?就是 TCP/IP 協(xié)議簇中不僅僅只有 TCP 協(xié)議和 IP 協(xié)議,它是一系列網(wǎng)絡(luò)通信協(xié)議的統(tǒng)稱。而其中最核心的兩個協(xié)議就是 TCP / IP 協(xié)議,其他的還有 UDP、ICMP、ARP 等等,共同構(gòu)成了一個復(fù)雜但有層次的協(xié)議棧。

          TCP 協(xié)議的全稱是 Transmission Control Protocol 的縮寫,意思是傳輸控制協(xié)議,HTTP 使用 TCP 作為通信協(xié)議,這是因為 TCP 是一種可靠的協(xié)議,而可靠能保證數(shù)據(jù)不丟失。

          IP 協(xié)議的全稱是 Internet Protocol 的縮寫,它主要解決的是通信雙方尋址的問題。IP 協(xié)議使用 IP 地址 來標識互聯(lián)網(wǎng)上的每一臺計算機,可以把 IP 地址想象成為你手機的電話號碼,你要與他人通話必須先要知道他人的手機號碼,計算機網(wǎng)絡(luò)中信息交換必須先要知道對方的 IP 地址。(關(guān)于 TCP 和 IP 更多的討論我們會在后面詳解)

          DNS

          你有沒有想過為什么你可以通過鍵入 www.google.com 就能夠獲取你想要的網(wǎng)站?我們上面說到,計算機網(wǎng)絡(luò)中的每個端系統(tǒng)都有一個 IP 地址存在,而把 IP 地址轉(zhuǎn)換為便于人類記憶的協(xié)議就是 DNS 協(xié)議。

          DNS 的全稱是域名系統(tǒng)(Domain Name System,縮寫:DNS),它作為將域名和 IP 地址相互映射的一個分布式數(shù)據(jù)庫,能夠使人更方便地訪問互聯(lián)網(wǎng)。

          URI / URL

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

          URI的全稱是(Uniform Resource Identifier),中文名稱是統(tǒng)一資源標識符,使用它就能夠唯一地標記互聯(lián)網(wǎng)上資源。

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

          URI 不僅包括 URL,還包括 URN(統(tǒng)一資源名稱),它們之間的關(guān)系如下

          HTTPS

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

          HTTP 請求響應(yīng)過程

          你是不是很好奇,當你在瀏覽器中輸入網(wǎng)址后,到底發(fā)生了什么事情?你想要的內(nèi)容是如何展現(xiàn)出來的?讓我們通過一個例子來探討一下,我們假設(shè)訪問的 URL 地址為 http://www.someSchool.edu/someDepartment/home.index,當我們輸入網(wǎng)址并點擊回車時,瀏覽器內(nèi)部會進行如下操作

          • DNS服務(wù)器會首先進行域名的映射,找到訪問www.someSchool.edu所在的地址,然后HTTP 客戶端進程在 80 端口發(fā)起一個到服務(wù)器 www.someSchool.edu 的 TCP 連接(80 端口是 HTTP 的默認端口)。在客戶和服務(wù)器進程中都會有一個套接字與其相連。

          • HTTP 客戶端通過它的套接字向服務(wù)器發(fā)送一個 HTTP 請求報文。該報文中包含了路徑 someDepartment/home.index 的資源,我們后面會詳細討論 HTTP 請求報文。

          • HTTP 服務(wù)器通過它的套接字接受該報文,進行請求的解析工作,并從其存儲器(RAM 或磁盤)中檢索出對象 www.someSchool.edu/someDepartment/home.index,然后把檢索出來的對象進行封裝,封裝到 HTTP 響應(yīng)報文中,并通過套接字向客戶進行發(fā)送。

          • HTTP 服務(wù)器隨即通知 TCP 斷開 TCP 連接,實際上是需要等到客戶接受完響應(yīng)報文后才會斷開 TCP 連接。

          • HTTP 客戶端接受完響應(yīng)報文后,TCP 連接會關(guān)閉。HTTP 客戶端從響應(yīng)中提取出報文中是一個 HTML 響應(yīng)文件,并檢查該 HTML 文件,然后循環(huán)檢查報文中其他內(nèi)部對象。

          • 檢查完成后,HTTP 客戶端會把對應(yīng)的資源通過顯示器呈現(xiàn)給用戶。

          至此,鍵入網(wǎng)址再按下回車的全過程就結(jié)束了。上述過程描述的是一種簡單的請求-響應(yīng)全過程,真實的請求-響應(yīng)情況可能要比上面描述的過程復(fù)雜很多。

          HTTP 請求特征

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

          • 支持客戶-服務(wù)器模式

          • 簡單快速:客戶向服務(wù)器請求服務(wù)時,只需傳送請求方法和路徑。請求方法常用的有 GET、HEAD、POST。每種方法規(guī)定了客戶與服務(wù)器聯(lián)系的類型不同。由于 HTTP 協(xié)議簡單,使得 HTTP 服務(wù)器的程序規(guī)模小,因而通信速度很快。

          • 靈活:HTTP 允許傳輸任意類型的數(shù)據(jù)對象。正在傳輸?shù)念愋陀?Content-Type 加以標記。

          • 無連接:無連接的含義是限制每次連接只處理一個請求。服務(wù)器處理完客戶的請求,并收到客戶的應(yīng)答后,即斷開連接。采用這種方式可以節(jié)省傳輸時間。

          • 無狀態(tài):HTTP 協(xié)議是無狀態(tài)協(xié)議。無狀態(tài)是指協(xié)議對于事務(wù)處理沒有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。另一方面,在服務(wù)器不需要先前信息時它的應(yīng)答就較快。

          詳解 HTTP 報文

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

          HTTP 協(xié)議主要由三大部分組成:

          • 起始行(start line):描述請求或響應(yīng)的基本信息;

          • 頭部字段(header):使用 key-value 形式更詳細地說明報文;

          • 消息正文(entity):實際傳輸?shù)臄?shù)據(jù),它不一定是純文本,可以是圖片、視頻等二進制數(shù)據(jù)。

          其中起始行和頭部字段并成為 請求頭 或者 響應(yīng)頭,統(tǒng)稱為 Header;消息正文也叫做實體,稱為 body。HTTP 協(xié)議規(guī)定每次發(fā)送的報文必須要有 Header,但是可以沒有 body,也就是說頭信息是必須的,實體信息可以沒有。而且在 header 和 body 之間必須要有一個空行(CRLF),如果用一幅圖來表示一下的話,我覺得應(yīng)該是下面這樣

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

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

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

          HTTP 請求方法

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

          • GET 獲取資源,GET 方法用來請求訪問已被 URI 識別的資源。指定的資源經(jīng)服務(wù)器端解析后返回響應(yīng)內(nèi)容。也就是說,如果請求的資源是文本,那就保持原樣返回;

          • POST 傳輸實體,雖然 GET 方法也可以傳輸主體信息,但是便于區(qū)分,我們一般不用 GET 傳輸實體信息,反而使用 POST 傳輸實體信息,

          • PUT 傳輸文件,PUT 方法用來傳輸文件。就像 FTP 協(xié)議的文件上傳一樣,要求在請求報文的主體中包含文件內(nèi)容,然后保存到請求 URI 指定的位置。

            但是,鑒于 HTTP 的 PUT 方法自身不帶驗證機制,任何人都可以上傳文件 , 存在安全性問題,因此一般的 W eb 網(wǎng)站不使用該方法。若配合 W eb 應(yīng)用程序的驗證機制,或架構(gòu)設(shè)計采用REST(REpresentational State Transfer,表征狀態(tài)轉(zhuǎn)移)標準的同類 Web 網(wǎng)站,就可能會開放使用 PUT 方法。

          • HEAD 獲得響應(yīng)首部,HEAD 方法和 GET 方法一樣,只是不返回報文主體部分。用于確認 URI 的有效性及資源更新的日期時間等。

          • DELETE 刪除文件,DELETE 方法用來刪除文件,是與 PUT 相反的方法。DELETE 方法按請求 URI 刪除指定的資源。

          • OPTIONS 詢問支持的方法,OPTIONS 方法用來查詢針對請求 URI 指定的資源支持的方法。

          • TRACE 追蹤路徑,TRACE 方法是讓 Web 服務(wù)器端將之前的請求通信環(huán)回給客戶端的方法。

          • CONNECT 要求用隧道協(xié)議連接代理,CONNECT 方法要求在與代理服務(wù)器通信時建立隧道,實現(xiàn)用隧道協(xié)議進行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協(xié)議把通信內(nèi)容加 密后經(jīng)網(wǎng)絡(luò)隧道傳輸。

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

          HTTP 請求 URL

          HTTP 協(xié)議使用 URI 定位互聯(lián)網(wǎng)上的資源。正是因為 URI 的特定功能,在互聯(lián)網(wǎng)上任意位置的資源都能訪問到。URL 帶有請求對象的標識符。在上面的例子中,瀏覽器正在請求對象/somedir/page.html 的資源。

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

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

          首先出場的是 http

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

          第二個出場的是 主機

          www.example.com 既是一個域名,也代表管理該域名的機構(gòu)。它指示了需要向網(wǎng)絡(luò)上的哪一臺主機發(fā)起請求。當然,也可以直接向主機的 IP address 地址發(fā)起請求。但直接使用 IP 地址的場景并不常見。

          第三個出場的是 端口

          我們前面說到,兩個主機之間要發(fā)起 TCP 連接需要兩個條件,主機 + 端口。它表示用于訪問 Web 服務(wù)器上資源的入口。如果訪問的該 Web 服務(wù)器使用HTTP協(xié)議的標準端口(HTTP為80,HTTPS為443)授予對其資源的訪問權(quán)限,則通常省略此部分。否則端口就是 URI 必須的部分。

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

          第四個出場的是 路徑

          /path/to/myfile.html 是 Web 服務(wù)器上資源的路徑。以端口后面的第一個 / 開始,到 ? 號之前結(jié)束,中間的 每一個/ 都代表了層級(上下級)關(guān)系。這個 URL 的請求資源是一個 html 頁面。

          緊跟著路徑后面的是 查詢參數(shù)

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

          緊跟著參數(shù)的是錨點

          #SomewhereInTheDocument 是資源本身的某一部分的一個錨點。錨點代表資源內(nèi)的一種“書簽”,它給予瀏覽器顯示位于該“加書簽”點的內(nèi)容的指示。例如,在HTML文檔上,瀏覽器將滾動到定義錨點的那個點上;在視頻或音頻文檔上,瀏覽器將轉(zhuǎn)到錨點代表的那個時間。值得注意的是 # 號后面的部分,也稱為片段標識符,永遠不會與請求一起發(fā)送到服務(wù)器。

          HTTP 版本

          表示報文使用的 HTTP 協(xié)議版本。

          請求頭部

          這部分內(nèi)容只是大致介紹一下,內(nèi)容較多,后面會再以一篇文章詳述。

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

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

          這個請求頭信息比較少,首先 Host 表示的是對象所在的主機。你也許認為這個 Host 是不需要的,因為 URL 不是已經(jīng)指明了請求對象的路徑了嗎?這個首部行提供的信息是 Web 代理高速緩存所需要的。Connection: close 表示的是瀏覽器需要告訴服務(wù)器使用的是非持久連接。它要求服務(wù)器在發(fā)送完響應(yīng)的對象后就關(guān)閉連接。User-agent: 這是請求頭用來告訴 Web 服務(wù)器,瀏覽器使用的類型是 Mozilla/5.0,即 Firefox 瀏覽器。Accept-language 告訴 Web 服務(wù)器,瀏覽器想要得到對象的法語版本,前提是服務(wù)器需要支持法語類型,否則將會發(fā)送服務(wù)器的默認版本。下面我們針對主要的實體字段進行介紹(具體的可以參考 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers MDN 官網(wǎng)學(xué)習(xí))

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

          通用標頭

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

          Date

          Date 是一個通用標頭,它可以出現(xiàn)在請求標頭和響應(yīng)標頭中,它的基本表示如下

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

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

          Cache-Control

          Cache-Control 是一個通用標頭,他可以出現(xiàn)在請求標頭和響應(yīng)標頭中,Cache-Control 的種類比較多,雖然說這是一個通用標頭,但是有一些特性是請求標頭具有的,有一些是響應(yīng)標頭才有的。主要大類有 可緩存性、閾值性、 重新驗證并重新加載 和其他特性

          可緩存性是唯一響應(yīng)標頭才具有的特性,我們會在響應(yīng)標頭中詳述。

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

          • max-age: 資源被認為仍然有效的最長時間,與 Expires 不同,這個請求是相對于 request標頭的時間,而 Expires 是相對于響應(yīng)標頭。(請求標頭)

          • s-maxage: 重寫了 max-age 和 Expires 請求頭,僅僅適用于共享緩存,被私有緩存所忽略(這塊不理解,看完響應(yīng)頭的 Cache-Control 再進行理解)(請求標頭)

          • max-stale:表示客戶端將接受的最大響應(yīng)時間,以秒為單位。(響應(yīng)標頭)

          • min-fresh: 表示客戶端希望響應(yīng)在指定的最小時間內(nèi)有效。(響應(yīng)標頭)

          Connection

          Connection 決定當前事務(wù)(一次三次握手和四次揮手)完成后,是否會關(guān)閉網(wǎng)絡(luò)連接。Connection 有兩種,一種是持久性連接,即一次事務(wù)完成后不關(guān)閉網(wǎng)絡(luò)連接

          Connection: keep-alive

          另一種是非持久性連接,即一次事務(wù)完成后關(guān)閉網(wǎng)絡(luò)連接

          Connection: close

          HTTP1.1 其他通用標頭如下

          實體標頭

          實體標頭是描述消息正文內(nèi)容的 HTTP 標頭。實體標頭用于 HTTP 請求和響應(yīng)中。頭部Content-Length、 Content-Language、 Content-Encoding 是實體頭。

          • Content-Length 實體報頭指示實體主體的大小,以字節(jié)為單位,發(fā)送到接收方。

          • Content-Language 實體報頭描述了客戶端或者服務(wù)端能夠接受的語言,例如

          Content-Language: de-DE
          Content-Language: en-US
          Content-Language: de-DE, en-CA
          • Content-Encoding 這又是一個比較麻煩的屬性,這個實體報頭用來壓縮媒體類型。Content-Encoding 指示對實體應(yīng)用了何種編碼。

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

          Accept-Encoding: gzip, deflate //請求頭
          Content-Encoding: gzip //響應(yīng)頭

          下面是一些實體標頭字段

          請求標頭

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

          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 請求頭指明了服務(wù)器的域名(對于虛擬主機來說),以及(可選的)服務(wù)器監(jiān)聽的TCP端口號。如果沒有給定端口號,會自動使用被請求服務(wù)的默認端口(比如請求一個 HTTP 的 URL 會自動使用80作為端口)。

          Host: developer.mozilla.org

          上面的 Accpet、 Accept-Language、Accept-Encoding 都是屬于內(nèi)容協(xié)商的請求標頭,我們會在下面說明

          Referer

          HTTP Referer 屬性是請求標頭的一部分,當瀏覽器向 web 服務(wù)器發(fā)送請求的時候,一般會帶上 Referer,告訴服務(wù)器該網(wǎng)頁是從哪個頁面鏈接過來的,服務(wù)器因此可以獲得一些信息用于處理。

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

          Upgrade-Insecure-Requests

          Upgrade-Insecure-Requests 是一個請求標頭,用來向服務(wù)器端發(fā)送信號,表示客戶端優(yōu)先選擇加密及帶有身份驗證的響應(yīng)。

          Upgrade-Insecure-Requests: 1

          If-Modified-Since

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

          • 返回200,只有在給定日期的最后一次修改資源后,服務(wù)器才會以200狀態(tài)發(fā)送回請求的資源。

          • 如果請求從開始以來沒有被修改過,響應(yīng)會返回304并且沒有任何響應(yīng)體

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

          大白話說就是如果在 Last-Modified 之后更新了服務(wù)器資源,那么服務(wù)器會響應(yīng)200,如果在Last-Modified 之后沒有更新過資源,則返回 304。

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

          If-None-Match

          If-None-Match HTTP請求標頭使請求成為條件請求。對于 GET 和 HEAD 方法,僅當服務(wù)器沒有與給定資源匹配的 ETag 時,服務(wù)器才會以200狀態(tài)發(fā)送回請求的資源。對于其他方法,僅當最終現(xiàn)有資源的ETag與列出的任何值都不匹配時,才會處理請求。

          If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"

          ETag 屬于響應(yīng)標頭,后面進行介紹。

          內(nèi)容協(xié)商

          內(nèi)容協(xié)商機制是指客戶端和服務(wù)器端就響應(yīng)的資源內(nèi)容進行交涉,然后提供給客戶端最為適合的資源。內(nèi)容協(xié)商會以響應(yīng)資源的語言、字符集、編碼方式等作為判斷的標準。

          內(nèi)容協(xié)商主要有以下3種類型:

          • 服務(wù)器驅(qū)動協(xié)商(Server-driven Negotiation)

          這種協(xié)商方式是由服務(wù)器端進行內(nèi)容協(xié)商。服務(wù)器端會根據(jù)請求首部字段進行自動處理

          • 客戶端驅(qū)動協(xié)商(Agent-driven Negotiation)

          這種協(xié)商方式是由客戶端來進行內(nèi)容協(xié)商。

          • 透明協(xié)商(Transparent Negotiation)

          是服務(wù)器驅(qū)動和客戶端驅(qū)動的結(jié)合體,是由服務(wù)器端和客戶端各自進行內(nèi)容協(xié)商的一種方法。

          內(nèi)容協(xié)商的分類有很多種,主要的幾種類型是 Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language。

          Accept

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

          那么什么是 MIME 類型呢?在回答這個問題前你應(yīng)該先了解一下什么是 MIME

          MIME: MIME (Multipurpose Internet Mail Extensions) 是描述消息內(nèi)容類型的因特網(wǎng)標準。MIME 消息能包含文本、圖像、音頻、視頻以及其他應(yīng)用程序?qū)S玫臄?shù)據(jù)。

          也就是說,MIME 類型其實就是一系列消息內(nèi)容類型的集合。那么 MIME 類型都有哪些呢?

          文本文件:text/html、text/plain、text/css、application/xhtml+xml、application/xml

          圖片文件:image/jpeg、image/gif、image/png

          視頻文件:video/mpeg、video/quicktime

          應(yīng)用程序二進制文件:application/octet-stream、application/zip

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

          一般 MIME 類型也會和 q 這個屬性一起使用,q 是什么?q 表示的是權(quán)重,來看一個例子

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

          這是什么意思呢?若想要給顯示的媒體類型增加優(yōu)先級,則使用 q= 來額外表示權(quán)重值,沒有顯示權(quán)重的時候默認值是1.0 ,我給你列個表格你就明白了

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

          Accept-Charset

          accept-charset 屬性規(guī)定服務(wù)器處理表單數(shù)據(jù)所接受的字符集。

          accept-charset 屬性允許您指定一系列字符集,服務(wù)器必須支持這些字符集,從而得以正確解釋表單中的數(shù)據(jù)。

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

          此屬性的默認值是 unknown,表示表單的字符集與包含表單的文檔的字符集相同。

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

          Accept-Language

          首部字段 Accept-Language 用來告知服務(wù)器用戶代理能夠處理的自然語言集(指中文或英文等),以及自然語言集的相對優(yōu)先級。可一次指定多種自然語言集。和 Accept 首部字段一樣,按權(quán)重值 q來表示相對優(yōu)先級。

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

          請求標頭我們大概就介紹這幾種,后面會有一篇文章詳細深挖所有的響應(yīng)頭的,下面是一個響應(yīng)頭的匯總,基于 HTTP 1.1

          響應(yīng)標頭

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

          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

          響應(yīng)狀態(tài)碼

          首先出現(xiàn)的應(yīng)該就是 200 OK,這是 HTTP 響應(yīng)標頭的狀態(tài)碼,它表示著響應(yīng)成功完成。HTTP 響應(yīng)標頭的狀態(tài)碼有很多,并做了如下規(guī)定

          以 2xx 為開頭的都表示請求成功響應(yīng)。

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

          以 4xx 的響應(yīng)結(jié)果表明客戶端是發(fā)生錯誤的原因所在。

          以 5xx 為開頭的響應(yīng)標頭都表示服務(wù)器本身發(fā)生錯誤

          Access-Control-Allow-Origin

          一個返回的 HTTP 標頭可能會具有 Access-Control-Allow-Origin ,Access-Control-Allow-Origin 指定一個來源,它告訴瀏覽器允許該來源進行資源訪問。否則-對于沒有憑據(jù)的請求 *通配符,告訴瀏覽器允許任何源訪問資源。例如,要允許源 https://mozilla.org 的代碼訪問資源,可以指定:

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

          如果服務(wù)器指定單個來源而不是 *通配符的話 ,則服務(wù)器還應(yīng)在 Vary 響應(yīng)標頭中包含 Origin ,以向客戶端指示 服務(wù)器響應(yīng)將根據(jù)原始請求標頭的值而有所不同。

          Keep-Alive

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

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

          而 Keep-Alive 表示的是 Connection 非持續(xù)連接的存活時間,如下

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

          Keep-Alive 有兩個參數(shù),它們是以逗號分隔的參數(shù)列表,每個參數(shù)由一個標識符和一個由等號 = 分隔的值組成。

          timeout:指示空閑連接必須保持打開狀態(tài)的最短時間(以秒為單位)。

          max:指示在關(guān)閉連接之前可以在此連接上發(fā)送的最大請求數(shù)。

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

          Server

          服務(wù)器標頭包含有關(guān)原始服務(wù)器用來處理請求的軟件的信息。

          應(yīng)該避免使用過于冗長和詳細的 Server 值,因為它們可能會泄露內(nèi)部實施細節(jié),這可能會使攻擊者容易地發(fā)現(xiàn)并利用已知的安全漏洞。例如下面這種寫法

          Server: Apache/2.4.1 (Unix)

          Set-Cookie

          Cookie 又是另外一個領(lǐng)域的內(nèi)容了,我們后面文章會說道 Cookie,這里需要記住 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部字段,它們不是屬于 HTTP 1.1 的首部字段,但是使用率仍然很高。

          Transfer-Encoding

          首部字段 Transfer-Encoding 規(guī)定了傳輸報文主體時采用的編碼方式。

          Transfer-Encoding: chunked

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

          X-Frame-Options

          HTTP 首部字段是可以自行擴展的。所以在 Web 服務(wù)器和瀏覽器的應(yīng)用上,會出現(xiàn)各種非標準的首部字段。

          首部字段 X-Frame-Options 屬于 HTTP 響應(yīng)首部,用于控制網(wǎng)站內(nèi)容在其他 Web 網(wǎng)站的 Frame 標簽內(nèi)的顯示問題。其主要目的是為了防止點擊劫持(clickjacking)攻擊。

          下面是一個響應(yīng)頭的匯總,基于 HTTP 1.1

          非 HTTP/1.1 首部字段

          在 HTTP 協(xié)議通信交互中使用到的首部字段,不限于 RFC2616 中定義的 47 種首部字段。還有 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部字段,它們的使用頻率也很高。這些非正式的首部字段統(tǒng)一歸納在 RFC4229 HTTP Header Field Registrations 中。

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

          HTTP 首部字段將定義成緩存代理和非緩存代理的行為,分成 2 種類型。

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

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

          這些標頭必須發(fā)送給消息的最終接收者 : 請求的服務(wù)器,或響應(yīng)的客戶端。中間代理必須重新傳輸未經(jīng)修改的標頭,并且緩存必須存儲這些信息

          Hop-by-hop(逐跳) 首部

          分在此類別中的首部只對單次轉(zhuǎn)發(fā)有效,會因通過緩存或代理而不再轉(zhuǎn)發(fā)。

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

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

          HTTP 的優(yōu)點和缺點

          HTTP 的優(yōu)點

          簡單靈活易擴展

          HTTP 最重要也是最突出的優(yōu)點是 簡單、靈活、易于擴展。

          HTTP 的協(xié)議比較簡單,它的主要組成就是 header + body,頭部信息也是簡單的文本格式,而且 HTTP 的請求報文根據(jù)英文也能猜出來個大概的意思,降低學(xué)習(xí)門檻,能夠讓更多的人研究和開發(fā) HTTP 應(yīng)用。

          所以,在簡單的基礎(chǔ)上,HTTP 協(xié)議又多了靈活 和 易擴展 的優(yōu)點。

          HTTP 協(xié)議里的請求方法、URI、狀態(tài)碼、原因短語、頭字段等每一個核心組成要素都沒有被制定死,允許開發(fā)者任意定制、擴充或解釋,給予了瀏覽器和服務(wù)器最大程度的信任和自由。

          應(yīng)用廣泛、環(huán)境成熟

          因為過于簡單,普及,因此應(yīng)用很廣泛。因為 HTTP 協(xié)議本身不屬于一種語言,它并不限定某種編程語言或者操作系統(tǒng),所以天然具有跨語言、跨平臺的優(yōu)越性。而且,因為本身的簡單特性很容易實現(xiàn),所以幾乎所有的編程語言都有 HTTP 調(diào)用庫和外圍的開發(fā)測試工具。

          隨著移動互聯(lián)網(wǎng)的發(fā)展, HTTP 的觸角已經(jīng)延伸到了世界的每一個角落,從簡單的 Web 頁面到復(fù)雜的 JSON、XML 數(shù)據(jù),從臺式機上的瀏覽器到手機上的各種 APP、新聞、論壇、購物、手機游戲,你很難找到一個沒有使用 HTTP 的地方。

          無狀態(tài)

          無狀態(tài)其實既是優(yōu)點又是缺點。因為服務(wù)器沒有記憶能力,所以就不需要額外的資源來記錄狀態(tài)信息,不僅實現(xiàn)上會簡單一些,而且還能減輕服務(wù)器的負擔(dān),能夠把更多的 CPU 和內(nèi)存用來對外提供服務(wù)。

          HTTP 的缺點

          無狀態(tài)

          既然服務(wù)器沒有記憶能力,它就無法支持需要連續(xù)多個步驟的事務(wù)操作。每次都得問一遍身份信息,不僅麻煩,而且還增加了不必要的數(shù)據(jù)傳輸量。由此出現(xiàn)了 Cookie 技術(shù)。

          明文

          HTTP 協(xié)議里還有一把優(yōu)缺點一體的雙刃劍,就是明文傳輸。明文意思就是協(xié)議里的報文(準確地說是 header 部分)不使用二進制數(shù)據(jù),而是用簡單可閱讀的文本形式。

          對比 TCP、UDP 這樣的二進制協(xié)議,它的優(yōu)點顯而易見,不需要借助任何外部工具,用瀏覽器、Wireshark 或者 tcpdump 抓包后,直接用肉眼就可以很容易地查看或者修改,為我們的開發(fā)調(diào)試工作帶來極大的便利。

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

          性能

          HTTP 的性能不算差,但不完全適應(yīng)現(xiàn)在的互聯(lián)網(wǎng),還有很大的提升空間。

          參考資料:

          https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Technical_overview

          https://developer.mozilla.org/en-US/docs/Web/HTTP

          https://baike.baidu.com/item/WEB服務(wù)器/8390210?fr=aladdin

          https://baike.baidu.com/item/內(nèi)容分發(fā)網(wǎng)絡(luò)/4034265

          https://baike.baidu.com/item/HTML/97049?fr=aladdin

          https://www.jianshu.com/p/3dd8f1879acb

          《計算機網(wǎng)絡(luò)-自頂向下方法》

          《圖解 HTTP》

          HTTP協(xié)議的內(nèi)容協(xié)商

          https://www.w3school.com.cn/tags/att_form_accept_charset.asp

          通常HTTP消息包括客戶機向服務(wù)器的請求消息和服務(wù)器向客戶機的響應(yīng)消息。客戶端向服務(wù)器發(fā)送一個請求,請求頭包含請求的方法、URI、協(xié)議版本、以及包含請求修飾符、客戶信息和內(nèi)容的類似于MIME的消息結(jié)構(gòu)。服務(wù)器以一個狀態(tài)行作為響應(yīng),相應(yīng)的內(nèi)容包括消息協(xié)議的版本,成功或者錯誤編碼加上包含服務(wù)器信息、實體元信息以及可能的實體內(nèi)容。

          Http協(xié)議定義了很多與服務(wù)器交互的方法,最基本的有4種,分別是GET、POST、PUT、DELETE。一個URL地址用于描述一個網(wǎng)絡(luò)上的資源,而HTTP中的GET、POST、PUT、 DELETE就對應(yīng)著對這個資源的查、改、增、刪4個操作,我們最常見的就是GET和POST了。GET一般用于獲取/查詢資源信息,而POST一般用于更新資源信息。

          一、HTTP頭信息解讀

            HTTP的頭域包括通用頭、請求頭、響應(yīng)頭和實體頭四個部分。每個頭域由一個域名,冒號(:)和域值三部分組成。

            通用頭部:是客戶端和服務(wù)器都可以使用的頭部,可以在客戶端、服務(wù)器和其他應(yīng)用程序之間提供一些非常有用的通用功能,如Date頭部。

            請求頭部:是請求報文特有的,它們?yōu)榉?wù)器提供了一些額外信息,比如客戶端希望接收什么類型的數(shù)據(jù),如Accept頭部。

            響應(yīng)頭部:便于客戶端提供信息,比如,客服端在與哪種類型的服務(wù)器進行交互,如Server頭部。

            實體頭部:指的是用于應(yīng)對實體主體部分的頭部,比如,可以用實體頭部來說明實體主體部分的數(shù)據(jù)類型,如Content-Type頭部。


          HTTP通用頭

            通用頭域包含請求和響應(yīng)消息都支持的頭域,通用頭域包含緩存頭部Cache-Control、Pragma及信息性頭部Connection、Date、Transfer-Encoding、Update、Via。

            1、Cache-Control

            Cache-Control指定請求和響應(yīng)遵循的緩存機制。在請求消息或響應(yīng)消息中設(shè)置 Cache-Control并不會修改另一個消息處理過程中的緩存處理過程。請求時的緩存指令包括no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached,響應(yīng)消息中的指令包括public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。各個消息中的指令含義如下:

            no-cache:指示請求或響應(yīng)消息不能緩存,實際上是可以存儲在本地緩存區(qū)中的,只是在與原始服務(wù)器進行新鮮度驗證之前,緩存不能將其提供給客戶端使用。 

            no-store:緩存應(yīng)該盡快從存儲器中刪除文檔的所有痕跡,因為其中可能會包含敏感信息。

            max-age:緩存無法返回緩存時間長于max-age規(guī)定秒的文檔,若不超規(guī)定秒瀏覽器將不會發(fā)送對應(yīng)的請求到服務(wù)器,數(shù)據(jù)由緩存直接返回;超過這一時間段才進一步由服務(wù)器決定是返回新數(shù)據(jù)還是仍由緩存提供。若同時還發(fā)送了max-stale指令,則使用期可能會超過其過期時間。

            min-fresh:至少在未來規(guī)定秒內(nèi)文檔要保持新鮮,接受其新鮮生命期大于其當前 Age 跟 min-fresh 值之和的緩存對象。

            max-stale:指示客戶端可以接收過期響應(yīng)消息,如果指定max-stale消息的值,那么客戶端可以接收過期但在指定值之內(nèi)的響應(yīng)消息。

            only-if-cached:只有當緩存中有副本存在時,客戶端才會獲得一份副本。

            Public:指示響應(yīng)可被任何緩存區(qū)緩存,可以用緩存內(nèi)容回應(yīng)任何用戶。

            Private:指示對于單個用戶的整個或部分響應(yīng)消息,不能被共享緩存處理,只能用緩存內(nèi)容回應(yīng)先前請求該內(nèi)容的那個用戶。

            2、Pragma

            Pragma頭域用來包含實現(xiàn)特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1協(xié)議中,它的含義和Cache- Control:no-cache相同。

            3、Connection

            Connection表示是否需要持久連接。如果Servlet看到這里的值為“Keep-Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久連接),它就可以利用持久連接的優(yōu)點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現(xiàn)這一點,Servlet需要在應(yīng)答中發(fā)送一個Content-Length頭,最簡單的實現(xiàn)方法是:先把內(nèi)容寫入ByteArrayOutputStream,然后在正式寫出內(nèi)容之前計算它的大小。

            Close:告訴WEB服務(wù)器或者代理服務(wù)器,在完成本次請求的響應(yīng)后,斷開連接,不要等待本次連接的后續(xù)請求了。

            Keepalive:告訴WEB服務(wù)器或者代理服務(wù)器,在完成本次請求的響應(yīng)后,保持連接,等待本次連接的后續(xù)請求。

            Keep-Alive:如果瀏覽器請求保持連接,則該頭部表明希望 WEB 服務(wù)器保持連接多長時間(秒),如Keep-Alive:300。

            4、Date

            Date頭域表示消息發(fā)送的時間,服務(wù)器響應(yīng)中要包含這個頭部,因為緩存在評估響應(yīng)的新鮮度時要用到,其時間的描述格式由RFC822定義。例如,Date:Mon, 31 Dec 2001 04:25:57 GMT。Date描述的時間表示世界標準時,換算成本地時間,需要知道用戶所在的時區(qū)。

            5、Transfer-Encoding

            WEB 服務(wù)器表明自己對本響應(yīng)消息體(不是消息體里面的對象)作了怎樣的編碼,比如是否分塊(chunked),例如:Transfer-Encoding: chunked

            6、Upgrade

            它可以指定另一種可能完全不同的協(xié)議,如HTTP/1.1客戶端可以向服務(wù)器發(fā)送一條HTTP/1.0請求,其中包含值為“HTTP/1.1”的Update頭部,這樣客戶端就可以測試一下服務(wù)器是否也使用HTTP/1.1了。

            7、Via

            列出從客戶端到 OCS 或者相反方向的響應(yīng)經(jīng)過了哪些代理服務(wù)器,他們用什么協(xié)議(和版本)發(fā)送的請求。

            當客戶端請求到達第一個代理服務(wù)器時,該服務(wù)器會在自己發(fā)出的請求里面添加 Via 頭部,并填上自己的相關(guān)信息,當下一個代理服務(wù)器 收到第一個代理服務(wù)器的請求時,會在自己發(fā)出的請求里面復(fù)制前一個代理服務(wù)器的請求的Via頭部,并把自己的相關(guān)信息加到后面,以此類推,當 OCS 收到最后一個代理服務(wù)器的請求時,檢查 Via 頭部,就知道該請求所經(jīng)過的路由。例如:Via:1.0 236-81.D07071953.sina.com.cn:80 (squid/2.6.STABLE13)


          HTTP請求頭

            請求頭用于說明是誰或什么在發(fā)送請求、請求源于何處,或者客戶端的喜好及能力。服務(wù)器可以根據(jù)請求頭部給出的客戶端信息,試著為客戶端提供更好的響應(yīng)。請求頭域可能包含下列字段Accept、Accept-Charset、Accept- Encoding、Accept-Language、Authorization、From、Host、If-Modified-Since、If-Match、If-None-Match、If-Range、If-Range、If-Unmodified-Since、Max-Forwards、Proxy-Authorization、Range、Referer、User-Agent。對請求頭域的擴展要求通訊雙方都支持,如果存在不支持的請求頭域,一般將會作為實體頭域處理。

            8、Accept

            告訴WEB服務(wù)器自己接受什么介質(zhì)類型,*/* 表示任何類型,type/* 表示該類型下的所有子類型,type/sub-type。

            9、Accept-Charset

            瀏覽器告訴服務(wù)器自己能接收的字符集。

            10、Accept-Encoding

            瀏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支持壓縮,支持什么壓縮方法(gzip,deflate)。

            11、Accept-Language

            瀏覽器申明自己接收的語言。語言跟字符集的區(qū)別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等。

            12、Authorization

            當客戶端接收到來自WEB服務(wù)器的 WWW-Authenticate 響應(yīng)時,用該頭部來回應(yīng)自己的身份驗證信息給WEB服務(wù)器。

            13、If-Match

            如果對象的 ETag 沒有改變,其實也就意味著對象沒有改變,才執(zhí)行請求的動作,獲取文檔。

            14、If-None-Match

            如果對象的 ETag 改變了,其實也就意味著對象也改變了,才執(zhí)行請求的動作,獲取文檔。

            15、If-Modified-Since

            如果請求的對象在該頭部指定的時間之后修改了,才執(zhí)行請求的動作(比如返回對象),否則返回代碼304,告訴瀏覽器該對象沒有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT

            16、If-Unmodified-Since

            如果請求的對象在該頭部指定的時間之后沒修改過,才執(zhí)行請求的動作(比如返回對象)。

            17、If-Range

            瀏覽器告訴 WEB 服務(wù)器,如果我請求的對象沒有改變,就把我缺少的部分給我,如果對象改變了,就把整個對象給我。瀏覽器通過發(fā)送請求對象的ETag 或者自己所知道的最后修改時間給 WEB 服務(wù)器,讓其判斷對象是否改變了。總是跟 Range 頭部一起使用。

            18、Range

            瀏覽器(比如 Flashget 多線程下載時)告訴 WEB 服務(wù)器自己想取對象的哪部分。例如:Range: bytes=1173546

            19、Proxy-Authenticate

            代理服務(wù)器響應(yīng)瀏覽器,要求其提供代理身份驗證信息。

            20、Proxy-Authorization

            瀏覽器響應(yīng)代理服務(wù)器的身份驗證請求,提供自己的身份信息。

            21、Host

            客戶端指定自己想訪問的WEB服務(wù)器的域名/IP 地址和端口號。如Host:rss.sina.com.cn

            22、Referer

            瀏覽器向WEB 服務(wù)器表明自己是從哪個網(wǎng)頁URL獲得點擊當前請求中的網(wǎng)址/URL,例如:Referer:http://www.ecdoer.com/

            23、User-Agent

            瀏覽器表明自己的身份(是哪種瀏覽器)。例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN;rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14


          HTTP響應(yīng)頭

            響應(yīng)頭向客戶端提供一些額外信息,比如誰在發(fā)送響應(yīng)、響應(yīng)者的功能,甚至與響應(yīng)相關(guān)的一些特殊指令。這些頭部有助于客戶端處理響應(yīng),并在將來發(fā)起更好的請求。響應(yīng)頭域包含Age、Location、Proxy-Authenticate、Public、Retry- After、Server、Vary、Warning、WWW-Authenticate。對響應(yīng)頭域的擴展要求通訊雙方都支持,如果存在不支持的響應(yīng)頭域,一般將會作為實體頭域處理。

            24、Age

            當代理服務(wù)器用自己緩存的實體去響應(yīng)請求時,用該頭部表明該實體從產(chǎn)生到現(xiàn)在經(jīng)過多長時間了。

            25、Server

            WEB 服務(wù)器表明自己是什么軟件及版本等信息。例如:Server:Apache/2.0.61 (Unix)

            26、Accept-Ranges

            WEB服務(wù)器表明自己是否接受獲取其某個實體的一部分(比如文件的一部分)的請求。bytes:表示接受,none:表示不接受。

            27、Vary

            WEB服務(wù)器用該頭部的內(nèi)容告訴 Cache 服務(wù)器,在什么條件下才能用本響應(yīng)所返回的對象響應(yīng)后續(xù)的請求。假如源WEB服務(wù)器在接到第一個請求消息時,其響應(yīng)消息的頭部為:Content-Encoding: gzip; Vary: Content-Encoding,那么Cache服務(wù)器會分析后續(xù)請求消息的頭部,檢查其Accept-Encoding,是否跟先前響應(yīng)的Vary頭部值一致,即是否使用相同的內(nèi)容編碼方法,這樣就可以防止Cache服務(wù)器用自己Cache 里面壓縮后的實體響應(yīng)給不具備解壓能力的瀏覽器。例如:Vary:Accept-Encoding。


          HTTP實體頭

            實體頭部提供了有關(guān)實體及其內(nèi)容的大量信息,從有關(guān)對象類型的信息,到能夠?qū)Y源使用的各種有效的請求方法。總之,實體頭部可以告知接收者它在對什么進行處理。請求消息和響應(yīng)消息都可以包含實體信息,實體信息一般由實體頭域和實體組成。實體頭域包含關(guān)于實體的原信息,實體頭包括信息性頭部Allow、Location,內(nèi)容頭部Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type,緩存頭部Etag、Expires、Last-Modified、extension-header。

            28、Allow

            服務(wù)器支持哪些請求方法(如GET、POST等)。

            29、Location

            表示客戶應(yīng)當?shù)侥睦锶ヌ崛∥臋n,用于將接收端定位到資源的位置(URL)上。Location通常不是直接設(shè)置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設(shè)置狀態(tài)代碼為302。

            30、Content-Base

            解析主體中的相對URL時使用的基礎(chǔ)URL。

            31、Content-Encoding

            WEB服務(wù)器表明自己使用了什么壓縮方法(gzip,deflate)壓縮響應(yīng)中的對象。例如:Content-Encoding:gzip

            32、Content-Language

            WEB 服務(wù)器告訴瀏覽器理解主體時最適宜使用的自然語言。

            33、Content-Length

            WEB服務(wù)器告訴瀏覽器自己響應(yīng)的對象的長度或尺寸,例如:Content-Length: 26012

            34、Content-Location

            資源實際所處的位置。

            35、Content-MD5

            主體的MD5校驗和。

            36、Content-Range

            實體頭用于指定整個實體中的一部分的插入位置,他也指示了整個實體的長度。在服務(wù)器向客戶返回一個部分響應(yīng),它必須描述響應(yīng)覆蓋的范圍和整個實體長度。一般格式: Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth。例如,傳送頭500個字節(jié)次字段的形式:Content-Range:bytes0- 499/1234如果一個http消息包含此節(jié)(例如,對范圍請求的響應(yīng)或?qū)σ幌盗蟹秶闹丿B請求),Content-Range表示傳送的范圍,Content-Length表示實際傳送的字節(jié)數(shù)。

            37、Content-Type

            WEB 服務(wù)器告訴瀏覽器自己響應(yīng)的對象的類型。例如:Content-Type:application/xml

            38、Etag

            就是一個對象(比如URL)的標志值,就一個對象而言,比如一個html文件,如果被修改了,其Etag也會別修改,所以,ETag的作用跟Last-Modified的作用差不多,主要供WEB服務(wù)器判斷一個對象是否改變了。比如前一次請求某個html文件時,獲得了其 ETag,當這次又請求這個文件時,瀏覽器就會把先前獲得ETag值發(fā)送給WEB服務(wù)器,然后WEB服務(wù)器會把這個ETag跟該文件的當前ETag進行對比,然后就知道這個文件有沒有改變了。

            39、Expires

            WEB服務(wù)器表明該實體將在什么時候過期,對于過期了的對象,只有在跟WEB服務(wù)器驗證了其有效性后,才能用來響應(yīng)客戶請求。是 HTTP/1.0 的頭部。例如:Expires:Sat, 23 May 2009 10:02:12 GMT

            40、Last-Modified

            WEB服務(wù)器認為對象的最后修改時間,比如文件的最后修改時間,動態(tài)頁面的最后產(chǎn)生時間等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT

          二、HTTP Request的Header信息

          1、HTTP請求方式

          說明:主要使用到“GET”和“POST”。

            實例: POST /test/tupian/cm HTTP/1.1

            分成三部分:

            (1)POST:HTTP請求方式

            (2)/test/tupian/cm:請求Web服務(wù)器的目錄地址(或者指令)

            (3)HTTP/1.1: URI(Uniform Resource Identifier,統(tǒng)一資源標識符)及其版本

            備注:在Ajax中,對應(yīng)method屬性設(shè)置。

          2、Host

            說明:請求的web服務(wù)器域名地址

          3、User-Agent

            說明:HTTP客戶端運行的瀏覽器類型的詳細信息。通過該頭部信息,web服務(wù)器可以判斷到當前HTTP請求的客戶端瀏覽器類別。

            實例:User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11

          4、Accept

            說明:指定客戶端能夠接收的內(nèi)容類型,內(nèi)容類型中的先后次序表示客戶端接收的先后次序。

            實例:Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

            備注:在Prototyp(1.5)的Ajax代碼封裝中,將Accept默認設(shè)置為“text/javascript, text/html, application/xml, text/xml, */*”。這是因為Ajax默認獲取服務(wù)器返回的Json數(shù)據(jù)模式。在Ajax代碼中,可以使用XMLHttpRequest 對象中setRequestHeader函數(shù)方法來動態(tài)設(shè)置這些Header信息。

          5、Accept-Language

            說明:指定HTTP客戶端瀏覽器用來展示返回信息所優(yōu)先選擇的語言。

            實例:Accept-Language: zh-cn,zh;q=0.5 這里默認為中文。

          6、Accept-Encoding

            說明:指定客戶端瀏覽器可以支持的web服務(wù)器返回內(nèi)容壓縮編碼類型。表示允許服務(wù)器在將輸出內(nèi)容發(fā)送到客戶端以前進行壓縮,以節(jié)約帶寬。而這里設(shè)置的就是客戶端瀏覽器所能夠支持的返回壓縮格式。

            實例:Accept-Encoding: gzip,deflate

            備注:其實在百度很多產(chǎn)品線中,apache在給客戶端返回頁面數(shù)據(jù)之前,將數(shù)據(jù)以gzip格式進行壓縮。

          7、Accept-Charset

            說明:瀏覽器可以接受的字符編碼集。

            實例:Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7

          8、Content-Type

            說明:顯示此HTTP請求提交的內(nèi)容類型。一般只有post提交時才需要設(shè)置該屬性。

            實例:Content-type: application/x-www-form-urlencoded;charset:UTF-8

            備注:有關(guān)Content-Type屬性值可以如下兩種編碼類型:

            (1)“application/x-www-form-urlencoded”: 表單數(shù)據(jù)向服務(wù)器提交時所采用的編碼類型,默認的缺省值就是“application/x-www-form-urlencoded”。 然而,在向服務(wù)器發(fā)送大量的文本、包含非ASCII字符的文本或二進制數(shù)據(jù)時這種編碼方式效率很低。

            (2)“multipart/form-data”: 在文件上載時,所使用的編碼類型應(yīng)當是“multipart/form-data”,它既可以發(fā)送文本數(shù)據(jù),也支持二進制數(shù)據(jù)上載。

            當提交為單單數(shù)據(jù)時,可以使用“application/x-www-form-urlencoded”;當提交的是文件時,就需要使用“multipart/form-data”編碼類型。

            在Content-Type屬性當中還是指定提交內(nèi)容的charset字符編碼。一般不進行設(shè)置,它只是告訴web服務(wù)器post提交的數(shù)據(jù)采用的何種字符編碼。

            一般在開發(fā)過程,是由前端工程與后端UI工程師商量好使用什么字符編碼格式來post提交的,然后后端ui工程師按照固定的字符編碼來解析提交的數(shù)據(jù)。所以這里設(shè)置的charset沒有多大作用。

          9、Connection

            說明:表示是否需要持久連接。如果web服務(wù)器端看到這里的值為“Keep-Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久連接),它就可以利用持久連接的優(yōu)點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現(xiàn)這一點, web服務(wù)器需要在返回給客戶端HTTP頭信息中發(fā)送一個Content-Length(返回信息正文的長度)頭,最簡單的實現(xiàn)方法是:先把內(nèi)容寫入ByteArrayOutputStream,然 后在正式寫出內(nèi)容之前計算它的大小。

            實例:Connection: keep-alive

          10、Keep-Alive

            說明:顯示此HTTP連接的Keep-Alive時間。使客戶端到服務(wù)器端的連接持續(xù)有效,當出現(xiàn)對服務(wù)器的后繼請求時,Keep-Alive功能避免了建立或者重新建立連接。以前HTTP請求是一站式連接,從HTTP/1.1協(xié)議之后,就有了長連接,即在規(guī)定的Keep-Alive時間內(nèi),連接是不會斷開的。

            實例:Keep-Alive: 300

          11、cookie

            說明:HTTP請求發(fā)送時,會把保存在該請求域名下的所有cookie值一起發(fā)送給web服務(wù)器。

          12、Referer

            說明:包含一個URL,用戶從該URL代表的頁面出發(fā)訪問當前請求的頁面

          三、HTTP Response的Header信息

          四、http返回錯誤碼

            HTTP響應(yīng)碼響應(yīng)碼由三位十進制數(shù)字組成,它們出現(xiàn)在由HTTP服務(wù)器發(fā)送的響應(yīng)的第一行。響應(yīng)碼分五種類型,由它們的第一位數(shù)字表示:

            1xx:信息,請求收到,繼續(xù)處理

            2xx:成功,行為被成功地接受、理解和采納

            3xx:重定向,為了完成請求,必須進一步執(zhí)行的動作

            4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實現(xiàn)

            5xx:服務(wù)器錯誤,服務(wù)器不能實現(xiàn)一種明顯無效的請求

            下表顯示每個響應(yīng)碼及其含義:

          容簡介

          使用scrapy寫爬蟲的時候,會莫名其妙的被目標網(wǎng)站拒絕,很大部分是瀏覽器請求頭的原因。

          現(xiàn)在一起來看看scrapy的請求頭,并探究設(shè)置方式

          工具準備

          • 開發(fā)環(huán)境python2.7 + scrapy 1.1.2
          • 測試請求頭網(wǎng)站:
          • https://httpbin.org/get?show_env=1
          • json在線解析:
          • https://www.json.cn/
          • 瀏覽器請求頭大全:
          • http://www.useragentstring.com/

          默認請求頭

          命令行執(zhí)行,新建爬蟲

          scrapy startproject myspider
          cd myspider 
          scrapy genspider scrapy_spider httpbin.org
          

          我們通過對 https://httpbin.org/get?show_env=1 的請求,查看本次請求的瀏覽器信息,可以打開看一看是否是自己的瀏覽器信息

          改寫生成的scrapy_spider.py文件

          import scrapy
          class ScrapySpider(scrapy.Spider):
           name = "scrapy_spider"
           allowed_domains = ["httpbin.org"]
           start_urls = (
           # 請求的鏈接
           "https://httpbin.org/get?show_env=1",
           )
           def parse(self, response):
           # 打印出相應(yīng)結(jié)果 
           print response.text
          if __name__ == '__main__':
           from scrapy import cmdline
           cmdline.execute("scrapy crawl scrapy_spider".split())
          

          如果是你正好使用mac本,正好使用pycharm可以按快捷鍵啟動爬蟲

          shift + control + r

          當然,如果是windows那就右鍵啟動吧

          將返回的文本復(fù)制到 https://www.json.cn/ 格式化成便于查看的json格式,下面操作亦然,不再贅述。

          {
           "args":{
           "show_env":"1"
           },
           "headers":{
           "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
           "Accept-Encoding":"gzip,deflate",
           "Accept-Language":"en",
           "Connect-Time":"1",
           "Connection":"close",
           "Host":"httpbin.org",
           "Total-Route-Time":"0",
           "User-Agent":"Scrapy/1.1.2 (+http://scrapy.org)",
           "Via":"1.1 vegur",
           "X-Forwarded-For":"39.155.188.22",
           "X-Forwarded-Port":"443",
           "X-Forwarded-Proto":"https",
           "X-Request-Id":"9dcf91a6-0bed-4d9e-b2bd-b7c88b832d81",
           "X-Request-Start":"1529654403617"
           },
           "origin":"39.155.188.22",
           "url":"https://httpbin.org/get?show_env=1"
          }
          

          看到了吧,默認的請求頭是

          "User-Agent":"Scrapy/1.1.2 (+http://scrapy.org)"
          

          修改請求頭

          既然這樣的話,那我們修改下請求頭,達到偽造的效果

          打開下面的鏈接,選一個自己喜歡的請求頭

          http://www.useragentstring.com/pages/useragentstring.php?name=Chrome

          這里使用chrome瀏覽器請求頭

          方式一:全局設(shè)置

          此方式設(shè)置后,覆蓋掉scrapy默認的請求頭,全局生效,即所有爬蟲都可以享受

          settings.py文件中找到如下代碼

          # Crawl responsibly by identifying yourself (and your website) on the user-agent
          # USER_AGENT = 'myspider (+http://www.yourdomain.com)'
          

          解除注釋,修改為自己的請求頭

          # Crawl responsibly by identifying yourself (and your website) on the user-agent
          USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
          

          運行爬蟲,驗證效果

          "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
          

          方式二:爬蟲設(shè)置

          此方式設(shè)置后,單個爬蟲生效,此爬蟲的所有連接都享受

          class ScrapySpider(scrapy.Spider):
           name = "scrapy_spider"
           allowed_domains = ["httpbin.org"]
           # 新添加的代碼
           custom_settings = {
           "USER_AGENT": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
           }
           # -----------
           start_urls = (
           "https://httpbin.org/get?show_env=1",
           )
          

          再次訪問,發(fā)現(xiàn)我們的請求頭已經(jīng)成功更換

          "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
          

          方式三:鏈接設(shè)置

          此方法對單個鏈接生效, 只是此次請求的這個鏈接享受

          在Request方法中設(shè)置headers參數(shù)

          import scrapy
          # 請求頭
          USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
          class ScrapySpider(scrapy.Spider):
           name = "scrapy_spider"
           allowed_domains = ["httpbin.org"]
           start_urls = (
           "https://httpbin.org/get?show_env=1",
           )
           # 新加的代碼
           def start_requests(self):
           for url in self.start_urls:
           yield scrapy.Request(url, headers={"User-Agent": USER_AGENT})
           # ------------
           def parse(self, response):
           print response.text
          

          測試效果

          "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
          

          方法四:中間件設(shè)置

          此方法可以從整個項目中去修改請求頭的設(shè)置規(guī)則,變化多端,不同的寫法,可以配置出不同的設(shè)置方式,下面是一個比較簡單的示例

          私信小編007即可獲取數(shù)十套PDF的獲取方式哦!

          我們參考scrapy默認處理請求頭的中間件

          from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
          

          編寫中間件

          # middlewares.py
          class RandomUserAgentMiddleware(object):
           def process_request(self, request, spider):
           request.headers['User-Agent']= "" # 絕對設(shè)置,其他設(shè)置都不生效
          

          我們可以從下面找到默認設(shè)置

          from scrapy.settings import default_settings
          

          找到項目中對請求頭起作用的中間件

          'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
          

          在settings.py 或者custom_settings替換原有的中間件

          "DOWNLOADER_MIDDLEWARES": {
           'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None,
           "myspider.middlewares.RandomUserAgentMiddleware": 400,
           }
          

          這樣可以從全局,或者局部替換掉請求頭規(guī)則

          作用優(yōu)先級

          如果作如下設(shè)置

          # settings.py
          USER_AGENT = "settings"
          


          # scrapy_spider.py
          custom_settings = {
           "USER_AGENT": "custom_settings",
           }
          headers={"User-Agent": "header"}
          

          運行效果為:

          "User-Agent":"header"
          

          注釋掉headers

          "User-Agent":"custom_settings"
          

          注釋掉custom_settings

          "User-Agent":"custom_settings"
          

          注釋掉settings

          "User-Agent":"Scrapy/1.1.2 (+http://scrapy.org)"
          

          可見優(yōu)先級為:

          headers > custom_settings > settings.py > Scrapy默認

          注意

          注意User-Agent參數(shù)的寫法

          headers={"User-Agent": USER_AGENT})
          

          如果寫錯了,很可能發(fā)生奇怪的事情

          headers={"User_Agent": USER_AGENT}
          

          請求頭中多了Scrapy…

          "User-Agent":"Scrapy/1.1.2 (+http://scrapy.org),Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
          

          其實,很好區(qū)分:

          User-Agent: 瀏覽器請求頭參數(shù),html代碼中經(jīng)常用-

          USER_AGENT: python變量

          建議:

          每次寫瀏覽器參數(shù),如果怕寫錯就打開自己的瀏覽器,隨便測試一個頁面,從里邊復(fù)制

          總結(jié)

          設(shè)置方式作用效果Scrapy默認所用爬蟲所有請求settings.py / USER_AGENT=""所用爬蟲所有請求custom_settings = {"USER_AGENT": "",}單個爬蟲所有請求headers={"User-Agent": ""}單個請求中間件方式downloadermiddleware視編寫規(guī)則而定

          表格從上至下,優(yōu)先級逐漸增加,中間件除外,一般掌握三種方式就夠用了:

          • settings.py
          • custom_settings
          • headers

          作為從入門到實戰(zhàn)的我,踩過不少坑,此文做了簡單的總結(jié),也分享了幾個比較實用的網(wǎng)站。希望此文的分享能給大家提供一個少走彎路的捷徑,那么此文的價值也就體現(xiàn)了。

          順便打個廣告

          最近想寫一個開源庫,chinesename中文取名,已經(jīng)實現(xiàn)基本的取名,不過名字需要優(yōu)化,如果有想一起搞事情的同學(xué),可以一起

          github地址:https://github.com/mouday/chinesename


          主站蜘蛛池模板: 久久无码一区二区三区少妇| 精品欧洲AV无码一区二区男男| 99精品国产高清一区二区三区| 国产激情з∠视频一区二区| 亚洲AV无码一区二区三区性色| 成人无号精品一区二区三区| 国产成人久久精品区一区二区| 一区二区乱子伦在线播放| 国产一区二区在线|播放| 国产精品日韩欧美一区二区三区| 久草新视频一区二区三区| 色一情一乱一伦一区二区三区| 在线视频一区二区| 精品乱人伦一区二区三区| 蜜桃视频一区二区| 亚洲国产成人精品久久久国产成人一区二区三区综 | 海角国精产品一区一区三区糖心 | 国产激情无码一区二区| 亚洲AV无码一区二区三区久久精品 | 精品国产一区二区22 | 国模精品视频一区二区三区| 亚洲一区无码精品色| 91精品一区二区| 日本一区二区三区日本免费| 亚洲色大成网站www永久一区| 欧美av色香蕉一区二区蜜桃小说 | 在线日韩麻豆一区| 制服丝袜一区二区三区| 亚洲日韩激情无码一区| 国产乱码精品一区二区三区中| 久久久精品人妻一区二区三区蜜桃 | 国产一区三区二区中文在线| 国内精品无码一区二区三区| 国模私拍福利一区二区| 亚洲一区二区精品视频| 国产福利91精品一区二区三区| 91一区二区三区| 精品一区二区三区无码视频| 男人的天堂亚洲一区二区三区| 在线观看国产一区| 一本一道波多野结衣AV一区|