先扒一扒HTTP協議背景?
-
HTTP(HyperText Transfer Protocol) 即超文本傳輸協議,現在基本上所有web專案都遵從HTTP協議(協議就是一種人為的規范),
-
目前絕大部分使用的都是HTTP/1.1版本(1.0太老,2.0仍在制訂中,,,),
因為HTTP協議是屬于TCP/IP協議簇的,所以先簡單介紹下與HTTP相關的TCP/IP知識,
TCP/IP簡介,
-
TCP/IP是一個協議簇,是由許多協議組成的,
TCP/IP四層模型,
-
TCP/IP按照層次從上至下分為四層:應用層,傳輸層,網路層,資料鏈路層,(實際上最初理論上OSI模型是分的七層,我們程式猿的話通常只用分四層就行了,)
-
應用層 :
-
應用層決定了向用戶提供應用服務時通信的活動,TCP/IP協議族內預存了各類通用的應用服務,比如,FTP(File Transfer Protocol,檔案傳輸協議)和DNS(Domain Name System,域名系統)服務就是其中兩類,HTTP協議也處于該層,
-
傳輸層 :
-
傳輸層對上層應用層,提供處于網路連接中的兩臺計算機之間的資料傳輸,在傳輸層有兩個性質不同的協議:TCP(Transmission ControlProtocol,傳輸控制協議)和UDP(User Data Protocol,用戶資料報協議),
-
網路層 :
-
網路層用來處理在網路上流動的資料包,資料包是網路傳輸的最小資料單位,該層規定了通過怎樣的路徑(所謂的傳輸路線)到達對方計算機,并把資料包傳送給對方,與對方計算機之間通過多臺計算機或網路設備進行傳輸時,網路層所起的作用就是在眾多的選項內選擇一條傳輸路線,
-
鏈路層(又名資料鏈路層,網路介面層) :
-
用來處理連接網路的硬體部分,包括控制作業系統、硬體的設備驅動、NIC(Network Interface Card,網路配接器,即網卡),及光纖等物理可見部分(還包括連接器等一切傳輸媒介),硬體上的范疇均在鏈路層的作用范圍之內,
TCP/IP具體是怎么通信的呢?
-
利用TCP/IP協議族進行網路通信時,會通過分層順序與對方進行通信,發送端從應用層往下走,接收端則往應用層往上走,我們用HTTP舉例來說明,首先作為發送端的客戶端在應用層(HTTP協議)發出一個想看某個Web頁面的HTTP請求,接著,為了傳輸方便,在傳輸層(TCP協議)把從應用層處收到的資料(HTTP請求報文)進行分割,并在各個報文上打上標記序號及埠號后轉發給網路層,在網路層(IP協議),增加作為通信目的地的MAC地址后轉發給鏈路層,這樣一來,發往網路的通信請求就準備齊全了,接收端的服務器在鏈路層接收到資料,按序往上層發送,一直到應用層,當傳輸到應用層,才能算真正接收到由客戶端發送過來的HTTP請求,
-
發送端在層與層之間傳輸資料時,每經過一層時必定會被打上一個該層所屬的首部資訊,反之,接收端在層與層傳輸資料時,每經過一層時會把對應的首部消去,這種把資料資訊包裝起來的做法稱為封裝(encapsulate),
負責傳輸的IP協議,
-
按層次分,IP(Internet Protocol)網際協議位于網路層,Internet Protocol這個名稱可能聽起來有點夸張,但事實正是如此,因為幾乎所有使用網路的系統都會用到IP協議,TCP/IP協議族中的IP指的就是網際協議,協議名稱中占據了一半位置,其重要性可見一斑,可能有人會把IP和IP 地址搞混,IP其實是一種協議的名稱,
-
IP協議的作用是把各種資料包傳送給對方,而要保證確實傳送到對方那里,則需要滿足各類條件,其中兩個重要的條件是IP地址和MAC地址(Media Access Control Address),IP地址指明了節點被分配到的地址,MAC地址是指網卡所屬的固定地址,IP地址可以和MAC地址進行配對,IP地址可變換,但MAC地址基本上不會更改,
-
使用ARP協議憑借MAC地址進行通信,IP間的通信依賴MAC地址,在網路上,通信的雙方在同一局域網(LAN)內的情況是很少的,通常是經過多臺計算機和網路設備中轉才能連接到對方,而在進行中轉時,會利用下一站中轉設備的MAC地址來搜索下一個中轉目標,這時,會采用ARP協議(Address Resolution Protocol),ARP 是一種用以決議地址的協議,根據通信方的IP地址就可以反查出對應的MAC地址,
-
沒有人能夠全面掌味訓聯網中的傳輸狀況,即在傳輸程序中每一個節點只需要了解下一個節點的資訊,再往下的資訊就交給下個節點去處理就行了,在到達通信目標前的中轉程序中,那些計算機和路由器等網路設備只能獲悉很粗略的傳輸路線, 這種機制稱為路由選擇(routing),有點像快遞公司的送貨程序,想要寄快遞的人,只要將自己的貨物送到集散中心,就可以知道快遞公司是否肯收件發貨,該快遞公司的集散中心檢查貨物的送達地址,明確下站該送往哪個區域的集散中心,接著,那個區域的集散中心自會判斷是否能送到對方的家中,我們是想通過這個比喻說明,無論哪臺計算機、哪臺網路設備,它們都無法全面掌味訓聯網中的細節,
確保可靠性的TCP協議,
-
按層次分,TCP位于傳輸層,提供可靠的位元組流服務,所謂的位元組流服務(Byte Stream Service)是指,為了方便傳輸,將大塊資料分割成以報文段(segment)為單位的資料包進行管理,而可靠的傳輸服務是指,能夠把資料準確可靠地傳給對方,一言以蔽之,TCP協議為了更容易傳送大資料才把資料分割,而且TCP協議能夠確認資料最終是否送達到對方,
-
確保資料能到達目標,為了準確無誤地將資料送達目標處,TCP協議采用了三次握手(three-way handshaking)策略,用TCP協議把資料包送出去后,TCP不會對傳送后的情況置之不理,它一定會向對方確認是否成功送達,握手程序中使用了TCP的標志(flag) ——SYN(synchronize) 和ACK(acknowledgement),發送端首先發送一個帶SYN標志的資料包給對方,接收端收到后,回傳一個帶有SYN/ACK標志的資料包以示傳達確認資訊,最后,發送端再回傳一個帶ACK標志的資料包,代表握手結束,若在握手程序中某個階段莫名中斷,TCP協議會再次以相同的順序發送相同的資料包,除了上述三次握手,TCP協議還有其他各種手段來保證通信的可靠性,
負責域名決議的DNS服務,
-
DNS(Domain Name System)服務是和HTTP協議一樣位于應用層的協議,它提供域名到IP地址之間的決議服務,計算機既可以被賦予IP地址,也可以被賦予主機名和域名,比如www.baidu.com,因為域名更加直觀,所以用戶通常使用主機名或域名來訪問對方的計算機,而不是直接通過IP地址訪問,但要讓計算機去理解名稱,相對而言就變得困難了,因為計算機更擅長處理一長串數字,為了解決上述的問題,DNS服務應運而生,DNS協議提供通過域名查找IP地址,或逆向從IP地址反查域名的服務,
HTTP協議與其他TCP/IP協議是如何協作的?
URI和URL,
URI是Uniform Resource Identifier的縮寫,即統一資源識別符號,
-
RFC2396分別對這 3 個單詞進行了如下定義:
-
Uniform :規定統一的格式可方便處理多種不同型別的資源, 而不用根據背景關系環境來識別資源指定的訪問方式,另外, 加入新增的協議方案(如http:或ftp:) 也更容易,
-
Resource :資源的定義是可標識的任何東西, 除了檔案檔案、 影像或服務(例如當天的天氣預報) 等能夠區別于其他型別的, 全都可作為資源, 另外, 資源不僅可以是單一的, 也可以是多數的集合體,
-
Identifier :表示可標識的物件, 也稱為識別符號,
-
綜上所述,URI就是由某個協議方案表示的資源的定位識別符號, 協議方案是指訪問資源所使用的協議型別名稱, 采用HTTP協議時, 協議方案就是http, 除此之外, 還有ftp、mailto、telnet、file等, 標準的URI協議方案有 30 種左右, 由隸屬于國際互聯網資源管理的非營利社團ICANN(Internet Corporation for Assigned Names and Numbers, 互聯網名稱與數字地址分配機構) 的IANA(Internet Assigned Numbers Authority, 互聯網號碼分配局) 管理頒布,
-
URI用字串標識某一互聯網資源, 而URL表示資源的地點(互聯網上所處的位置) , 可見URL是URI的子集,(當然通常可以大致把URL理解成URI)
URI的格式,
-
要想表示指定的資源, 就得使用涵蓋全部必要資訊的絕對URI,同樣的也會有相對URI,這里以相對URL為例,就是指從瀏覽器中基本URL處指定的URL,形如/image/logo.gif這種形式,
接下來結合下面這個例子著重介紹一下絕對URI:
-
協議方案名:使用http:或https:等協議方案名獲取訪問資源時要指定協議型別, 不區分字母大小寫, 最后附一個冒號(:),也可使用data:或javascript:這類指定資料或腳本程式的方案名,
-
登錄資訊(認證) :指定用戶名和密碼作為從服務器端獲取資源時必要的登錄資訊(身份認證) , 此項是可選項,
-
服務器地址 :使用絕對URI必須指定待訪問的服務器地址, 地址可以是類似baidu.com這種DNS可決議的域名, 或是192.168.1.1這類IPv4地址, 還可以是[0:0:0:0:0:0:0:1]這樣用方括號括起來的IPv6地址,
-
服務器埠號 :指定服務器連接的網路埠號, 此項也是可選項, 若用戶省略則自動使用默認埠號,
-
帶層次的檔案路徑 :指定服務器上的檔案路徑來定位特指的資源, 這與UNIX系統的檔案目錄結構相似,
-
查詢字串 :針對已指定的檔案路徑內的資源, 可以使用查詢字串傳入任意引數, 此項可選,
-
片段識別符號 :使用片段識別符號通常可標記出已獲取資源中的子資源(檔案內的某個位置) , 但在RFC中并沒有明確規定其使用方法, 該項也為可選項,
RFC : Request for Comments, 征求修正意見書,一些用來制定HTTP協議技術標準的檔案,當然并不是強制性的,所以還是有一小部分應用程式并沒有遵從RFC標準,這也就導致了其他應用不同標準的互聯網資源可能就無法與該應用程式進行通訊了,
-
RFC3986列舉了幾種URI的常用語法格式:
-
tp://ftp.is.co.za/rfc/rfc1808.txt
-
http://www.ietf.org/rfc/rfc2396.txt
-
ldap://[2001:db8::7]/c=GB?objectClass?one
-
mailto:[email protected]
-
news:comp.infosystems.www.servers.unix
-
tel:+1-816-555-1212
-
telnet://192.0.2.16:80/
-
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
HTTP協議用于客戶端和服務器端之間的通信,
-
HTTP協議和TCP/IP協議族內的其他眾多的協議相同, 用于客戶端和服務器之間的通信,請求訪問文本或影像等資源的一端稱為客戶端, 而提供資源回應的一端稱為服務器端,在兩臺計算機之間使用HTTP協議通信時, 在一條通信線路上必定有一端是客戶端, 另一端則是服務器端,有時候, 按實際情況, 兩臺計算機作為客戶端和服務器端的角色有可能會互換, 但就僅從一條通信路線來說, 服務器端和客戶端的角色是確定的, 而用HTTP協議能夠明確區分哪端是客戶端, 哪端是服務器端,
通過請求和回應的交換達成通信,
-
HTTP協議規定, 請求從客戶端發出, 最后服務器端回應該請求并回傳, 換句話說, 肯定是先從客戶端開始建立通信的, 服務器端在沒有接收到請求之前不會發送回應,
-
起始行開頭的GET表示請求訪問服務器的型別, 稱為方法(method) , 隨后的字串/index.htm指明了請求訪問的資源物件,也叫做請求URI(request-URI) , 最后的HTTP/1.1, 即HTTP的版本號, 用來提示客戶端使用的HTTP協議功能,綜合來看, 這段請求內容的意思是: 請求訪問某臺HTTP服務器上的/index.htm頁面資源,
-
請求報文是由請求方法、 請求URI、 協議版本、 可選的請求首部欄位和內容物體構成的,
-
緊挨著的200 OK表示請求的處理結果的狀態碼(status code) 和原因短語(reason-phrase) , 下一行顯示了創建回應的日期時間, 是首部欄位(header field) 內的一個屬性,接著以一空行分隔, 之后的內容稱為資源物體的主體(entity body),回應報文基本上由協議版本、 狀態碼(表示請求成功或失敗的數字代 碼) 、 用以解釋狀態碼的原因短語、 可選的回應首部欄位以及物體主體構成, 稍后我們會對這些內容進行詳細說明,
HTTP是不保存狀態的協議,
-
HTTP是一種不保存狀態, 即無狀態(stateless) 協議,HTTP協議自身不對請求和回應之間的通信狀態進行保存, 也就是說在HTTP這個級別, 協議對于發送過的請求或回應都不做持久化處理,
-
使用HTTP協議, 每當有新的請求發送時, 就會有對應的新回應產生, 協議本身并不保留之前一切的請求或回應報文的資訊, 這是為了更快地處理大量事務, 確保協議的可伸縮性, 而特意把HTTP協議設計成如此簡單的,可是, 隨著Web的不斷發展, 因無狀態而導致業務處理變得棘手的情況增多了, 比如, 用戶登錄到一家購物網站, 即使他跳轉到該站的其他頁面后, 也需要能繼續保持登錄狀態, 針對這個實體, 網站為了能夠掌握是誰送出的請求, 需要保存用戶的狀態,HTTP/1.1雖然是無狀態協議, 但為了實作期望的保持狀態功能, 于是引入了Cookie技術, 有了Cookie再用HTTP協議通信, 就可以管理狀態了, 有關Cookie的詳細內容稍后講解,
請求URI定位資源
-
HTTP協議使用URI定位互聯網上的資源, 正是因為URI的特定功能, 在互聯網上任意位置的資源都能訪問到,
-
當客戶端請求訪問資源而發送請求時,URI需要將作為請求報文中的請求URI包含在內, 指定請求URI的方式有很多,
-
除此之外, 如果不是訪問特定資源而是對服務器本身發起請求, 可以用一個*來代替請求URI, 下面這個例子是查詢HTTP服務器端支持的HTTP方法種類,
告知服務器意圖的HTTP方法,
-
向請求URI指定的資源發送請求報文時, 采用稱為方法的命令,方法的作用在于, 可以指定請求的資源按期望產生某種行為, 方法中有GET、POST和HEAD等,
-
下表列出了HTTP/1.0和HTTP/1.1支持的方法, 另外, 方法名區分大小寫, 注意要用大寫字母,
在這里列舉的眾多方法中,LINK和UNLINK已被HTTP/1.1廢棄, 不再支持,
GET: 獲取資源,
-
GET方法用來請求訪問已被URI識別的資源, 指定的資源經服務器端決議后回傳回應內容, 也就是說, 如果請求的資源是文本, 那就保持原樣回傳; 如果是像CGI(Common Gateway Interface, 通用網關介面)那樣的程式, 則回傳經過執行后的輸出結果,
POST: 傳輸物體主體,
-
雖然用GET方法也可以傳輸物體的主體, 但一般不用GET方法進行傳輸, 而是用POST方法, 雖說POST的功能與GET很相似, 但POST的主要目的并不是獲取回應的主體內容,
PUT: 傳輸檔案,
-
PUT方法用來傳輸檔案, 就像FTP協議的檔案上傳一樣, 要求在請求報文的主體中包含檔案內容, 然后保存到請求URI指定的位置,但是, 鑒于HTTP/1.1的PUT方法自身不帶驗證機制, 任何人都可以 上傳檔案 , 存在安全性問題, 因此一般的Web網站不使用該方法, 若配合Web應用程式的驗證機制, 或架構設計采用REST(REpresentational State Transfer, 表征狀態轉移) 標準的同類Web網站, 就可能會開放使用PUT方法,
HEAD: 獲得報文首部,
-
HEAD方法和GET方法一樣, 只是不回傳報文主體部分, 用于確認URI的有效性及資源更新的日期時間等,
DELETE: 洗掉檔案,
-
DELETE方法用來洗掉檔案, 是與PUT相反的方法,DELETE方法按請求URI洗掉指定的資源, 但是,HTTP/1.1的DELETE方法本身和PUT方法一樣不帶驗證機制, 所以一般的Web網站也不使用DELETE方法, 當配合Web應用程式的驗證機制, 或遵守REST標準時還是有可能會開放使用的,
OPTIONS: 詢問支持的方法,
-
OPTIONS方法用來查詢針對請求URI指定的資源支持的方法,
TRACE: 追蹤路徑,
-
TRACE方法是讓Web服務器端將之前的請求通信環回給客戶端的方法,發送請求時, 在Max-Forwards首部欄位中填入數值, 每經過一個服務器端就將該數字減1, 當數值剛好減到0時, 就停止繼續傳輸, 最后接收到請求的服務器端則回傳狀態碼200 OK的回應,客戶端通過TRACE方法可以查詢發送出去的請求是怎樣被加工修改的, 這是因為, 請求想要連接到源目標服務器可能會通過代理中轉,TRACE方法就是用來確認連接程序中發生的一系列操作,但是,TRACE方法本來就不怎么常用, 再加上它容易引發XST(Cross-Site Tracing, 跨站追蹤) 攻擊, 通常就更不會用到了,
CONNECT: 要求用隧道協議連接代理,
-
CONNECT方法要求在與代理服務器通信時建立隧道, 實作用隧道協議進行TCP通信, 主要使用SSL(Secure Sockets Layer, 安全套接層) 和TLS(Transport Layer Security, 傳輸層安全) 協議把通信內容加密后經網路隧道傳輸,
持久連接節省通信量,
-
HTTP 協議的初始版本中, 每進行一次 HTTP 通信就要斷開一次 TCP 連接,以當年的通信情況來說,因為都是些容量很小的文本傳輸, 所以即使這樣也沒有多大問題, 可隨著 HTTP 的普及, 檔案中包含大量圖片的情況多了起來,比如, 使用瀏覽器瀏覽一個包含多張圖片的 HTML 頁面時, 在發送請求訪問 HTML 頁面資源的同時, 也會請求該 HTML 頁面里包含的其他資源, 因此, 每次的請求都會造成無謂的 TCP 連接建立和斷開, 增加通信量的開銷,
持久連接,
-
為解決上述 TCP 連接的問題, HTTP/1.1 和一部分的 HTTP/1.0 想出了持久連接(HTTP Persistent onnections, 也稱為 HTTP keep-alive 或 HTTP connection reuse) 的方法, 持久連接的特點是, 只要任意一端沒有明確提出斷開連接, 則保持 TCP 連接狀態,
-
持久連接的好處在于減少了 TCP 連接的重復建立和斷開所造成的額外開銷, 減輕了服務器端的負載, 另外, 減少開銷的那部分時間, 使 HTTP 請求和回應能夠更早地結束, 這樣 Web 頁面的顯示速度也就相應提高了,在 HTTP/1.1 中, 所有的連接默認都是持久連接, 但在 HTTP/1.0 內并未標準化, 雖然有一部分服務器通過非標準的手段實作了持久連接,但服務器端不一定能夠支持持久連接, 毫無疑問, 除了服務器端, 客戶端也需要支持持久連接,
管線化,
-
持久連接使得多數請求以管線化(pipelining) 方式發送成為可能, 從前發送請求后需等待并收到回應, 才能發送下一個請求, 管線化技術出現后, 不用等待回應亦可直接發送下一個請求,這樣就能夠做到同時并行發送多個請求, 而不需要一個接一個地等待回應了,
-
比如, 當請求一個包含 10 張圖片的 HTML Web 頁面, 與挨個連接相比, 用持久連接可以讓請求更快結束, 而管線化技術則比持久連接還要快, 請求數越多, 時間差就越明顯,
使用 Cookie 的狀態管理,
-
HTTP 是無狀態協議, 它不對之前發生過的請求和回應的狀態進行管理, 也就是說, 無法根據之前的狀態進行本次的請求處理,假設要求登錄認證的 Web 頁面本身無法進行狀態的管理(不記錄已登錄的狀態) , 那么每次跳轉新頁面不是要再次登錄, 就是要在每次請求報文中附加引數來管理登錄狀態,不可否認, 無狀態協議當然也有它的優點, 由于不必保存狀態, 自然可減少服務器的 CPU 及記憶體資源的消耗, 從另一側面來說, 也正是因為 HTTP 協議本身是非常簡單, 所以才會被應用在各種場景里,
-
保留無狀態協議這個特征的同時又要解決類似的矛盾問題, 于是引入了 Cookie 技術, Cookie 技術通過在請求和回應報文中寫入 Cookie 資訊來控制客戶端的狀態,Cookie 會根據從服務器端發送的回應報文內的一個叫做 Set-Cookie 的首部欄位資訊, 通知客戶端保存 Cookie,當下次客戶端再往該服務器發送請求時, 客戶端會自動在請求報文中加入 Cookie 值后發送出去,服務器端發現客戶端發送過來的 Cookie 后, 會去檢查究竟是從哪一個客戶端發來的連接請求, 然后對比服務器上的記錄, 最后得到之前的狀態資訊,
上圖展示了發生 Cookie 互動的情景, HTTP 請求報文和回應報文的內容如下,上圖展示了發生 Cookie 互動的情景, HTTP 請求報文和回應報文的內容如下,
有關請求報文和回應報文內 Cookie 對應的首部欄位, 請參考之后的章節,
HTTP 報文內的 HTTP 資訊,
-
HTTP 通信程序包括從客戶端發往服務器端的請求及從服務器端回傳客戶端的回應, 本章就讓我們來了解一下請求和回應是怎樣運作的,
HTTP 報文,
-
用于 HTTP 協議互動的資訊被稱為 HTTP 報文, 請求端(客戶端) 的 HTTP 報文叫做請求報文, 回應端(服務器端) 的叫做回應報文,HTTP報文本身是由多行(用 CR+LF 作換行符) 資料構成的字串文本,HTTP 報文大致可分為報文首部和報文主體兩塊, 兩者由最初出現的空行(CR+LF) 來劃分, 通常, 并不一定要有報文主體,
請求報文及回應報文的結構,
-
請求行 : 包含用于請求的方法, 請求 URI 和 HTTP 版本,
-
狀態行 : 包含表明回應結果的狀態碼, 原因短語和 HTTP 版本,
-
首部欄位 : 包含表示請求和回應的各種條件和屬性的各類首部,一般有 4 種首部, 分別是: 通用首部、 請求首部、 回應首部和物體首部,
-
其他 : 可能包含 HTTP 的 RFC 里未定義的首部(Cookie 等),
編碼提升傳輸速率,
-
HTTP 在傳輸資料時可以按照資料原貌直接傳輸, 但也可以在傳輸程序中通過編碼提升傳輸速率, 通過在傳輸時編碼, 能有效地處理大量的訪問請求, 但是, 編碼的操作需要計算機來完成, 因此會消耗更多的 CPU 等資源,
-
報文主體和物體主體的差異,
-
報文(message) : 是 HTTP 通信中的基本單位, 由 8 位組位元組流(octet sequence,其中 octet 為 8 個位元) 組成, 通過 HTTP 通信傳輸,
-
物體(entity) : 作為請求或回應的有效載荷資料(補充項) 被傳輸, 其內容由物體首部和物體主體組成,
-
HTTP 報文的主體用于傳輸請求或回應的物體主體,通常, 報文主體等于物體主體, 只有當傳輸中進行編碼操作時, 物體主體的內容發生變化, 才導致它和報文主體產生差異,
-
向待發送郵件內增加附件時, 為了使郵件容量變小, 我們會先用 ZIP 壓縮檔案之后再添加附件發送, HTTP 協議中有一種被稱為內容編碼的功能也能進行類似的操作,內容編碼指明應用在物體內容上的編碼格式, 并保持物體資訊原樣壓縮, 內容編碼后的物體由客戶端接收并負責解碼,
-
常用的內容編碼有以下幾種:
-
gzip(GNU zip)
-
compress(UNIX 系統的標準壓縮)
-
deflate(zlib)
-
identity(不進行編碼)
-
在 HTTP 通信程序中, 請求的編碼物體資源尚未全部傳輸完成之前,瀏覽器無法顯示請求頁面, 在傳輸大容量資料時, 通過把資料分割成多塊, 能夠讓瀏覽器逐步顯示頁面,這種把物體主體分塊的功能稱為分塊傳輸編碼(Chunked Transfer Coding),
-
分塊傳輸編碼會將物體主體分成多個部分(塊) , 每一塊都會用十六進制來標記塊的大小, 而物體主體的最后一塊會使用 “0(CR+LF)” 來標記,使用分塊傳輸編碼的物體主體會由接收的客戶端負責解碼, 恢復到編碼前的物體主體,HTTP/1.1 中存在一種稱為傳輸編碼(Transfer Coding) 的機制, 它可以在通信時按某種編碼方式傳輸, 但只定義作用于分塊傳輸編碼中,
發送多種資料的多部分物件集合,
-
發送郵件時, 我們可以在郵件里寫入文字并添加多份附件, 這是因為采用了 MIME(Multipurpose Internet Mail Extensions, 多用途因特網郵件擴展) 機制, 它允許郵件處理文本、 圖片、 視頻等多個不同型別的53資料, 例如, 圖片等二進制資料以 ASCII 碼字串編碼的方式指明,就是利用 MIME 來描述標記資料型別, 而在 MIME 擴展中會使用一種稱為多部分物件集合(Multipart) 的方法, 來容納多份不同型別的資料,相應地, HTTP 協議中也采納了多部分物件集合, 發送的一份報文主體內可含有多型別物體, 通常是在圖片或文本檔案等上傳時使用,
-
多部分物件集合包含的物件如下:
-
multipart/byteranges :
-
multipart/form-data : 在 Web 表單檔案上傳時使用,
-
multipart/byteranges : 狀態碼 206(Partial Content, 部分內容) 回應報文包含了多個范圍的內容時使用,
-
multipart/form-data :
-
在 HTTP 報文中使用多部分物件集合時, 需要在首部欄位里加上 Content-type, 有關這個首部欄位, 我們稍后講解,使用 boundary 字串來劃分多部分物件集合指明的各類物體, 在 boundary 字串指定的各個物體的起始行之前插入“--”標記(例如: --AaB03x、 --THIS_STRING_SEPARATES) , 而在多部分物件集合對應的字串的最后插入“--”標記(例如: --AaB03x--、 --THIS_STRING_SEPARATES--) 作為結束,多部分物件集合的每個部分型別中, 都可以含有首部欄位, 另外, 可以在某個部分中嵌套使用多部分物件集合,
獲取部分內容的范圍請求,
-
以前, 用戶不能使用現在這種高速的帶寬訪問互聯網, 當時, 下載一個尺寸稍大的圖片或檔案就已經很吃力了, 如果下載程序中遇到網路中斷的情況, 那就必須重頭開始, 為了解決上述問題, 需要一種可恢復的機制, 所謂恢復是指能從之前下載中斷處恢復下載,要實作該功能需要指定下載的物體范圍, 像這樣, 指定范圍發送的請求叫做范圍請求(Range Request) ,對一份 10000 位元組大小的資源, 如果使用范圍請求, 可以只請求 5001~10000 位元組內的資源,
-
執行范圍請求時, 會用到首部欄位 Range 來指定資源的 byte 范圍,byte 范圍的指定形式如下:
-
5001~10 000 位元組 : Range: bytes=5001-10000,
-
從 5001 位元組之后全部的 : Range: bytes=5001,
-
從一開始到 3000 位元組和 5000~7000 位元組的多重范圍 : Range: bytes=-3000, 5000-7000,
-
針對范圍請求, 回應會回傳狀態碼為 206 Partial Content 的回應報文, 另外, 對于多重范圍的范圍請求, 回應會在首部欄位 ContentType標明 multipart/byteranges 后回傳回應報文,如果服務器端無法回應范圍請求, 則會回傳狀態碼 200 OK 和完整的物體內容,
內容協商回傳最合適的內容,
-
同一個 Web 網站有可能存在著多份相同內容的頁面, 比如英語版和中文版的 Web 頁面, 它們內容上雖相同, 但使用的語言卻不同,當瀏覽器的默認語言為英語或中文, 訪問相同 URI 的 Web 頁面時,則會顯示對應的英語版或中文版的 Web 頁面, 這樣的機制稱為內容協商(Content Negotiation),
-
內容協商機制是指客戶端和服務器端就回應的資源內容進行交涉, 然后提供給客戶端最為適合的資源, 內容協商會以回應資源的語言、 字符集、 編碼方式等作為判斷的基準,包含在請求報文中的某些首部欄位就是判斷的基準,
-
內容協商技術有以下 3 種型別:
-
服務器驅動協商(Server-driven Negotiation) : 由服務器端進行內容協商, 以請求的首部欄位為參考, 在服務器端自動處理, 但對用戶來說, 以瀏覽器發送的資訊作為判定的依據, 并不一定能篩選出最優內容,
-
客戶端驅動協商(Agent-driven Negotiation) : 由客戶端進行內容協商的方式, 用戶從瀏覽器顯示的可選項串列中手動選擇, 還可以利用 JavaScript 腳本在 Web 頁面上自動進行上述選擇, 比如按 OS 的型別或瀏覽器型別, 自行切換成 PC 版頁面或手機版頁面,
-
透明協商(Transparent Negotiation) : 是服務器驅動和客戶端驅動的結合體, 是由服務器端和客戶端各自進行內容協商的一種方法,
回傳結果的 HTTP 狀態碼,
-
HTTP 狀態碼負責表示客戶端 HTTP 請求的回傳結果、 標記服務器端的處理是否正常、 通知出現的錯誤等作業,
-
狀態碼如 200 OK, 以 3 位數字和原因短語組成,數字中的第一位指定了回應類別, 后兩位無分類, 回應類別有以下 5 種,
只要遵守狀態碼類別的定義, 即使改變 RFC2616 中定義的狀態碼,或服務器端自行創建狀態碼都沒問題,
-
僅記錄在 RFC2616 上的 HTTP 狀態碼就達 40 種, 若再加上 WebDAV(Web-based Distributed Authoring and Versioning, 基于萬維網的分布式創作和版本控制)和附加 HTTP 狀態碼 (RFC6585) 等擴展, 數量就達 60 余種, 別看種類繁多, 實際上經常使用的大概只有 14 種, 接下來, 我們就介紹一下這些具有代表性的 14 個狀態碼,
2XX 成功,表明請求被正常處理了,
-
200 OK : 表示從客戶端發來的請求在服務器端被正常處理了,在回應報文內, 隨狀態碼一起回傳的資訊會因方法的不同而發生改變, 比如, 使用 GET 方法時, 對應請求資源的物體會作為回應回傳; 而使用 HEAD方法時, 對應請求資源的物體首部不隨報文主體作為回應回傳(即在回應中只回傳首部, 不會回傳物體的主體部分) ,
-
204 No Content : 該狀態碼代表服務器接收的請求已成功處理, 但在回傳的回應報文中不含物體的主體部分,另外, 也不允許回傳任何物體的主體, 比如,當從瀏覽器發出請求處理后, 回傳 204 回應, 那么瀏覽器顯示的頁面不發生更新,一般在只需要從客戶端往服務器發送資訊, 而對客戶端不需要發送新資訊內容的情況下使用,
-
206 Partial Content : 該狀態碼表示客戶端進行了范圍請求, 而服務器成功執行了這部分的 GET 請求, 回應報文中包含由 Content-Range 指定范圍的物體內容,
3XX 重定向,表明瀏覽器需要執行某些特殊的處理以正確處理請求,
-
301 Moved Permanently : 永久性重定向, 該狀態碼表示請求的資源已被分配了新的 URI, 以后 應使用資源現在所指的 URI, 也就是說, 如果已經把資源對應的 URI 保存為書簽了, 這時應該按 Location 首部欄位提示的 URI 重新保存,像下方給出的請求 URI, 當指定資源路徑的最后忘記添加斜杠“/”, 就會產生 301 狀態碼,
-
302 Found : 臨時性重定向, 該狀態碼表示請求的資源已被分配了新的 URI, 希望用戶(本次) 能使用新的 URI 訪問,和 301 Moved Permanently 狀態碼相似, 但 302 狀態碼代表的資源不是被永久移動,只是臨時性質的, 換句話說, 已移動的資源對應的 URI 將來還有可能發生改變, 比如, 用戶把 URI 保存成書簽, 但不會像 301 狀態碼出現時那樣去更新書簽, 而是仍舊保留回傳 302 狀態碼的頁面對應的 URI,
-
303 See Other : 該狀態碼表示由于請求對應的資源存在著另一個 URI, 應使用 GET 方法定向獲取請求的資源,303 狀態碼和 302 Found 狀態碼有著相同的功能, 但 303 狀態碼明確表示客戶端應當采用 GET 方法獲取資源, 這點與 302 狀態碼有區別,比如, 當使用 POST 方法訪問 CGI 程式, 其執行后的處理結果是希望客戶端能以 GET 方法重定向到另一個 URI 上去時, 回傳 303 狀態碼, 雖然 302 Found 狀態碼也可以實作相同的功能, 但這里使用 303 狀態碼是最理想的,
當 301、 302、 303 回應狀態碼回傳時, 幾乎所有的瀏覽器都會把 POST 改成 GET, 并洗掉請求報文內的主體, 之后請求會自動再次發送,301、 302 標準是禁止將 POST 方法改變成 GET 方法的, 但實際使用時大家都會這么做,
-
304 Not Modified : 該狀態碼表示客戶端發送附帶條件(附帶條件的請求是指采用 GET方法的請求報文中包含 If-Match, If-ModifiedSince, If-None-Match, If-Range, If-Unmodified-Since 中任一首部,)的請求時, 服務器端允許請求訪問資源, 但未滿足條件的情況, 304 狀態碼回傳時, 不包含任何回應的主體部分, 304 雖然被劃分在 3XX 類別中, 但是和重定向沒有關 系,
-
307 Temporary Redirect : 臨時重定向, 該狀態碼與 302 Found 有著相同的含義, 盡管 302 標準禁止 POST 變換成 GET, 但實際使用時大家并不遵守,307 會遵照瀏覽器標準, 不會從 POST 變成 GET, 但是, 對于處理回應時的行為, 每種瀏覽器有可能出現不同的情況,
4XX 客戶端錯誤,表明客戶端是發生錯誤的原因所在,
-
400 Bad Request : 該狀態碼表示請求報文中存在語法錯誤, 當錯誤發生時, 需修改請求的內容后再次發送請求, 另外, 瀏覽器會像 200 OK 一樣對待該狀態碼,
-
401 Unauthorized : 該狀態碼表示發送的請求需要有通過 HTTP 認證(BASIC 認證、DIGEST 認證) 的認證資訊, 另外若之前已進行過 1 次請求, 則表示用戶認證失敗,回傳含有 401 的回應必須包含一個適用于被請求資源的 WWW-Authenticate 首部用以質詢(challenge) 用戶資訊, 當瀏覽器初次接收到 401 回應, 會彈出認證用的對話視窗,
-
403 Forbidden : 該狀態碼表明對請求資源的訪問被服務器拒絕了, 服務器端沒有必要給出拒絕的詳細理由, 但如果想作說明的話, 可以在物體的主體部分對原因進行描述, 這樣就能讓用戶看到了,例如,未獲得檔案系統的訪問授權,訪問權限出現某些問題(從未授權的發送源 IP 地址試圖訪問) 等情況,
-
404 Not Found : 該狀態碼表明服務器上無法找到請求的資源, 除此之外, 也可以在服務器端拒絕請求且不想說明理由時使用,
5XX 服務器錯誤 : 表明服務器本身發生錯誤,
-
500 Internal Server Error : 該狀態碼表明服務器端在執行請求時發生了錯誤, 也有可能是 Web 應用存在的 bug 或某些臨時的故障,
-
503 Service Unavailable : 該狀態碼表明服務器暫時處于超負載或正在進行停機維護, 現在無法處理請求, 如果事先得知解除以上狀況需要的時間, 最好寫入 RetryAfter 首部欄位再回傳給客戶端,
狀態碼和狀況的不一致,不少回傳的狀態碼回應都是錯誤的, 但是用戶可能察覺不到這點,比如 Web 應用程式內部發生錯誤, 狀態碼依然回傳 200 OK, 這種情況也經常遇到,
與 HTTP 協作的 Web 服務器,
-
一臺 Web 服務器可搭建多個獨立域名的 Web 網站, 也可作為通信路徑上的中轉服務器提升傳輸效率,
用單臺虛擬主機實作多個域名,
-
HTTP/1.1 規范允許一臺 HTTP 服務器搭建多個 Web 站點, 比如, 提供 Web 托管服務(Web Hosting Service) 的供應商, 可以用一臺服務器為多位客戶服務, 也可以以每位客戶持有的域名運行各自不同的網站, 這是因為利用了虛擬主機(Virtual Host, 又稱虛擬服務器) 的功能,即使物理層面只有一臺服務器, 但只要使用虛擬主機的功能, 則可以假想已具有多臺服務器,
-
客戶端使用 HTTP 協議訪問服務器時, 會經常采用類似 www.hackr.jp 這樣的主機名和域名,在互聯網上, 域名通過 DNS 服務映射到 IP 地址(域名決議) 之后訪問目標網站, 可見, 當請求發送到服務器時, 已經是以 IP 地址形式訪問了,所以, 如果一臺服務器內托管了 www.tricorder.jp 和 www.hackr.jp 這兩個域名, 當收到請求時就需要弄清楚究竟要訪問哪個域名,在相同的 IP 地址下, 由于虛擬主機可以寄存多個不同主機名和域名的 Web 網站, 因此在發送 HTTP 請求時, 必須在 Host 首部內完整指定主機名或域名的 URI,
通信資料轉發程式 : 代理、 網關、 隧道,
-
HTTP 通信時, 除客戶端和服務器以外, 還有一些用于通信資料轉發的應用程式, 例如代理、 網關和隧道, 它們可以配合服務器作業,這些應用程式和服務器可以將請求轉發給通信線路上的下一站服務器, 并且能接收從那臺服務器發送的回應再轉發給客戶端,
-
代理 : 代理是一種有轉發功能的應用程式, 它扮演了位于服務器和客戶端“中間人”的角色, 接收由客戶端發送的請求并轉發給服務器, 同時也接收服務器回傳的回應并轉發給客戶端,
-
代理服務器的基本行為就是接收客戶端發送的請求后轉發給其他服務器, 代理不改變請求 URI, 會直接發送給前方持有資源的目標服務器,持有資源物體的服務器被稱為源服務器, 從源服務器回傳的回應經過代理服務器后再傳給客戶端,
-
每次通過代理服務器轉發請求或回應時, 會追加寫入 Via 首部資訊,在 HTTP 通信程序中, 可級聯多臺代理服務器,請求和回應的轉發會經過數臺類似鎖鏈一樣連接起來的代理服務器, 轉發時, 需要附加 Via 首部欄位以標記出經過的主機資訊,
-
使用代理服務器的理由有: 利用快取技術(稍后講解) 減少網路帶寬的流量, 組織內部針對特定網站的訪問控制, 以獲取訪問日志為主要目的,代理有多種使用方法, 按兩種基準分類, 一種是是否使用快取, 另一種是是否會修改報文:
-
快取代理 : 代理轉發回應時, 快取代理(Caching Proxy) 會預先將資源的副本(快取) 保存在代理服務器上,當代理再次接收到對相同資源的請求時, 就可以不從源服務器那里獲取資源, 而是將之前快取的資源作為回應回傳,
-
透明代理 : 轉發請求或回應時, 不對報文做任何加工的代理型別被稱為透明代理(Transparent Proxy) , 反之, 對報文內容進行加工的代理被稱為非透明代理,
-
網關 : 網關是轉發其他服務器通信資料的服務器, 接收從客戶端發送來的請求時, 它就像自己擁有資源的源服務器一樣對請求進行處理, 有時客戶端可能都不會察覺, 自己的通信目標是一個網關,
-
利用網關可以由 HTTP 請求轉化為其他協議通信網關的作業機制和代理十分相似, 而網關能使通信線路上的服務器提供非 HTTP 協議服務,利用網關能提高通信的安全性, 因為可以在客戶端與網關之間的通信線路上加密以確保連接的安全, 比如, 網關可以連接資料庫, 使用 SQL 陳述句查詢資料, 另外, 在 Web 購物網站上進行信用卡結算時,網關可以和信用卡結算系統聯動,
-
隧道 : 隧道是在相隔甚遠的客戶端和服務器兩者之間進行中轉, 并保持雙方通信連接的應用程式,
-
隧道可按要求建立起一條與其他服務器的通信線路, 屆時使用 SSL 等加密手段進行通信, 隧道的目的是確保客戶端能與服務器進行安全的通信,隧道本身不會去決議 HTTP 請求, 也就是說, 請求保持原樣中轉給之后的服務器, 隧道會在通信雙方斷開連接時結束,通過隧道的傳輸, 可以和遠距離的服務器安全通信, 隧道本身是透明的, 客戶端不用在意隧道的存在,
保存資源的快取,
-
快取是指代理服務器或客戶端本地磁盤內保存的資源副本, 利用快取可減少對源服務器的訪問, 因此也就節省了通信流量和通信時間,快取服務器是代理服務器的一種, 并歸類在快取代理型別中, 換句話說, 當代理轉發從服務器回傳的回應時, 代理服務器將會保存一份資源的副本,快取服務器的優勢在于利用快取可避免多次從源服務器轉發資源, 因此客戶端可就近從快取服務器上獲取資源, 而源服務器也不必多次處理相同的請求了,
-
即便快取服務器內有快取, 也不能保證每次都會回傳對同資源的請求, 因為這關系到被快取資源的有效性問題,當遇上源服務器上的資源更新時, 如果還是使用不變的快取, 那就會演變成回傳更新前的“舊”資源了,即使存在快取, 也會因為客戶端的要求、 快取的有效期等因素, 向源服務器確認資源的有效性, 若判斷快取失效, 快取服務器將會再次從源服務器上獲取“新”資源,
-
快取不僅可以存在于快取服務器內, 還可以存在客戶端瀏覽器中, 以 Internet Explorer 程式為例, 把客戶端快取稱為臨時網路檔案(Temporary Internet File) ,瀏覽器快取如果有效, 就不必再向服務器請求相同的資源了, 可以直接從本地磁盤內讀取,另外, 和快取服務器相同的一點是, 當判定快取過期后, 會向源服務器確認資源的有效性, 若判斷瀏覽器快取失效, 瀏覽器會再次請求新資源,
HTTP 首部,
-
HTTP 協議的請求和回應報文中必定包含 HTTP 首部, 只是我們平時在使用 Web 的程序中感受不到它,
HTTP 報文首部,
-
HTTP 協議的請求和回應報文中必定包含 HTTP 首部, 首部內容為客戶端和服務器分別處理請求和回應提供所需要的資訊, 對于客戶端用戶來說, 這些資訊中的大部分內容都無須親自查看,報文首部由幾個欄位構成:
-
HTTP 回應報文 : 在回應中, HTTP 報文由 HTTP 版本、 狀態碼(數字和原因短語) 、HTTP 首部欄位 3 部分構成,
-
HTTP 請求報文 : 在請求中, HTTP 報文由方法、 URI、 HTTP 版本、 HTTP 首部欄位等部分構成,
-
在報文眾多的欄位當中, HTTP 首部欄位包含的資訊最為豐富, 首部欄位同時存在于請求和回應報文內, 并涵蓋 HTTP 報文相關的內容資訊,
HTTP 首部欄位,
-
HTTP 首部欄位傳遞重要資訊 : HTTP 首部欄位是構成 HTTP 報文的要素之一, 在客戶端與服務器之間以 HTTP 協議進行通信的程序中, 無論是請求還是回應都會使用首部欄位, 它能起到傳遞額外重要資訊的作用,使用首部欄位是為了給瀏覽器和服務器提供報文主體大小、 所使用的語言、 認證資訊等內容,
-
HTTP 首部欄位結構 : HTTP 首部欄位是由首部欄位名和欄位值構成的, 中間用冒號 “:” 分隔,
-
例如, 在 HTTP 首部中以 Content-Type 這個欄位來表示報文主體的物件型別,
-
就以上述示例來看, 首部欄位名為 Content-Type, 字串 text/html 是欄位值,另外, 欄位值對應單個 HTTP 首部欄位可以有多個值, 如下所示,
當 HTTP 報文首部中出現了兩個或兩個以上具有相同首部欄位名時會怎么樣? 這種情況在規范內尚未明確, 根據瀏覽器內部處理邏輯的不同, 結果可能并不一致, 有些瀏覽器會優先處理第一次出現的首部欄位, 而有些則會優先處理最后出現的首部欄位,
4 種 HTTP 首部欄位型別,
-
通用首部欄位(General Header Fields) : 請求報文和回應報文兩方都會使用的首部,
-
請求首部欄位(Request Header Fields) : 從客戶端向服務器端發送請求報文時使用的首部, 補充了請求的附加內容、 客戶端資訊、 回應內容相關優先級等資訊,
-
回應首部欄位(Response Header Fields) : 從服務器端向客戶端回傳回應報文時使用的首部, 補充了回應的附加內容, 也會要求客戶端附加額外的內容資訊,
-
物體首部欄位(Entity Header Fields) : 針對請求報文和回應報文的物體部分使用的首部, 補充了資源內容更新時間等與物體有關的資訊,
HTTP/1.1 47 種首部欄位一覽,
-
通用首部欄位:
-
請求首部欄位:
-
回應首部欄位:
-
物體首部欄位:
非 HTTP/1.1 首部欄位,
-
在 HTTP 協議通信互動中使用到的首部欄位, 不限于 RFC2616 中定義的 47 種首部欄位, 還有 Cookie、 Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部欄位, 它們的使用頻率也很高,
End-to-end 首部和 Hop-by-hop 首部,
-
HTTP 首部欄位將定義成快取代理和非快取代理的行為, 分成 2 種型別,
-
端到端首部(End-to-end Header) : 分在此類別中的首部會轉發給請求 / 回應對應的最終接收目標, 且必 須保存在由快取生成的回應中, 另外規定它必須被轉發,
-
逐跳首部(Hop-by-hop Header) : 分在此類別中的首部只對單次轉發有效, 會因通過快取或代理而不再轉發, HTTP/1.1 和之后版本中, 如果要使用 hop-by-hop 首部, 需提供 Connection 首部欄位,下面列舉了 HTTP/1.1 中的逐跳首部欄位, 除這 8 個首部欄位之外,其他所有欄位都屬于端到端首部:
-
Connection
-
Keep-Alive
-
Proxy-Authenticate
-
Proxy-Authorization
-
Trailer
-
TE
-
Transfer-Encoding
-
Upgrade
HTTP/1.1 通用首部欄位,
-
通用首部欄位是指, 請求報文和回應報文雙方都會使用的首部,
Cache-Control,
-
通過指定首部欄位 Cache-Control 的指令, 就能操作快取的作業機制,
-
首部欄位 Cache-Control 能夠控制快取的行為指令的引數是可選的, 多個指令之間通過“,”分隔, 首部欄位 CacheControl 的指令可用于請求及回應時,
-
Cache-Control 可用的指令按請求和回應分類如下所示:
-
表示是否能快取的指令 :
-
public 指令 :當指定使用 public 指令時, 則明確表明其他用戶也可利用快取,
-
private 指令 : 當指定 private 指令后, 回應只以特定的用戶作為物件, 這與 public 指令的行為相反,快取服務器會對該特定用戶提供資源快取的服務, 對于其他用戶發送過來的請求, 代理服務器則不會回傳快取,
-
no-cache 指令 : 使用 no-cache 指令的目的是為了防止從快取中回傳過期的資源,客戶端發送的請求中如果包含 no-cache 指令, 則表示客戶端將不會接收快取過的回應, 于是, “中間” 的快取服務器必須把客戶端請求轉發給源服務器,如果服務器回傳的回應中包含 no-cache 指令, 那么快取服務器不能對資源進行快取, 源服務器以后也將不再對快取服務器請求中提出的資源有效性進行確認, 且禁止其對回應資源進行快取操作,由服務器回傳的回應中, 若報文首部欄位 Cache-Control 中對 no-cache 欄位名具體指定引數值, 那么客戶端在接收到這個被指定引數值的首部欄位對應的回應報文后, 就不能使用快取, 換言之, 無引數值的首部欄位可以使用快取, 只能在回應指令中指定該引數,
-
控制可執行快取的物件的指令 :
-
no-store 指令 : 當使用 no-store 指令時, 暗示請求(和對應的回應) 或回應中包含機密資訊,因此, 該指令規定快取不能在本地存盤請求或回應的任一部分,
-
s-maxage 指令 : s-maxage 指令的功能和 max-age 指令的相同, 它們的不同點是 s-maxage 指令只適用于供多位用戶使用的公共快取服務器, 也就是說, 對于向同一用戶重復回傳回應的服務器來說, 這個指令沒有任何作用,另外, 當使用 s-maxage 指令后, 則直接忽略對 Expires 首部欄位及 max-age 指令的處理,
-
max-age 指令 : 當客戶端發送的請求中包含 max-age 指令時, 如果判定快取資源的快取時間數值比指定時間的數值更小, 那么客戶端就接收快取的資源,另外, 當指定 max-age 值為0, 那么快取服務器通常需要將請求轉發給源服務器,當服務器回傳的回應中包含 max-age 指令時, 快取服務器將不對資源的有效性再作確認, 而 max-age 數值代表資源保存為快取的最長時間,應用 HTTP/1.1 版本的快取服務器遇到同時存在 Expires 首部欄位的情況時, 會優先處理 max-age 指令, 而忽略掉 Expires 首部欄位, 而 HTTP/1.0 版本的快取服務器的情況卻相反, max-age指令會被忽略掉,
-
從字面意思上很容易把 **no-cache 誤解成為不快取, 但事實上 no-cache 代表不快取過期的資源, 快取會向源服務器進行有效期確認后處理資源, 也許稱為 do-notserve-from-cache-without-revalidation 更合適, no-store** 才是真正地不進行快取
-
min-fresh 指令 : min-fresh 指令要求快取服務器回傳至少還未過指定時間的快取資源,比如, 當指定 min-fresh 為 60 秒后, 過了 60 秒的資源都無法作為回應回傳了,
-
max-stale 指令 : 使用 max-stale 可指示快取資源, 即使過期也照常接收,如果指令未指定引數值, 那么無論經過多久, 客戶端都會接收回應,如果指令中指定了具體數值, 那么即使過期, 只要仍處于 max-stale 指定的時間內, 仍舊會被客戶端接收,
-
only-if-cached 指令 : 使用 only-if-cached 指令表示客戶端僅在快取服務器本地快取目標資源的情況下才會要求其回傳, 換言之, 該指令要求快取服務器不重新加載回應, 也不會再次確認資源有效性, 若發生請求快取服務器的本地快取無回應, 則回傳狀態碼 504 Gateway Timeout,
-
must-revalidate 指令 : 使用 must-revalidate 指令, 代理會向源服務器再次驗證即將回傳的回應快取目前是否仍然有效,若代理無法連通源服務器再次獲取有效資源的話, 快取必須給客戶端一條 504(Gateway Timeout) 狀態碼,另外, 使用 must-revalidate 指令會忽略請求的max-stale 指令(即使已經在首部使用了 max-stale, 也不會再有效果),
-
proxy-revalidate 指令 : proxy-revalidate 指令要求所有的快取服務器在接收到客戶端帶有該指令的請求回傳回應之前, 必須再次驗證快取的有效性,
-
no-transform 指令 : 使用 no-transform 指令規定無論是在請求還是回應中, 快取都不能改變物體主體的媒體型別,這樣做可防止快取或代理壓縮圖片等類似操作,
-
Cache-Control 擴展,
-
cache-extension token : 通過 cache-extension 標記(token) , 可以擴展 Cache-Control 首部欄位內的指令,如鞋面的例子, Cache-Control 首部欄位本身沒有 community 這個指令, 借助 extension tokens 實作了該指令的添加, 如果快取服務器不能理解 community這個新指令, 就會直接忽略, 因此, extension tokens 僅對能理解它的快取服務器來說是有意義的,
Connection,
-
Connection 首部欄位具備如下兩個作用:
-
控制不再轉發給代理的首部欄位,
-
管理持久連接,
-
控制不再轉發給代理的首部欄位 : 在客戶端發送請求和服務器回傳回應內, 使用 Connection 首部欄位, 可控制不再轉發給代理的首部欄位(即 Hop-by-hop 首部),
-
管理持久連接 : HTTP/1.1 版本的默認連接都是持久連接, 為此, 客戶端會在持久連接上連續發送請求,當服務器端想明確斷開連接時, 則指定 Connection 首部欄位的值為 Close,HTTP/1.1 之前的HTTP 版本的默認連接都是非持久連接, 為此, 如果想在舊版本的 HTTP 協議上維持持續連接, 則需要指定 Connection 首部欄位的值為 Keep-Alive,
Date,
-
首部欄位 Date 表明創建 HTTP 報文的日期和時間,
-
HTTP/1.1 協議使用在 RFC1123 中規定的日期時間的格式, 如下示例:
-
之前的 HTTP 協議版本中使用在 RFC850 中定義的格式, 如下所示:
-
除此之外, 還有一種格式, 它與 C 標準庫內的 asctime() 函式的輸出格式一致:
Pragma,
-
Pragma 是 HTTP/1.1 之前版本的歷史遺留欄位, 僅作為與 HTTP/1.0 的向后兼容而定義,規范定義的形式唯一, 如下所示:
-
該首部欄位屬于通用首部欄位, 但只用在客戶端發送的請求中, 客戶端會要求所有的中間服務器不回傳快取的資源,
-
所有的中間服務器如果都能以 HTTP/1.1 為基準, 那直接采用 CacheControl: no-cache 指定快取的處理方式是最為理想的, 但要整體掌握全部中間服務器使用的 HTTP 協議版本卻是不現實的, 因此, 發送的請求會同時含有下面兩個首部欄位,
Trailer,
-
首部欄位 Trailer 會事先說明在報文主體后記錄了哪些首部欄位, 該首部欄位可應用在 HTTP/1.1 版本分塊傳輸編碼時,
以上用例中, 指定首部欄位 Trailer 的值為 Expires , 在報文主體之后(分塊長度 0 之后) 出現了首部欄位Expires ,
Transfer-Encoding,
-
首部欄位 Transfer-Encoding 規定了傳輸報文主體時采用的編碼方式,HTTP/1.1的傳輸編碼方式僅對分塊傳輸編碼有效,
以上用例中, 正如在首部欄位 Transfer-Encoding 中指定的那樣, 有效使用分塊傳輸編碼, 且分別被分成3312 位元組和 914 位元組大小的分塊資料,
Upgrade,
-
首部欄位 Upgrade 用于檢測 HTTP 協議及其他協議是否可使用更高的版本進行通信, 其引數值可以用來指定一個完全不同的通信協議,
-
上圖用例中, 首部欄位 Upgrade 指定的值為 TLS/1.0, 請注意此處兩個欄位首部欄位的對應關系,Connection 的值被指定為 Upgrade,Upgrade 首部欄位產生作用的 Upgrade 物件僅限于客戶端和鄰接服務器之間, 因此, 使用首部欄位 Upgrade 時, 還需要額外指定 Connection:Upgrade,對于附有首部欄位 Upgrade 的請求, 服務器可用 101 Switching Protocols 狀態碼作為回應回傳,
Via,
-
使用首部欄位 Via 是為了追蹤客戶端與服務器之間的請求和回應報文的傳輸路徑,報文經過代理或網關時, 會先在首部欄位 Via 中附加該服務器的資訊, 然后再進行轉發, 這個做法和 traceroute 及電子郵件的 Received 首部的作業機制很類似,首部欄位 Via 不僅用于追蹤報文的轉發, 還可避免請求回環的發生,所以必須在經過代理時附加該首部欄位內容,
-
上圖用例中, 在經過代理服務器 A 時, Via 首部附加了“1.0 gw.hackr.jp (Squid/3.1)”這樣的字串值, 行頭的 1.0 是指接收請求的服務器上應用的 HTTP協議版本, 接下來經過代理服務器 B 時亦是如此, 在 Via 首部附加服務器資訊, 也可增加 1 個新的 Via 首部寫入服務器資訊,Via 首部是為了追蹤傳輸路徑, 所以經常會和 TRACE 方法一起使用, 比如, 代理服務器接收到由 TRACE 方法發送過來的請求(其中 Max-Forwards: 0) 時, 代理服務器就不能再轉發該請求了, 這種情況下, 代理服務器會將自身的資訊附加到 Via 首部后, 回傳該請求的回應,
Warning,
-
HTTP/1.1 的 Warning 首部是從 HTTP/1.0 的回應首部(Retry-After) 演變過來的, 該首部通常會告知用戶一些與快取相關的問題的警告,
-
Warning 首部的格式如下, 最后的日期時間部分可省略,
-
HTTP/1.1 中定義了 7 種警告, 警告碼對應的警告內容僅推薦參考,另外, 警告碼具備擴展性, 今后有可能追加新的警告碼,
回應首部欄位,
-
回應首部欄位是由服務器端向客戶端回傳回應報文中所使用的欄位,用于補充回應的附加資訊、 服務器資訊, 以及對客戶端的附加要求等資訊,
Accept-Ranges,
當不能處理范圍請求時, Accept-Ranges: none
-
首部欄位 Accept-Ranges 是用來告知客戶端服務器是否能處理范圍請求, 以指定獲取服務器端某個部分的資源,可指定的欄位值有兩種, 可處理范圍請求時指定其為 bytes, 反之則指定其為 none,
Age,
-
首部欄位 Age 能告知客戶端, 源服務器在多久前創建了回應, 欄位值的單位為秒,若創建該回應的服務器是快取服務器, Age 值是指快取后的回應再次發起認證到認證完成的時間值, 代理創建回應時必須加上首部欄位 Age,
ETag,
-
首部欄位 ETag 能告知客戶端物體標識, 它是一種可將資源以字串形式做唯一性標識的方式, 服務器會為每份資源分配對應的 ETag 值,另外, 當資源更新時, ETag值也需要更新, 生成 ETag 值時, 并沒有統一的演算法規則, 而僅僅是由服務器來分配,
-
資源被快取時, 就會被分配唯一性標識, 例如, 當使用中文版的瀏覽器訪問http://www.google.com/ 時, 就會回傳中文版對應的資源, 而使用英文版的瀏覽器訪問時, 則會回傳英文版對應的資源, 兩者的 URI 是相同的, 所以僅憑 URI指定快取的資源是相當困難的, 若在下載程序中出現連接中斷、 再連接的情況, 都會依照 ETag 值來指定資源,
-
ETag 中有 強 ETag 值 和 弱 ETag 值 之分:
-
強 ETag 值 : 不論物體發生多么細微的變化都會改變其值,
-
弱 ETag 值 : 弱 ETag 值 只用于提示資源是否相同, 只有資源發生了根本改變, 產生差異時才會改變 ETag 值, 這時, 會在欄位值最開始處附加 W/,
Location,
-
使用首部欄位 Location 可以將回應接收方引導至某個與請求 URI 位置不同的資源,基本上, 該欄位會配合 3xx : Redirection 的回應, 提供重定向的 URI,幾乎所有的瀏覽器在接收到包含首部欄位Location 的回應后, 都會強制性地嘗試對已提示的重定向資源的訪問,
Proxy-Authenticate,
-
首部欄位 Proxy-Authenticate 會把由代理服務器所要求的認證資訊發送給客戶端,它與客戶端和服務器之間的 HTTP 訪問認證的行為相似, 不同之處在于其認證行為是在客戶端與代理之間進行的, 而客戶端與服務器之間進行認證時, 首部欄位 WWW-Authorization 有著相同的作用,
Retry-After,
-
首部欄位 Retry-After 告知客戶端應該在多久之后再次發送請求, 主要配合狀態碼 503 Service Unavailable 回應, 或 3xx Redirect 回應一起使用,欄位值可以指定為具體的日期時間(Wed, 04 Jul 2012 06: 34: 24 GMT 等格式) , 也可以是創建回應后的秒數,
Server,
-
首部欄位 Server 告知客戶端當前服務器上安裝的 HTTP 服務器應用程式的資訊, 不單單會標出服務器上的軟體應用名稱, 還有可能包括版本號和安裝時啟用的可選項,
Vary,
當代理服務器接收到帶有 **Vary 首部欄位指定獲取資源的請求時, 如果使用的 Accept-Language** 欄位的值相同, 那么就直接從快取回傳回應, 反之, 則需要先從源服務器端獲取資源后才能作為回應回傳
-
首部欄位 Vary 可對快取進行控制, 源服務器會向代理服務器傳達關于本地快取使用方法的命令,從代理服務器接收到源服務器回傳包含 Vary 指定項的回應之后, 若再要進行快取, 僅對請求中含有相同Vary 指定首部欄位的請求回傳快取, 即使對相同資源發起請求, 但由于 Vary 指定的首部欄位不相同, 因此必須要從源服務器重新獲取資源,
WWW-Authenticate,
-
首部欄位 WWW-Authenticate 用于 HTTP 訪問認證, 它會告知客戶端適用于訪問請求 URI 所指定資源的認證方案(Basic 或是 Digest) 和帶引數提示的質詢(challenge) , 狀態碼 401 Unauthorized 回應中,肯定帶有首部欄位 WWW-Authenticate,
realm 欄位的字串是為了辨別請求 URI 指定資源所受到的保護策略,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/103831.html
標籤:其他
上一篇:王爽匯編實驗(九)
