图解http协议
圖解傳說中的HTTP協議
轉自頭條號豬哥亮額先扒一扒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:John.Doe@example.com
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?指定資源所受到的保護策略。
</div></div>
總結
- 上一篇: 基于vue,解决打开新窗口被浏览器拦截的
- 下一篇: WPS格式转换成Word的方法