整合營(yíng)銷(xiāo)服務(wù)商

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

          免費(fèi)咨詢(xún)熱線(xiàn):

          全網(wǎng)分析HTTP協(xié)議最全的一篇文章,程序員趕緊收藏

          全網(wǎng)分析HTTP協(xié)議最全的一篇文章,程序員趕緊收藏

          注于Java領(lǐng)域優(yōu)質(zhì)技術(shù),歡迎關(guān)注

          作者:滌生_Woo

          本篇文章篇幅比較長(zhǎng),先來(lái)個(gè)思維導(dǎo)圖預(yù)覽一下。

          一張圖帶你看完本篇文章

          一、概述

          1.計(jì)算機(jī)網(wǎng)絡(luò)體系結(jié)構(gòu)分層

          計(jì)算機(jī)網(wǎng)絡(luò)體系結(jié)構(gòu)分層

          2.TCP/IP 通信傳輸流

          利用 TCP/IP 協(xié)議族進(jìn)行網(wǎng)絡(luò)通信時(shí),會(huì)通過(guò)分層順序與對(duì)方進(jìn)行通信。發(fā)送端從應(yīng)用層往下走,接收端則從鏈路層往上走。如下:

          TCP/IP 通信傳輸流

          • 首先作為發(fā)送端的客戶(hù)端在應(yīng)用層(HTTP 協(xié)議)發(fā)出一個(gè)想看某個(gè) Web 頁(yè)面的 HTTP 請(qǐng)求。
          • 接著,為了傳輸方便,在傳輸層(TCP 協(xié)議)把從應(yīng)用層處收到的數(shù)據(jù)(HTTP 請(qǐng)求報(bào)文)進(jìn)行分割,并在各個(gè)報(bào)文上打上標(biāo)記序號(hào)及端口號(hào)后轉(zhuǎn)發(fā)給網(wǎng)絡(luò)層。
          • 在網(wǎng)絡(luò)層(IP 協(xié)議),增加作為通信目的地的 MAC 地址后轉(zhuǎn)發(fā)給鏈路層。這樣一來(lái),發(fā)往網(wǎng)絡(luò)的通信請(qǐng)求就準(zhǔn)備齊全了。
          • 接收端的服務(wù)器在鏈路層接收到數(shù)據(jù),按序往上層發(fā)送,一直到應(yīng)用層。當(dāng)傳輸?shù)綉?yīng)用層,才能算真正接收到由客戶(hù)端發(fā)送過(guò)來(lái)的 HTTP請(qǐng)求。

          如下圖所示:

          HTTP 請(qǐng)求

          在網(wǎng)絡(luò)體系結(jié)構(gòu)中,包含了眾多的網(wǎng)絡(luò)協(xié)議,這篇文章主要圍繞 HTTP 協(xié)議(HTTP/1.1版本)展開(kāi)。

          HTTP協(xié)議(HyperText Transfer Protocol,超文本傳輸協(xié)議)是用于從WWW服務(wù)器傳輸超文本到本地瀏覽器的傳輸協(xié)議。它可以使瀏覽器更加高效,使網(wǎng)絡(luò)傳輸減少。它不僅保證計(jì)算機(jī)正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內(nèi)容首先顯示(如文本先于圖形)等。
           HTTP是客戶(hù)端瀏覽器或其他程序與Web服務(wù)器之間的應(yīng)用層通信協(xié)議。在Internet上的Web服務(wù)器上存放的都是超文本信息,客戶(hù)機(jī)需要通過(guò)HTTP協(xié)議傳輸所要訪(fǎng)問(wèn)的超文本信息。HTTP包含命令和傳輸信息,不僅可用于Web訪(fǎng)問(wèn),也可以用于其他因特網(wǎng)/內(nèi)聯(lián)網(wǎng)應(yīng)用系統(tǒng)之間的通信,從而實(shí)現(xiàn)各類(lèi)應(yīng)用資源超媒體訪(fǎng)問(wèn)的集成。
           我們?cè)跒g覽器的地址欄里輸入的網(wǎng)站地址叫做URL (Uniform Resource Locator,統(tǒng)一資源定位符)。就像每家每戶(hù)都有一個(gè)門(mén)牌地址一樣,每個(gè)網(wǎng)頁(yè)也都有一個(gè)Internet地址。當(dāng)你在瀏覽器的地址框中輸入一個(gè)URL或是單擊一個(gè)超級(jí)鏈接時(shí),URL就確定了要瀏覽的地址。瀏覽器通過(guò)超文本傳輸協(xié)議(HTTP),將Web服務(wù)器上站點(diǎn)的網(wǎng)頁(yè)代碼提取出來(lái),并翻譯成漂亮的網(wǎng)頁(yè)。
          

          二、HTTP 工作過(guò)程

          HTTP請(qǐng)求響應(yīng)模型

          HTTP通信機(jī)制是在一次完整的 HTTP 通信過(guò)程中,客戶(hù)端與服務(wù)器之間將完成下列7個(gè)步驟:

          1 建立 TCP 連接

          在HTTP工作開(kāi)始之前,客戶(hù)端首先要通過(guò)網(wǎng)絡(luò)與服務(wù)器建立連接,該連接是通過(guò) TCP 來(lái)完成的,該協(xié)議與 IP 協(xié)議共同構(gòu)建 Internet,即著名的 TCP/IP 協(xié)議族,因此 Internet 又被稱(chēng)作是 TCP/IP 網(wǎng)絡(luò)。HTTP 是比 TCP 更高層次的應(yīng)用層協(xié)議,根據(jù)規(guī)則,只有低層協(xié)議建立之后,才能進(jìn)行高層協(xié)議的連接,因此,首先要建立 TCP 連接,一般 TCP 連接的端口號(hào)是80;

          2 客戶(hù)端向服務(wù)器發(fā)送請(qǐng)求命令

          一旦建立了TCP連接,客戶(hù)端就會(huì)向服務(wù)器發(fā)送請(qǐng)求命令;

          例如:GET/sample/hello.jsp HTTP/1.1

          3 客戶(hù)端發(fā)送請(qǐng)求頭信息

          客戶(hù)端發(fā)送其請(qǐng)求命令之后,還要以頭信息的形式向服務(wù)器發(fā)送一些別的信息,之后客戶(hù)端發(fā)送了一空白行來(lái)通知服務(wù)器,它已經(jīng)結(jié)束了該頭信息的發(fā)送;

          4 服務(wù)器應(yīng)答

          客戶(hù)端向服務(wù)器發(fā)出請(qǐng)求后,服務(wù)器會(huì)客戶(hù)端返回響應(yīng);

          例如: HTTP/1.1 200 OK

          響應(yīng)的第一部分是協(xié)議的版本號(hào)和響應(yīng)狀態(tài)碼

          5 服務(wù)器返回響應(yīng)頭信息

          正如客戶(hù)端會(huì)隨同請(qǐng)求發(fā)送關(guān)于自身的信息一樣,服務(wù)器也會(huì)隨同響應(yīng)向用戶(hù)發(fā)送關(guān)于它自己的數(shù)據(jù)及被請(qǐng)求的文檔;

          6 服務(wù)器向客戶(hù)端發(fā)送數(shù)據(jù)

          服務(wù)器向客戶(hù)端發(fā)送頭信息后,它會(huì)發(fā)送一個(gè)空白行來(lái)表示頭信息的發(fā)送到此為結(jié)束,接著,它就以 Content-Type 響應(yīng)頭信息所描述的格式發(fā)送用戶(hù)所請(qǐng)求的實(shí)際數(shù)據(jù);

          7 服務(wù)器關(guān)閉 TCP 連接

          一般情況下,一旦服務(wù)器向客戶(hù)端返回了請(qǐng)求數(shù)據(jù),它就要關(guān)閉 TCP 連接,然后如果客戶(hù)端或者服務(wù)器在其頭信息加入了這行代碼 Connection:keep-alive ,TCP 連接在發(fā)送后將仍然保持打開(kāi)狀態(tài),于是,客戶(hù)端可以繼續(xù)通過(guò)相同的連接發(fā)送請(qǐng)求。保持連接節(jié)省了為每個(gè)請(qǐng)求建立新連接所需的時(shí)間,還節(jié)約了網(wǎng)絡(luò)帶寬。

          三、HTTP 協(xié)議基礎(chǔ)

          1.通過(guò)請(qǐng)求和響應(yīng)的交換達(dá)成通信

          應(yīng)用 HTTP 協(xié)議時(shí),必定是一端擔(dān)任客戶(hù)端角色,另一端擔(dān)任服務(wù)器端角色。僅從一條通信線(xiàn)路來(lái)說(shuō),服務(wù)器端和客服端的角色是確定的。HTTP 協(xié)議規(guī)定,請(qǐng)求從客戶(hù)端發(fā)出,最后服務(wù)器端響應(yīng)該請(qǐng)求并返回。換句話(huà)說(shuō),肯定是先從客戶(hù)端開(kāi)始建立通信的,服務(wù)器端在沒(méi)有接收到請(qǐng)求之前不會(huì)發(fā)送響應(yīng)。

          2.HTTP 是不保存狀態(tài)的協(xié)議

          HTTP 是一種無(wú)狀態(tài)協(xié)議。協(xié)議自身不對(duì)請(qǐng)求和響應(yīng)之間的通信狀態(tài)進(jìn)行保存。也就是說(shuō)在 HTTP 這個(gè)級(jí)別,協(xié)議對(duì)于發(fā)送過(guò)的請(qǐng)求或響應(yīng)都不做持久化處理。這是為了更快地處理大量事務(wù),確保協(xié)議的可伸縮性,而特意把 HTTP 協(xié)議設(shè)計(jì)成如此簡(jiǎn)單的。

          可是隨著 Web 的不斷發(fā)展,我們的很多業(yè)務(wù)都需要對(duì)通信狀態(tài)進(jìn)行保存。于是我們引入了 Cookie 技術(shù)。有了 Cookie 再用 HTTP 協(xié)議通信,就可以管理狀態(tài)了。

          3.使用 Cookie 的狀態(tài)管理

          Cookie 技術(shù)通過(guò)在請(qǐng)求和響應(yīng)報(bào)文中寫(xiě)入 Cookie 信息來(lái)控制客戶(hù)端的狀態(tài)。Cookie 會(huì)根據(jù)從服務(wù)器端發(fā)送的響應(yīng)報(bào)文內(nèi)的一個(gè)叫做 Set-Cookie 的首部字段信息,通知客戶(hù)端保存Cookie。當(dāng)下次客戶(hù)端再往該服務(wù)器發(fā)送請(qǐng)求時(shí),客戶(hù)端會(huì)自動(dòng)在請(qǐng)求報(bào)文中加入 Cookie 值后發(fā)送出去。服務(wù)器端發(fā)現(xiàn)客戶(hù)端發(fā)送過(guò)來(lái)的 Cookie 后,會(huì)去檢查究竟是從哪一個(gè)客戶(hù)端發(fā)來(lái)的連接請(qǐng)求,然后對(duì)比服務(wù)器上的記錄,最后得到之前的狀態(tài)信息。

          Cookie 的流程

          4.請(qǐng)求 URI 定位資源

          HTTP 協(xié)議使用 URI 定位互聯(lián)網(wǎng)上的資源。正是因?yàn)?URI 的特定功能,在互聯(lián)網(wǎng)上任意位置的資源都能訪(fǎng)問(wèn)到。

          5.告知服務(wù)器意圖的 HTTP 方法(HTTP/1.1)

          HTTP 方法

          6.持久連接

          HTTP 協(xié)議的初始版本中,每進(jìn)行一個(gè) HTTP 通信都要斷開(kāi)一次 TCP 連接。比如使用瀏覽器瀏覽一個(gè)包含多張圖片的 HTML 頁(yè)面時(shí),在發(fā)送請(qǐng)求訪(fǎng)問(wèn) HTML 頁(yè)面資源的同時(shí),也會(huì)請(qǐng)求該 HTML 頁(yè)面里包含的其他資源。因此,每次的請(qǐng)求都會(huì)造成無(wú)畏的 TCP 連接建立和斷開(kāi),增加通信量的開(kāi)銷(xiāo)。

          為了解決上述 TCP 連接的問(wèn)題,HTTP/1.1 和部分 HTTP/1.0 想出了持久連接的方法。其特點(diǎn)是,只要任意一端沒(méi)有明確提出斷開(kāi)連接,則保持 TCP 連接狀態(tài)。旨在建立一次 TCP 連接后進(jìn)行多次請(qǐng)求和響應(yīng)的交互。在 HTTP/1.1 中,所有的連接默認(rèn)都是持久連接。

          7.管線(xiàn)化

          持久連接使得多數(shù)請(qǐng)求以管線(xiàn)化方式發(fā)送成為可能。以前發(fā)送請(qǐng)求后需等待并接收到響應(yīng),才能發(fā)送下一個(gè)請(qǐng)求。管線(xiàn)化技術(shù)出現(xiàn)后,不用等待亦可發(fā)送下一個(gè)請(qǐng)求。這樣就能做到同時(shí)并行發(fā)送多個(gè)請(qǐng)求,而不需要一個(gè)接一個(gè)地等待響應(yīng)了。

          比如,當(dāng)請(qǐng)求一個(gè)包含多張圖片的 HTML 頁(yè)面時(shí),與挨個(gè)連接相比,用持久連接可以讓請(qǐng)求更快結(jié)束。而管線(xiàn)化技術(shù)要比持久連接速度更快。請(qǐng)求數(shù)越多,時(shí)間差就越明顯。

          四、HTTP 協(xié)議報(bào)文結(jié)構(gòu)

          1.HTTP 報(bào)文

          用于 HTTP 協(xié)議交互的信息被稱(chēng)為 HTTP 報(bào)文。請(qǐng)求端(客戶(hù)端)的 HTTP 報(bào)文叫做請(qǐng)求報(bào)文;響應(yīng)端(服務(wù)器端)的叫做響應(yīng)報(bào)文。HTTP 報(bào)文本身是由多行(用 CR+LF 作換行符)數(shù)據(jù)構(gòu)成的字符串文本。

          2.HTTP 報(bào)文結(jié)構(gòu)

          HTTP 報(bào)文大致可分為報(bào)文首部和報(bào)文主體兩部分。兩者由最初出現(xiàn)的空行(CR+LF)來(lái)劃分。通常,并不一定有報(bào)文主體。如下:

          HTTP 報(bào)文結(jié)構(gòu)

          2.1請(qǐng)求報(bào)文結(jié)構(gòu)

          請(qǐng)求報(bào)文結(jié)構(gòu)

          請(qǐng)求報(bào)文的首部?jī)?nèi)容由以下數(shù)據(jù)組成:

          • 請(qǐng)求行 —— 包含用于請(qǐng)求的方法、請(qǐng)求 URI 和 HTTP 版本。
          • 首部字段 —— 包含表示請(qǐng)求的各種條件和屬性的各類(lèi)首部。(通用首部、請(qǐng)求首部、實(shí)體首部以及RFC里未定義的首部如 Cookie 等)

          請(qǐng)求報(bào)文的示例,如下:

          請(qǐng)求報(bào)文示例

          2.2響應(yīng)報(bào)文結(jié)構(gòu)

          響應(yīng)報(bào)文結(jié)構(gòu)

          響應(yīng)報(bào)文的首部?jī)?nèi)容由以下數(shù)據(jù)組成:

          • 狀態(tài)行 —— 包含表明響應(yīng)結(jié)果的狀態(tài)碼、原因短語(yǔ)和 HTTP 版本。
          • 首部字段 —— 包含表示請(qǐng)求的各種條件和屬性的各類(lèi)首部。(通用首部、響應(yīng)首部、實(shí)體首部以及RFC里未定義的首部如 Cookie 等)

          響應(yīng)報(bào)文的示例,如下:

          響應(yīng)報(bào)文示例

          五、HTTP 報(bào)文首部之請(qǐng)求行、狀態(tài)行

          1.請(qǐng)求行

          舉個(gè)栗子,下面是一個(gè) HTTP 請(qǐng)求的報(bào)文:

          GET /index.htm HTTP/1.1
          Host: sample.com
          

          其中,下面的這行就是請(qǐng)求行,

          GET /index.htm HTTP/1.1
          
          • 開(kāi)頭的 GET 表示請(qǐng)求訪(fǎng)問(wèn)服務(wù)器的類(lèi)型,稱(chēng)為方法;
          • 隨后的字符串 /index.htm 指明了請(qǐng)求訪(fǎng)問(wèn)的資源對(duì)象,也叫做請(qǐng)求 URI;
          • 最后的 HTTP/1.1,即 HTTP 的版本號(hào),用來(lái)提示客戶(hù)端使用的 HTTP 協(xié)議功能。

          綜合來(lái)看,大意是請(qǐng)求訪(fǎng)問(wèn)某臺(tái) HTTP 服務(wù)器上的 /index.htm 頁(yè)面資源。

          2.狀態(tài)行

          同樣舉個(gè)栗子,下面是一個(gè) HTTP 響應(yīng)的報(bào)文:

          HTTP/1.1 200 OK
          Date: Mon, 10 Jul 2017 15:50:06 GMT
          Content-Length: 256
          Content-Type: text/html
           
          <html>
          ...
          

          其中,下面的這行就是狀態(tài)行,

          HTTP/1.1 200 OK
          
          • 開(kāi)頭的 HTTP/1.1 表示服務(wù)器對(duì)應(yīng)的 HTTP 版本;
          • 緊挨著的 200 OK 表示請(qǐng)求的處理結(jié)果的狀態(tài)碼和原因短語(yǔ)。

          六、HTTP 報(bào)文首部之首部字段(重點(diǎn)分析)

          1.首部字段概述

          先來(lái)回顧一下首部字段在報(bào)文的位置,HTTP 報(bào)文包含報(bào)文首部和報(bào)文主體,報(bào)文首部包含請(qǐng)求行(或狀態(tài)行)和首部字段。

          在報(bào)文眾多的字段當(dāng)中,HTTP 首部字段包含的信息最為豐富。首部字段同時(shí)存在于請(qǐng)求和響應(yīng)報(bào)文內(nèi),并涵蓋 HTTP 報(bào)文相關(guān)的內(nèi)容信息。使用首部字段是為了給客服端和服務(wù)器端提供報(bào)文主體大小、所使用的語(yǔ)言、認(rèn)證信息等內(nèi)容。

          2.首部字段結(jié)構(gòu)

          • HTTP 首部字段是由首部字段名和字段值構(gòu)成的,中間用冒號(hào)“:”分隔。
          • 另外,字段值對(duì)應(yīng)單個(gè) HTTP 首部字段可以有多個(gè)值。
          • 當(dāng) HTTP 報(bào)文首部中出現(xiàn)了兩個(gè)或以上具有相同首部字段名的首部字段時(shí),這種情況在規(guī)范內(nèi)尚未明確,根據(jù)瀏覽器內(nèi)部處理邏輯的不同,優(yōu)先處理的順序可能不同,結(jié)果可能并不一致。

          3.首部字段類(lèi)型

          首部字段根據(jù)實(shí)際用途被分為以下4種類(lèi)型:

          4.通用首部字段(HTTP/1.1)

          4.1 Cache-Control

          通過(guò)指定首部字段 Cache-Control 的指令,就能操作緩存的工作機(jī)制。

          4.1.1 可用的指令一覽

          可用的指令按請(qǐng)求和響應(yīng)分類(lèi)如下:

          緩存請(qǐng)求指令

          緩存響應(yīng)指令

          4.1.2 表示能否緩存的指令

          public 指令

           Cache-Control: public
          

          當(dāng)指定使用 public 指令時(shí),則明確表明其他用戶(hù)也可利用緩存。

          private 指令

           Cache-Control: private
          

          當(dāng)指定 private 指令后,響應(yīng)只以特定的用戶(hù)作為對(duì)象,這與 public 指令的行為相反。緩存服務(wù)器會(huì)對(duì)該特定用戶(hù)提供資源緩存的服務(wù),對(duì)于其他用戶(hù)發(fā)送過(guò)來(lái)的請(qǐng)求,代理服務(wù)器則不會(huì)返回緩存。

          no-cache 指令

           Cache-Control: no-cache
          
          • 使用 no-cache 指令是為了防止從緩存中返回過(guò)期的資源。
          • 客戶(hù)端發(fā)送的請(qǐng)求中如果包含 no-cache 指令,則表示客戶(hù)端將不會(huì)接收緩存過(guò)的響應(yīng)。于是,“中間”的緩存服務(wù)器必須把客戶(hù)端請(qǐng)求轉(zhuǎn)發(fā)給源服務(wù)器。
          • 如果服務(wù)器中返回的響應(yīng)包含 no-cache 指令,那么緩存服務(wù)器不能對(duì)資源進(jìn)行緩存。源服務(wù)器以后也將不再對(duì)緩存服務(wù)器請(qǐng)求中提出的資源有效性進(jìn)行確認(rèn),且禁止其對(duì)響應(yīng)資源進(jìn)行緩存操作。
          Cache-Control: no-cache=Location
          

          由服務(wù)器返回的響應(yīng)中,若報(bào)文首部字段 Cache-Control 中對(duì) no-cache 字段名具體指定參數(shù)值,那么客戶(hù)端在接收到這個(gè)被指定參數(shù)值的首部字段對(duì)應(yīng)的響應(yīng)報(bào)文后,就不能使用緩存。換言之,無(wú)參數(shù)值的首部字段可以使用緩存。只能在響應(yīng)指令中指定該參數(shù)。

          no-store 指令

           Cache-Control: no-store
          

          當(dāng)使用 no-store 指令時(shí),暗示請(qǐng)求(和對(duì)應(yīng)的響應(yīng))或響應(yīng)中包含機(jī)密信息。因此,該指令規(guī)定緩存不能在本地存儲(chǔ)請(qǐng)求或響應(yīng)的任一部分。

          注意:no-cache 指令代表不緩存過(guò)期的指令,緩存會(huì)向源服務(wù)器進(jìn)行有效期確認(rèn)后處理資源;no-store 指令才是真正的不進(jìn)行緩存。

          4.1.3 指定緩存期限和認(rèn)證的指令

          s-maxage 指令

           Cache-Control: s-maxage=604800(單位:秒)
          
          • s-maxage 指令的功能和 max-age 指令的相同,它們的不同點(diǎn)是 s-maxage 指令只適用于供多位用戶(hù)使用的公共緩存服務(wù)器(一般指代理)。也就是說(shuō),對(duì)于向同一用戶(hù)重復(fù)返回響應(yīng)的服務(wù)器來(lái)說(shuō),這個(gè)指令沒(méi)有任何作用。
          • 另外,當(dāng)使用 s-maxage 指令后,則直接忽略對(duì) Expires 首部字段及 max-age 指令的處理。

          max-age 指令

           Cache-Control: max-age=604800(單位:秒)
          
          • 當(dāng)客戶(hù)端發(fā)送的請(qǐng)求中包含 max-age 指令時(shí),如果判定緩存資源的緩存時(shí)間數(shù)值比指定的時(shí)間更小,那么客戶(hù)端就接收緩存的資源。另外,當(dāng)指定 max-age 的值為0,那么緩存服務(wù)器通常需要將請(qǐng)求轉(zhuǎn)發(fā)給源服務(wù)器。
          • 當(dāng)服務(wù)器返回的響應(yīng)中包含 max-age 指令時(shí),緩存服務(wù)器將不對(duì)資源的有效性再作確認(rèn),而 max-age 數(shù)值代表資源保存為緩存的最長(zhǎng)時(shí)間。
          • 應(yīng)用 HTTP/1.1 版本的緩存服務(wù)器遇到同時(shí)存在 Expires 首部字段的情況時(shí),會(huì)優(yōu)先處理 max-age 指令,并忽略掉 Expires 首部字段;而 HTTP/1.0 版本的緩存服務(wù)器則相反。

          min-fresh 指令

           Cache-Control: min-fresh=60(單位:秒)
          

          min-fresh 指令要求緩存服務(wù)器返回至少還未過(guò)指定時(shí)間的緩存資源。

          max-stale 指令

          Cache-Control: max-stale=3600(單位:秒)

          • 使用 max-stale 可指示緩存資源,即使過(guò)期也照常接收。
          • 如果指令未指定參數(shù)值,那么無(wú)論經(jīng)過(guò)多久,客戶(hù)端都會(huì)接收響應(yīng);如果指定了具體參數(shù)值,那么即使過(guò)期,只要仍處于 max-stale 指定的時(shí)間內(nèi),仍舊會(huì)被客戶(hù)端接收。

          only-if-cached 指令

           Cache-Control: only-if-cached
          

          表示客戶(hù)端僅在緩存服務(wù)器本地緩存目標(biāo)資源的情況下才會(huì)要求其返回。換言之,該指令要求緩存服務(wù)器不重新加載響應(yīng),也不會(huì)再次確認(rèn)資源的有效性。

          must-revalidate 指令

           Cache-Control: must-revalidate
          

          使用 must-revalidate 指令,代理會(huì)向源服務(wù)器再次驗(yàn)證即將返回的響應(yīng)緩存目前是否仍有效。另外,使用 must-revalidate 指令會(huì)忽略請(qǐng)求的 max-stale 指令。

          proxy-revalidate 指令

           Cache-Control: proxy-revalidate
          

          proxy-revalidate 指令要求所有的緩存服務(wù)器在接收到客戶(hù)端帶有該指令的請(qǐng)求返回響應(yīng)之前,必須再次驗(yàn)證緩存的有效性。

          no-transform 指令

           Cache-Control: no-transform
          

          使用 no-transform 指令規(guī)定無(wú)論是在請(qǐng)求還是響應(yīng)中,緩存都不能改變實(shí)體主體的媒體類(lèi)型。這樣做可防止緩存或代理壓縮圖片等類(lèi)似操作。

          4.1.4 Cache-Control 擴(kuò)展

          Cache-Control: private, community="UCI"
          

          通過(guò) cache-extension 標(biāo)記(token),可以擴(kuò)展 Cache-Control 首部字段內(nèi)的指令。上述 community 指令即擴(kuò)展的指令,如果緩存服務(wù)器不能理解這個(gè)新指令,就會(huì)直接忽略掉。

          4.2 Connection

          Connection 首部字段具備以下兩個(gè)作用:

          控制不再轉(zhuǎn)發(fā)的首部字段

           Connection: Upgrade
          

          在客戶(hù)端發(fā)送請(qǐng)求和服務(wù)器返回響應(yīng)中,使用 Connection 首部字段,可控制不再轉(zhuǎn)發(fā)給代理的首部字段,即刪除后再轉(zhuǎn)發(fā)(即Hop-by-hop首部)。

          管理持久連接

           Connection: close
          

          HTTP/1.1 版本的默認(rèn)連接都是持久連接。當(dāng)服務(wù)器端想明確斷開(kāi)連接時(shí),則指定 Connection 首部字段的值為 close。

           Connection: Keep-Alive
          

          HTTP/1.1 之前的 HTTP 版本的默認(rèn)連接都是非持久連接。為此,如果想在舊版本的 HTTP 協(xié)議上維持持續(xù)連接,則需要指定 Connection 首部字段的值為 Keep-Alive。

          4.3 Date

          表明創(chuàng)建 HTTP 報(bào)文的日期和時(shí)間。

           Date: Mon, 10 Jul 2017 15:50:06 GMT
          

          HTTP/1.1 協(xié)議使用在 RFC1123 中規(guī)定的日期時(shí)間的格式。

          4.4 Pragma

          Pragma 首部字段是 HTTP/1.1 版本之前的歷史遺留字段,僅作為與 HTTP/1.0 的向后兼容而定義。

           Pragma: no-cache
          
          • 該首部字段屬于通用首部字段,但只用在客戶(hù)端發(fā)送的請(qǐng)求中,要求所有的中間服務(wù)器不返回緩存的資源。
          • 所有的中間服務(wù)器如果都能以 HTTP/1.1 為基準(zhǔn),那直接采用 Cache-Control: no-cache 指定緩存的處理方式最為理想。但是要整體掌握所有中間服務(wù)器使用的 HTTP 協(xié)議版本卻是不現(xiàn)實(shí)的,所以,發(fā)送的請(qǐng)求會(huì)同時(shí)包含下面兩個(gè)首部字段:
          Cache-Control: no-cache
          Pragma: no-cache
          

          4.5 Trailer

          Trailer: Expires
          

          首部字段 Trailer 會(huì)事先說(shuō)明在報(bào)文主體后記錄了哪些首部字段。可應(yīng)用在 HTTP/1.1 版本分塊傳輸編碼時(shí)。

          4.6 Transfer-Encoding

          Transfer-Encoding: chunked
          
          • 規(guī)定了傳輸報(bào)文主體時(shí)采用的編碼方式。
          • HTTP/1.1 的傳輸編碼方式僅對(duì)分塊傳輸編碼有效。

          4.7 Upgrade

          Upgrade: TSL/1.0
          

          用于檢測(cè) HTTP 協(xié)議及其他協(xié)議是否可使用更高的版本進(jìn)行通信,其參數(shù)值可以用來(lái)指定一個(gè)完全不同的通信協(xié)議。

          4.8 Via

          Via: 1.1 a1.sample.com(Squid/2.7)
          
          • 為了追蹤客戶(hù)端和服務(wù)器端之間的請(qǐng)求和響應(yīng)報(bào)文的傳輸路徑。
          • 報(bào)文經(jīng)過(guò)代理或網(wǎng)關(guān)時(shí),會(huì)現(xiàn)在首部字段 Via 中附加該服務(wù)器的信息,然后再進(jìn)行轉(zhuǎn)發(fā)。
          • 首部字段 Via 不僅用于追蹤報(bào)文的轉(zhuǎn)發(fā),還可避免請(qǐng)求回環(huán)的發(fā)生。

          4.9 Warning

          該首部字段通常會(huì)告知用戶(hù)一些與緩存相關(guān)的問(wèn)題的警告。

          Warning 首部字段的格式如下:

          Warning:[警告碼][警告的主機(jī):端口號(hào)] "[警告內(nèi)容]"([日期時(shí)間])

          最后的日期時(shí)間可省略。

          HTTP/1.1 中定義了7種警告,警告碼對(duì)應(yīng)的警告內(nèi)容僅推薦參考,另外,警告碼具備擴(kuò)展性,今后有可能追加新的警告碼。

          5. 請(qǐng)求首部字段(HTTP/1.1)

          5.1 Accept

          Accept: text/html, application/xhtml+xml, application/xml; q=0.5
          
          • Accept 首部字段可通知服務(wù)器,用戶(hù)代理能夠處理的媒體類(lèi)型及媒體類(lèi)型的相對(duì)優(yōu)先級(jí)。可使用 type/subtype 這種形式,一次指定多種媒體類(lèi)型。
          • 若想要給顯示的媒體類(lèi)型增加優(yōu)先級(jí),則使用 q=[數(shù)值] 來(lái)表示權(quán)重值,用分號(hào)(;)進(jìn)行分隔。權(quán)重值的范圍 0~1(可精確到小數(shù)點(diǎn)后三位),且 1 為最大值。不指定權(quán)重值時(shí),默認(rèn)為 1。

          5.2 Accept-Charset

          Accept-Charset: iso-8859-5, unicode-1-1; q=0.8
          

          Accept-Charset 首部字段可用來(lái)通知服務(wù)器用戶(hù)代理支持的字符集及字符集的相對(duì)優(yōu)先順序。另外,可一次性指定多種字符集。同樣使用 q=[數(shù)值] 來(lái)表示相對(duì)優(yōu)先級(jí)。

          5.3 Accept-Encoding

          Accept-Encoding: gzip, deflate
          

          Accept-Encoding 首部字段用來(lái)告知服務(wù)器用戶(hù)代理支持的內(nèi)容編碼及內(nèi)容編碼的優(yōu)先順序,并可一次性指定多種內(nèi)容編碼。同樣使用 q=[數(shù)值] 來(lái)表示相對(duì)優(yōu)先級(jí)。也可使用星號(hào)(*)作為通配符,指定任意的編碼格式。

          5.4 Accept-Language

          Accept-Lanuage: zh-cn,zh;q=0.7,en=us,en;q=0.3
          

          告知服務(wù)器用戶(hù)代理能夠處理的自然語(yǔ)言集(指中文或英文等),以及自然語(yǔ)言集的相對(duì)優(yōu)先級(jí),可一次性指定多種自然語(yǔ)言集。同樣使用 q=[數(shù)值] 來(lái)表示相對(duì)優(yōu)先級(jí)。

          5.5 Authorization

          Authorization: Basic ldfKDHKfkDdasSAEdasd==

          告知服務(wù)器用戶(hù)代理的認(rèn)證信息(證書(shū)值)。通常,想要通過(guò)服務(wù)器認(rèn)證的用戶(hù)代理會(huì)在接收到返回的 401 狀態(tài)碼響應(yīng)后,把首部字段 Authorization 加入請(qǐng)求中。共用緩存在接收到含有 Authorization 首部字段的請(qǐng)求時(shí)的操作處理會(huì)略有差異。

          5.6 Expect

          Expect: 100-continue
          

          告知服務(wù)器客戶(hù)端期望出現(xiàn)的某種特定行為。

          5.7 From

          From: Deeson_Woo@163.com
          

          告知服務(wù)器使用用戶(hù)代理的電子郵件地址。

          5.8 Host

          Host: www.jianshu.com
          
          • 告知服務(wù)器,請(qǐng)求的資源所處的互聯(lián)網(wǎng)主機(jī)和端口號(hào)。
          • Host 首部字段是 HTTP/1.1 規(guī)范內(nèi)唯一一個(gè)必須被包含在請(qǐng)求內(nèi)的首部字段。
          • 若服務(wù)器未設(shè)定主機(jī)名,那直接發(fā)送一個(gè)空值即可 Host: 。

          5.9 If-Match

          形如 If-xxx 這種樣式的請(qǐng)求首部字段,都可稱(chēng)為條件請(qǐng)求。服務(wù)器接收到附帶條件的請(qǐng)求后,只有判斷指定條件為真時(shí),才會(huì)執(zhí)行請(qǐng)求。

          If-Match: "123456"
          
          • 首部字段 If-Match,屬附帶條件之一,它會(huì)告知服務(wù)器匹配資源所用的實(shí)體標(biāo)記(ETag)值。這時(shí)的服務(wù)器無(wú)法使用弱 ETag 值。
          • 服務(wù)器會(huì)比對(duì) If-Match 的字段值和資源的 ETag 值,僅當(dāng)兩者一致時(shí),才會(huì)執(zhí)行請(qǐng)求。反之,則返回狀態(tài)碼 412 Precondition Failed 的響應(yīng)。
          • 還可以使用星號(hào)(*)指定 If-Match 的字段值。針對(duì)這種情況,服務(wù)器將會(huì)忽略 ETag 的值,只要資源存在就處理請(qǐng)求。

          5.10 If-Modified-Since

          If-Modified-Since: Mon, 10 Jul 2017 15:50:06 GMT
          
          • 首部字段 If-Modified-Since,屬附帶條件之一,用于確認(rèn)代理或客戶(hù)端擁有的本地資源的有效性。
          • 它會(huì)告知服務(wù)器若 If-Modified-Since 字段值早于資源的更新時(shí)間,則希望能處理該請(qǐng)求。而在指定 If-Modified-Since 字段值的日期時(shí)間之后,如果請(qǐng)求的資源都沒(méi)有過(guò)更新,則返回狀態(tài)碼 304 Not Modified 的響應(yīng)。

          5.11 If-None-Match

          If-None-Match: "123456"
          

          首部字段 If-None-Match 屬于附帶條件之一。它和首部字段 If-Match 作用相反。用于指定 If-None-Match 字段值的實(shí)體標(biāo)記(ETag)值與請(qǐng)求資源的 ETag 不一致時(shí),它就告知服務(wù)器處理該請(qǐng)求。

          5.12 If-Range

          If-Range: "123456"
          
          • 首部字段 If-Range 屬于附帶條件之一。它告知服務(wù)器若指定的 If-Range 字段值(ETag 值或者時(shí)間)和請(qǐng)求資源的 ETag 值或時(shí)間相一致時(shí),則作為范圍請(qǐng)求處理。反之,則返回全體資源。
          • 下面我們思考一下不使用首部字段 If-Range 發(fā)送請(qǐng)求的情況。服務(wù)器端的資源如果更新,那客戶(hù)端持有資源中的一部分也會(huì)隨之無(wú)效,當(dāng)然,范圍請(qǐng)求作為前提是無(wú)效的。這時(shí),服務(wù)器會(huì)暫且以狀態(tài)碼 412 Precondition Failed 作為響應(yīng)返回,其目的是催促客戶(hù)端再次發(fā)送請(qǐng)求。這樣一來(lái),與使用首部字段 If-Range 比起來(lái),就需要花費(fèi)兩倍的功夫。

          5.13 If-Unmodified-Since

          If-Unmodified-Since: Mon, 10 Jul 2017 15:50:06 GMT
          

          首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相反。它的作用的是告知服務(wù)器,指定的請(qǐng)求資源只有在字段值內(nèi)指定的日期時(shí)間之后,未發(fā)生更新的情況下,才能處理請(qǐng)求。如果在指定日期時(shí)間后發(fā)生了更新,則以狀態(tài)碼 412 Precondition Failed 作為響應(yīng)返回。

          5.14 Max-Forwards

          Max-Forwards: 10
          

          通過(guò) TRACE 方法或 OPTIONS 方法,發(fā)送包含首部字段 Max-Forwards 的請(qǐng)求時(shí),該字段以十進(jìn)制整數(shù)形式指定可經(jīng)過(guò)的服務(wù)器最大數(shù)目。服務(wù)器在往下一個(gè)服務(wù)器轉(zhuǎn)發(fā)請(qǐng)求之前,Max-Forwards 的值減 1 后重新賦值。當(dāng)服務(wù)器接收到 Max-Forwards 值為 0 的請(qǐng)求時(shí),則不再進(jìn)行轉(zhuǎn)發(fā),而是直接返回響應(yīng)。

          5.15 Proxy-Authorization

          Proxy-Authorization: Basic dGlwOjkpNLAGfFY5
          
          • 接收到從代理服務(wù)器發(fā)來(lái)的認(rèn)證質(zhì)詢(xún)時(shí),客戶(hù)端會(huì)發(fā)送包含首部字段 Proxy-Authorization 的請(qǐng)求,以告知服務(wù)器認(rèn)證所需要的信息。
          • 這個(gè)行為是與客戶(hù)端和服務(wù)器之間的 HTTP 訪(fǎng)問(wèn)認(rèn)證相類(lèi)似的,不同之處在于,認(rèn)證行為發(fā)生在客戶(hù)端與代理之間。

          5.16 Range

          Range: bytes=5001-10000
          
          • 對(duì)于只需獲取部分資源的范圍請(qǐng)求,包含首部字段 Range 即可告知服務(wù)器資源的指定范圍。
          • 接收到附帶 Range 首部字段請(qǐng)求的服務(wù)器,會(huì)在處理請(qǐng)求之后返回狀態(tài)碼為 206 Partial Content 的響應(yīng)。無(wú)法處理該范圍請(qǐng)求時(shí),則會(huì)返回狀態(tài)碼 200 OK 的響應(yīng)及全部資源。

          5.17 Referer

          Referer: http://www.sample.com/index.html
          

          首部字段 Referer 會(huì)告知服務(wù)器請(qǐng)求的原始資源的 URI。

          5.18 TE

          TE: gzip, deflate; q=0.5
          
          • 首部字段 TE 會(huì)告知服務(wù)器客戶(hù)端能夠處理響應(yīng)的傳輸編碼方式及相對(duì)優(yōu)先級(jí)。它和首部字段 Accept-Encoding 的功能很相像,但是用于傳輸編碼。
          • 首部字段 TE 除指定傳輸編碼之外,還可以指定伴隨 trailer 字段的分塊傳輸編碼的方式。應(yīng)用后者時(shí),只需把 trailers 賦值給該字段值。TE: trailers

          5.19 User-Agent

          User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101
          
          • 首部字段 User-Agent 會(huì)將創(chuàng)建請(qǐng)求的瀏覽器和用戶(hù)代理名稱(chēng)等信息傳達(dá)給服務(wù)器。
          • 由網(wǎng)絡(luò)爬蟲(chóng)發(fā)起請(qǐng)求時(shí),有可能會(huì)在字段內(nèi)添加爬蟲(chóng)作者的電子郵件地址。此外,如果請(qǐng)求經(jīng)過(guò)代理,那么中間也很可能被添加上代理服務(wù)器的名稱(chēng)。

          6. 響應(yīng)首部字段(HTTP/1.1)

          6.1 Accept-Ranges

          Accept-Ranges: bytes
          
          • 首部字段 Accept-Ranges 是用來(lái)告知客戶(hù)端服務(wù)器是否能處理范圍請(qǐng)求,以指定獲取服務(wù)器端某個(gè)部分的資源。
          • 可指定的字段值有兩種,可處理范圍請(qǐng)求時(shí)指定其為 bytes,反之則指定其為 none。

          6.2 Age

          Age: 1200
          
          • 首部字段 Age 能告知客戶(hù)端,源服務(wù)器在多久前創(chuàng)建了響應(yīng)。字段值的單位為秒。
          • 若創(chuàng)建該響應(yīng)的服務(wù)器是緩存服務(wù)器,Age 值是指緩存后的響應(yīng)再次發(fā)起認(rèn)證到認(rèn)證完成的時(shí)間值。代理創(chuàng)建響應(yīng)時(shí)必須加上首部字段 Age。

          6.3 ETag

          ETag: "usagi-1234"
          
          • 首部字段 ETag 能告知客戶(hù)端實(shí)體標(biāo)識(shí)。它是一種可將資源以字符串形式做唯一性標(biāo)識(shí)的方式。服務(wù)器會(huì)為每份資源分配對(duì)應(yīng)的 ETag 值。
          • 另外,當(dāng)資源更新時(shí),ETag 值也需要更新。生成 ETag 值時(shí),并沒(méi)有統(tǒng)一的算法規(guī)則,而僅僅是由服務(wù)器來(lái)分配。
          • ETag 中有強(qiáng) ETag 值和弱 ETag 值之分。強(qiáng) ETag 值,不論實(shí)體發(fā)生多么細(xì)微的變化都會(huì)改變其值;弱 ETag 值只用于提示資源是否相同。只有資源發(fā)生了根本改變,產(chǎn)生差異時(shí)才會(huì)改變 ETag 值。這時(shí),會(huì)在字段值最開(kāi)始處附加 W/: ETag: W/"usagi-1234"。

          6.4 Location

          Location: http://www.sample.com/sample.html
          
          • 使用首部字段 Location 可以將響應(yīng)接收方引導(dǎo)至某個(gè)與請(qǐng)求 URI 位置不同的資源。
          • 基本上,該字段會(huì)配合 3xx :Redirection 的響應(yīng),提供重定向的 URI。
          • 幾乎所有的瀏覽器在接收到包含首部字段 Location 的響應(yīng)后,都會(huì)強(qiáng)制性地嘗試對(duì)已提示的重定向資源的訪(fǎng)問(wèn)。

          6.5 Proxy-Authenticate

          Proxy-Authenticate: Basic realm="Usagidesign Auth"
          
          • 首部字段 Proxy-Authenticate 會(huì)把由代理服務(wù)器所要求的認(rèn)證信息發(fā)送給客戶(hù)端。
          • 它與客戶(hù)端和服務(wù)器之間的 HTTP 訪(fǎng)問(wèn)認(rèn)證的行為相似,不同之處在于其認(rèn)證行為是在客戶(hù)端與代理之間進(jìn)行的。

          6.6 Retry-After

          Retry-After: 180
          
          • 首部字段 Retry-After 告知客戶(hù)端應(yīng)該在多久之后再次發(fā)送請(qǐng)求。主要配合狀態(tài)碼 503 Service Unavailable 響應(yīng),或 3xx Redirect 響應(yīng)一起使用。
          • 字段值可以指定為具體的日期時(shí)間(Mon, 10 Jul 2017 15:50:06 GMT 等格式),也可以是創(chuàng)建響應(yīng)后的秒數(shù)。

          6.7 Server

          Server: Apache/2.2.6 (Unix) PHP/5.2.5
          

          首部字段 Server 告知客戶(hù)端當(dāng)前服務(wù)器上安裝的 HTTP 服務(wù)器應(yīng)用程序的信息。不單單會(huì)標(biāo)出服務(wù)器上的軟件應(yīng)用名稱(chēng),還有可能包括版本號(hào)和安裝時(shí)啟用的可選項(xiàng)。

          6.8 Vary

          Vary: Accept-Language
          
          • 首部字段 Vary 可對(duì)緩存進(jìn)行控制。源服務(wù)器會(huì)向代理服務(wù)器傳達(dá)關(guān)于本地緩存使用方法的命令。
          • 從代理服務(wù)器接收到源服務(wù)器返回包含 Vary 指定項(xiàng)的響應(yīng)之后,若再要進(jìn)行緩存,僅對(duì)請(qǐng)求中含有相同 Vary 指定首部字段的請(qǐng)求返回緩存。即使對(duì)相同資源發(fā)起請(qǐng)求,但由于 Vary 指定的首部字段不相同,因此必須要從源服務(wù)器重新獲取資源。

          6.9 WWW-Authenticate

          WWW-Authenticate: Basic realm="Usagidesign Auth"
          

          首部字段 WWW-Authenticate 用于 HTTP 訪(fǎng)問(wèn)認(rèn)證。它會(huì)告知客戶(hù)端適用于訪(fǎng)問(wèn)請(qǐng)求 URI 所指定資源的認(rèn)證方案(Basic 或是 Digest)和帶參數(shù)提示的質(zhì)詢(xún)(challenge)。

          7. 實(shí)體首部字段(HTTP/1.1)

          7.1 Allow

          Allow: GET, HEAD
          
          • 首部字段 Allow 用于通知客戶(hù)端能夠支持 Request-URI 指定資源的所有 HTTP 方法。
          • 當(dāng)服務(wù)器接收到不支持的 HTTP 方法時(shí),會(huì)以狀態(tài)碼 405 Method Not Allowed 作為響應(yīng)返回。與此同時(shí),還會(huì)把所有能支持的 HTTP 方法寫(xiě)入首部字段 Allow 后返回。

          7.2 Content-Encoding

          Content-Encoding: gzip
          
          • 首部字段 Content-Encoding 會(huì)告知客戶(hù)端服務(wù)器對(duì)實(shí)體的主體部分選用的內(nèi)容編碼方式。內(nèi)容編碼是指在不丟失實(shí)體信息的前提下所進(jìn)行的壓縮。
          • 主要采用這 4 種內(nèi)容編碼的方式(gzip、compress、deflate、identity)。

          7.3 Content-Language

          Content-Language: zh-CN
          

          首部字段 Content-Language 會(huì)告知客戶(hù)端,實(shí)體主體使用的自然語(yǔ)言(指中文或英文等語(yǔ)言)。

          7.4 Content-Length

          Content-Length: 15000
          

          首部字段 Content-Length 表明了實(shí)體主體部分的大小(單位是字節(jié))。對(duì)實(shí)體主體進(jìn)行內(nèi)容編碼傳輸時(shí),不能再使用 Content-Length首部字段。

          7.5 Content-Location

          Content-Location: http://www.sample.com/index.html
          

          首部字段 Content-Location 給出與報(bào)文主體部分相對(duì)應(yīng)的 URI。和首部字段 Location 不同,Content-Location 表示的是報(bào)文主體返回資源對(duì)應(yīng)的 URI。

          7.6 Content-MD5

          Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==

          首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于檢查報(bào)文主體在傳輸過(guò)程中是否保持完整,以及確認(rèn)傳輸?shù)竭_(dá)。

          7.7 Content-Range

          Content-Range: bytes 5001-10000/10000
          

          針對(duì)范圍請(qǐng)求,返回響應(yīng)時(shí)使用的首部字段 Content-Range,能告知客戶(hù)端作為響應(yīng)返回的實(shí)體的哪個(gè)部分符合范圍請(qǐng)求。字段值以字節(jié)為單位,表示當(dāng)前發(fā)送部分及整個(gè)實(shí)體大小。

          7.8 Content-Type

          Content-Type: text/html; charset=UTF-8
          

          首部字段 Content-Type 說(shuō)明了實(shí)體主體內(nèi)對(duì)象的媒體類(lèi)型。和首部字段 Accept 一樣,字段值用 type/subtype 形式賦值。參數(shù) charset 使用 iso-8859-1 或 euc-jp 等字符集進(jìn)行賦值。

          7.9 Expires

          Expires: Mon, 10 Jul 2017 15:50:06 GMT
          
          • 首部字段 Expires 會(huì)將資源失效的日期告知客戶(hù)端。
          • 緩存服務(wù)器在接收到含有首部字段 Expires 的響應(yīng)后,會(huì)以緩存來(lái)應(yīng)答請(qǐng)求,在 Expires 字段值指定的時(shí)間之前,響應(yīng)的副本會(huì)一直被保存。當(dāng)超過(guò)指定的時(shí)間后,緩存服務(wù)器在請(qǐng)求發(fā)送過(guò)來(lái)時(shí),會(huì)轉(zhuǎn)向源服務(wù)器請(qǐng)求資源。
          • 源服務(wù)器不希望緩存服務(wù)器對(duì)資源緩存時(shí),最好在 Expires 字段內(nèi)寫(xiě)入與首部字段 Date 相同的時(shí)間值。

          7.10 Last-Modified

          Last-Modified: Mon, 10 Jul 2017 15:50:06 GMT
          

          首部字段 Last-Modified 指明資源最終修改的時(shí)間。一般來(lái)說(shuō),這個(gè)值就是 Request-URI 指定資源被修改的時(shí)間。但類(lèi)似使用 CGI 腳本進(jìn)行動(dòng)態(tài)數(shù)據(jù)處理時(shí),該值有可能會(huì)變成數(shù)據(jù)最終修改時(shí)的時(shí)間。

          8. 為 Cookie 服務(wù)的首部字段

          8.1 Set-Cookie

          Set-Cookie: status=enable; expires=Mon, 10 Jul 2017 15:50:06 GMT; path=/;
          

          下面的表格列舉了 Set-Cookie 的字段值。

          8.1.1 expires 屬性

          • Cookie 的 expires 屬性指定瀏覽器可發(fā)送 Cookie 的有效期。
          • 當(dāng)省略 expires 屬性時(shí),其有效期僅限于維持瀏覽器會(huì)話(huà)(Session)時(shí)間段內(nèi)。這通常限于瀏覽器應(yīng)用程序被關(guān)閉之前。
          • 另外,一旦 Cookie 從服務(wù)器端發(fā)送至客戶(hù)端,服務(wù)器端就不存在可以顯式刪除 Cookie 的方法。但可通過(guò)覆蓋已過(guò)期的 Cookie,實(shí)現(xiàn)對(duì)客戶(hù)端 Cookie 的實(shí)質(zhì)性刪除操作。

          8.1.2 path 屬性

          Cookie 的 path 屬性可用于限制指定 Cookie 的發(fā)送范圍的文件目錄。

          8.1.3 domain 屬性

          • 通過(guò) Cookie 的 domain 屬性指定的域名可做到與結(jié)尾匹配一致。比如,當(dāng)指定 example.com 后,除example.com 以外,www.example.com 或 www2.example.com 等都可以發(fā)送 Cookie。
          • 因此,除了針對(duì)具體指定的多個(gè)域名發(fā)送 Cookie 之 外,不指定 domain 屬性顯得更安全。

          8.1.4 secure 屬性

          Cookie 的 secure 屬性用于限制 Web 頁(yè)面僅在 HTTPS 安全連接時(shí),才可以發(fā)送 Cookie。

          8.1.5 HttpOnly 屬性

          • Cookie 的 HttpOnly 屬性是 Cookie 的擴(kuò)展功能,它使 JavaScript 腳本無(wú)法獲得 Cookie。其主要目的為防止跨站腳本攻擊(Cross-site scripting,XSS)對(duì) Cookie 的信息竊取。
          • 通過(guò)上述設(shè)置,通常從 Web 頁(yè)面內(nèi)還可以對(duì) Cookie 進(jìn)行讀取操作。但使用 JavaScript 的 document.cookie 就無(wú)法讀取附加 HttpOnly 屬性后的 Cookie 的內(nèi)容了。因此,也就無(wú)法在 XSS 中利用 JavaScript 劫持 Cookie 了。

          8.2 Cookie

          Cookie: status=enable
          

          首部字段 Cookie 會(huì)告知服務(wù)器,當(dāng)客戶(hù)端想獲得 HTTP 狀態(tài)管理支持時(shí),就會(huì)在請(qǐng)求中包含從服務(wù)器接收到的 Cookie。接收到多個(gè) Cookie 時(shí),同樣可以以多個(gè) Cookie 形式發(fā)送。

          9. 其他首部字段

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

          以下是最為常用的首部字段。

          9.1 X-Frame-Options

          X-Frame-Options: DENY
          

          首部字段 X-Frame-Options 屬于 HTTP 響應(yīng)首部,用于控制網(wǎng)站內(nèi)容在其他 Web 網(wǎng)站的 Frame 標(biāo)簽內(nèi)的顯示問(wèn)題。其主要目的是為了防止點(diǎn)擊劫持(clickjacking)攻擊。首部字段 X-Frame-Options 有以下兩個(gè)可指定的字段值:

          • DENY:拒絕
          • SAMEORIGIN:僅同源域名下的頁(yè)面(Top-level-browsing-context)匹配時(shí)許可。(比如,當(dāng)指定 http://sample.com/sample.html 頁(yè)面為 SAMEORIGIN 時(shí),那么 sample.com 上所有頁(yè)面的 frame 都被允許可加載該頁(yè)面,而 example.com 等其他域名的頁(yè)面就不行了)

          9.2 X-XSS-Protection

          X-XSS-Protection: 1
          

          首部字段 X-XSS-Protection 屬于 HTTP 響應(yīng)首部,它是針對(duì)跨站腳本攻擊(XSS)的一種對(duì)策,用于控制瀏覽器 XSS 防護(hù)機(jī)制的開(kāi)關(guān)。首部字段 X-XSS-Protection 可指定的字段值如下:

          • 0 :將 XSS 過(guò)濾設(shè)置成無(wú)效狀態(tài)
          • 1 :將 XSS 過(guò)濾設(shè)置成有效狀態(tài)

          9.3 DNT

          DNT: 1
          

          首部字段 DNT 屬于 HTTP 請(qǐng)求首部,其中 DNT 是 Do Not Track 的簡(jiǎn)稱(chēng),意為拒絕個(gè)人信息被收集,是表示拒絕被精準(zhǔn)廣告追蹤的一種方法。首部字段 DNT 可指定的字段值如下:

          • 0 :同意被追蹤
          • 1 :拒絕被追蹤

          由于首部字段 DNT 的功能具備有效性,所以 Web 服務(wù)器需要對(duì) DNT做對(duì)應(yīng)的支持。

          9.4 P3P

          P3P: CP="CAO DSP LAW CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa OUR BUS IND
          

          首部字段 P3P 屬于 HTTP 響應(yīng)首部,通過(guò)利用 P3P(The Platform for Privacy Preferences,在線(xiàn)隱私偏好平臺(tái))技術(shù),可以讓 Web 網(wǎng)站上的個(gè)人隱私變成一種僅供程序可理解的形式,以達(dá)到保護(hù)用戶(hù)隱私的目的。

          要進(jìn)行 P3P 的設(shè)定,需按以下操作步驟進(jìn)行:

          • 步驟 1:創(chuàng)建 P3P 隱私
          • 步驟 2:創(chuàng)建 P3P 隱私對(duì)照文件后,保存命名在 /w3c/p3p.xml
          • 步驟 3:從 P3P 隱私中新建 Compact policies 后,輸出到 HTTP 響應(yīng)中

          七、HTTP 響應(yīng)狀態(tài)碼(重點(diǎn)分析)

          1. 狀態(tài)碼概述

          • HTTP 狀態(tài)碼負(fù)責(zé)表示客戶(hù)端 HTTP 請(qǐng)求的返回結(jié)果、標(biāo)記服務(wù)器端的處理是否正常、通知出現(xiàn)的錯(cuò)誤等工作。
          • HTTP 狀態(tài)碼如 200 OK ,以 3 位數(shù)字和原因短語(yǔ)組成。數(shù)字中的第一位指定了響應(yīng)類(lèi)別,后兩位無(wú)分類(lèi)。
          • 不少返回的響應(yīng)狀態(tài)碼都是錯(cuò)誤的,但是用戶(hù)可能察覺(jué)不到這點(diǎn)。比如 Web 應(yīng)用程序內(nèi)部發(fā)生錯(cuò)誤,狀態(tài)碼依然返回 200 OK。

          2. 狀態(tài)碼類(lèi)別

          我們可以自行改變 RFC2616 中定義的狀態(tài)碼或者服務(wù)器端自行創(chuàng)建狀態(tài)碼,只要遵守狀態(tài)碼的類(lèi)別定義就可以了。

          3. 常用狀態(tài)碼解析

          HTTP 狀態(tài)碼種類(lèi)繁多,數(shù)量達(dá)幾十種。其中最常用的有以下 14 種,一起來(lái)看看。

          3.1 200 OK

          表示從客戶(hù)端發(fā)來(lái)的請(qǐng)求在服務(wù)器端被正常處理了。

          3.2 204 No Content

          • 代表服務(wù)器接收的請(qǐng)求已成功處理,但在返回的響應(yīng)報(bào)文中不含實(shí)體的主體部分。另外,也不允許返回任何實(shí)體的主體。
          • 一般在只需要從客戶(hù)端向服務(wù)器端發(fā)送消息,而服務(wù)器端不需要向客戶(hù)端發(fā)送新消息內(nèi)容的情況下使用。

          3.3 206 Partial Content

          表示客戶(hù)端進(jìn)行了范圍請(qǐng)求,而服務(wù)器成功執(zhí)行了這部分的 GET 請(qǐng)求。響應(yīng)報(bào)文中包含由 Content-Range 首部字段指定范圍的實(shí)體內(nèi)容。

          3.4 301 Moved Permanently

          永久性重定向。表示請(qǐng)求的資源已被分配了新的 URI。以后應(yīng)使用資源現(xiàn)在所指的 URI。也就是說(shuō),如果已經(jīng)把資源對(duì)應(yīng)的 URI 保存為書(shū)簽了,這時(shí)應(yīng)該按 Location 首部字段提示的 URI 重新保存。

          3.5 302 Found

          • 臨時(shí)性重定向。表示請(qǐng)求的資源已被分配了新的 URI,希望用戶(hù)(本次)能使用新的 URI 訪(fǎng)問(wèn)。
          • 和 301 Moved Permanently 狀態(tài)碼相似,但 302 Found 狀態(tài)碼代表資源不是被永久移動(dòng),只是臨時(shí)性質(zhì)的。換句話(huà)說(shuō),已移動(dòng)的資源對(duì)應(yīng)的 URI 將來(lái)還有可能發(fā)生改變。

          3.6 303 See Other

          • 表示由于請(qǐng)求的資源存在著另一個(gè) URI,應(yīng)使用 GET 方法定向獲取請(qǐng)求的資源。
          • 303 See Other 和 302 Found 狀態(tài)碼有著相同的功能,但 303 See Other 狀態(tài)碼明確表示客戶(hù)端應(yīng)采用 GET 方法獲取資源,這點(diǎn)與 302 Found 狀態(tài)碼有區(qū)別。

          3.7 304 Not Modified

          • 表示客戶(hù)端發(fā)送附帶條件的請(qǐng)求時(shí),服務(wù)器端允許請(qǐng)求訪(fǎng)問(wèn)的資源,但未滿(mǎn)足條件的情況。
          • 304 Not Modified 狀態(tài)碼返回時(shí),不包含任何響應(yīng)的主體部分。
          • 304 Not Modified 雖然被劃分到 3xx 類(lèi)別中,但和重定向沒(méi)有關(guān)系。

          3.8 307 Temporary Redirect

          臨時(shí)重定向。該狀態(tài)碼與 302 Found 有著相同的含義。

          3.9 400 Bad Request

          • 表示請(qǐng)求報(bào)文中存在語(yǔ)法錯(cuò)誤。當(dāng)錯(cuò)誤發(fā)生時(shí),需修改請(qǐng)求的內(nèi)容后再次發(fā)送請(qǐng)求。
          • 另外,瀏覽器會(huì)像 200 OK 一樣對(duì)待該狀態(tài)碼。

          3.10 401 Unauthorized

          • 表示發(fā)送的請(qǐng)求需要有通過(guò) HTTP 認(rèn)證(BASIC 認(rèn)證、DIGEST 認(rèn)證)的認(rèn)證信息。
          • 另外,若之前已進(jìn)行過(guò) 1 次請(qǐng)求,則表示用戶(hù)認(rèn)證失敗。
          • 返回含有 401 Unauthorized 的響應(yīng)必須包含一個(gè)適用于被請(qǐng)求資源的 WWW-Authenticate 首部用以質(zhì)詢(xún)(challenge)用戶(hù)信息。

          3.11 403 Forbidden

          表明對(duì)請(qǐng)求資源的訪(fǎng)問(wèn)被服務(wù)器拒絕了。服務(wù)器端沒(méi)有必要給出詳細(xì)的拒絕理由,當(dāng)然也可以在響應(yīng)報(bào)文的實(shí)體主體部分對(duì)原因進(jìn)行描述。

          3.12 404 Not Found

          表明服務(wù)器上無(wú)法找到請(qǐng)求的資源。除此之外,也可以在服務(wù)器端拒絕請(qǐng)求且不想說(shuō)明理由的時(shí)候使用。

          3.13 500 Internal Server Error

          表明服務(wù)器端在執(zhí)行請(qǐng)求時(shí)發(fā)生了錯(cuò)誤。也可能是 Web 應(yīng)用存在的 bug 或某些臨時(shí)的故障。

          3.14 503 Service Unavailable

          表明服務(wù)器暫時(shí)處于超負(fù)載或正在進(jìn)行停機(jī)維護(hù),現(xiàn)在無(wú)法處理請(qǐng)求。如果事先得知解除以上狀況需要的時(shí)間,最好寫(xiě)入 Retry-After 首部字段再返回給客戶(hù)端。

          八、HTTP 報(bào)文實(shí)體

          1. HTTP 報(bào)文實(shí)體概述

          HTTP 報(bào)文結(jié)構(gòu)

          大家請(qǐng)仔細(xì)看看上面示例中,各個(gè)組成部分對(duì)應(yīng)的內(nèi)容。

          接著,我們來(lái)看看報(bào)文和實(shí)體的概念。如果把 HTTP 報(bào)文想象成因特網(wǎng)貨運(yùn)系統(tǒng)中的箱子,那么 HTTP 實(shí)體就是報(bào)文中實(shí)際的貨物。

          • 報(bào)文:是網(wǎng)絡(luò)中交換和傳輸?shù)臄?shù)據(jù)單元,即站點(diǎn)一次性要發(fā)送的數(shù)據(jù)塊。報(bào)文包含了將要發(fā)送的完整的數(shù)據(jù)信息,其長(zhǎng)短很不一致,長(zhǎng)度不限且可變。
          • 實(shí)體:作為請(qǐng)求或響應(yīng)的有效載荷數(shù)據(jù)(補(bǔ)充項(xiàng))被傳輸,其內(nèi)容由實(shí)體首部和實(shí)體主體組成。(實(shí)體首部相關(guān)內(nèi)容在上面第六點(diǎn)中已有闡述。)

          我們可以看到,上面示例右圖中深紅色框的內(nèi)容就是報(bào)文的實(shí)體部分,而藍(lán)色框的兩部分內(nèi)容分別就是實(shí)體首部和實(shí)體主體。而左圖中粉紅框內(nèi)容就是報(bào)文主體。

          通常,報(bào)文主體等于實(shí)體主體。只有當(dāng)傳輸中進(jìn)行編碼操作時(shí),實(shí)體主體的內(nèi)容發(fā)生變化,才導(dǎo)致它和報(bào)文主體產(chǎn)生差異。

          2. 內(nèi)容編碼

          • HTTP 應(yīng)用程序有時(shí)在發(fā)送之前需要對(duì)內(nèi)容進(jìn)行編碼。例如,在把很大的 HTML 文檔發(fā)送給通過(guò)慢速連接上來(lái)的客戶(hù)端之前,服務(wù)器可能會(huì)對(duì)其進(jìn)行壓縮,這樣有助于減少傳輸實(shí)體的時(shí)間。服務(wù)器還可以把內(nèi)容攪亂或加密,以此來(lái)防止未授權(quán)的第三方看到文檔的內(nèi)容。
          • 這種類(lèi)型的編碼是在發(fā)送方應(yīng)用到內(nèi)容之上的。當(dāng)內(nèi)容經(jīng)過(guò)內(nèi)容編碼后,編好碼的數(shù)據(jù)就放在實(shí)體主體中,像往常一樣發(fā)送給接收方。

          內(nèi)容編碼類(lèi)型:

          3. 傳輸編碼

          內(nèi)容編碼是對(duì)報(bào)文的主體進(jìn)行的可逆變換,是和內(nèi)容的具體格式細(xì)節(jié)緊密相關(guān)的。

          傳輸編碼也是作用在實(shí)體主體上的可逆變換,但使用它們是由于架構(gòu)方面的原因,同內(nèi)容的格式無(wú)關(guān)。使用傳輸編碼是為了改變報(bào)文中的數(shù)據(jù)在網(wǎng)絡(luò)上傳輸?shù)姆绞健?/p>

          內(nèi)容編碼和傳輸編碼的對(duì)比

          4. 分塊編碼

          分塊編碼把報(bào)文分割成若干已知大小的塊。塊之間是緊挨著發(fā)送的,這樣就不需要在發(fā)送之前知道整個(gè)報(bào)文的大小了。分塊編碼是一種傳輸編碼,是報(bào)文的屬性。

          分塊編碼與持久連接

          若客戶(hù)端與服務(wù)器端之間不是持久連接,客戶(hù)端就不需要知道它在讀取的主體的長(zhǎng)度,而只需要讀取到服務(wù)器關(guān)閉主體連接為止。

          當(dāng)使用持久連接時(shí),在服務(wù)器寫(xiě)主體之前,必須知道它的大小并在 Content-Length 首部中發(fā)送。如果服務(wù)器動(dòng)態(tài)創(chuàng)建內(nèi)容,就可能在發(fā)送之前無(wú)法知道主體的長(zhǎng)度。

          分塊編碼為這種困難提供了解決方案,只要允許服務(wù)器把主體分塊發(fā)送,說(shuō)明每塊的大小就可以了。因?yàn)橹黧w是動(dòng)態(tài)創(chuàng)建的,服務(wù)器可以緩沖它的一部分,發(fā)送其大小和相應(yīng)的塊,然后在主體發(fā)送完之前重復(fù)這個(gè)過(guò)程。服務(wù)器可以用大小為 0 的塊作為主體結(jié)束的信號(hào),這樣就可以繼續(xù)保持連接,為下一個(gè)響應(yīng)做準(zhǔn)備。

          來(lái)看看一個(gè)分塊編碼的報(bào)文示例:

          分塊編碼的報(bào)文

          5.多部分媒體類(lèi)型

          MIME 中的 multipart(多部分)電子郵件報(bào)文中包含多個(gè)報(bào)文,它們合在一起作為單一的復(fù)雜報(bào)文發(fā)送。每一部分都是獨(dú)立的,有各自的描述其內(nèi)容的集,不同部分之間用分界字符串連接在一起。

          相應(yīng)得,HTTP 協(xié)議中也采納了多部分對(duì)象集合,發(fā)送的一份報(bào)文主體內(nèi)可包含多種類(lèi)型實(shí)體。

          多部分對(duì)象集合包含的對(duì)象如下:

          • multipart/form-data:在 Web 表單文件上傳時(shí)使用。
          • multipart/byteranges:狀態(tài)碼 206 Partial Content 響應(yīng)報(bào)文包含了多個(gè)范圍的內(nèi)容時(shí)使用。

          6. 范圍請(qǐng)求

          假設(shè)你正在下載一個(gè)很大的文件,已經(jīng)下了四分之三,忽然網(wǎng)絡(luò)中斷了,那下載就必須重頭再來(lái)一遍。為了解決這個(gè)問(wèn)題,需要一種可恢復(fù)的機(jī)制,即能從之前下載中斷處恢復(fù)下載。要實(shí)現(xiàn)該功能,這就要用到范圍請(qǐng)求。

          有了范圍請(qǐng)求, HTTP 客戶(hù)端可以通過(guò)請(qǐng)求曾獲取失敗的實(shí)體的一個(gè)范圍(或者說(shuō)一部分),來(lái)恢復(fù)下載該實(shí)體。當(dāng)然這有一個(gè)前提,那就是從客戶(hù)端上一次請(qǐng)求該實(shí)體到這一次發(fā)出范圍請(qǐng)求的時(shí)間段內(nèi),該對(duì)象沒(méi)有改變過(guò)。例如:

          GET /bigfile.html HTTP/1.1
          Host: www.sample.com
          Range: bytes=20224-
          ···
          

          實(shí)體范圍請(qǐng)求示例

          上面示例中,客戶(hù)端請(qǐng)求的是文檔開(kāi)頭20224字節(jié)之后的部分。

          九、與 HTTP 協(xié)作的 Web 服務(wù)器

          HTTP 通信時(shí),除客戶(hù)端和服務(wù)器外,還有一些用于協(xié)助通信的應(yīng)用程序。如下列出比較重要的幾個(gè):代理、緩存、網(wǎng)關(guān)、隧道、Agent 代理

          1.代理

          代理

          HTTP 代理服務(wù)器是 Web 安全、應(yīng)用集成以及性能優(yōu)化的重要組成模塊。代理位于客戶(hù)端和服務(wù)器端之間,接收客戶(hù)端所有的 HTTP 請(qǐng)求,并將這些請(qǐng)求轉(zhuǎn)發(fā)給服務(wù)器(可能會(huì)對(duì)請(qǐng)求進(jìn)行修改之后再進(jìn)行轉(zhuǎn)發(fā))。對(duì)用戶(hù)來(lái)說(shuō),這些應(yīng)用程序就是一個(gè)代理,代表用戶(hù)訪(fǎng)問(wèn)服務(wù)器。

          出于安全考慮,通常會(huì)將代理作為轉(zhuǎn)發(fā)所有 Web 流量的可信任中間節(jié)點(diǎn)使用。代理還可以對(duì)請(qǐng)求和響應(yīng)進(jìn)行過(guò)濾,安全上網(wǎng)或綠色上網(wǎng)。

          2. 緩存

          瀏覽器第一次請(qǐng)求:

          瀏覽器第一次請(qǐng)求

          瀏覽器再次請(qǐng)求:

          瀏覽器再次請(qǐng)求

          Web 緩存或代理緩存是一種特殊的 HTTP 代理服務(wù)器,可以將經(jīng)過(guò)代理傳輸?shù)某S梦臋n復(fù)制保存起來(lái)。下一個(gè)請(qǐng)求同一文檔的客戶(hù)端就可以享受緩存的私有副本所提供的服務(wù)了。客戶(hù)端從附近的緩存下載文檔會(huì)比從遠(yuǎn)程 Web 服務(wù)器下載快得多。

          3. 網(wǎng)關(guān)

          HTTP / FTP 網(wǎng)關(guān)

          網(wǎng)關(guān)是一種特殊的服務(wù)器,作為其他服務(wù)器的中間實(shí)體使用。通常用于將 HTTP 流量轉(zhuǎn)換成其他的協(xié)議。網(wǎng)關(guān)接收請(qǐng)求時(shí)就好像自己是資源的源服務(wù)器一樣。客戶(hù)端可能并不知道自己正在跟一個(gè)網(wǎng)關(guān)進(jìn)行通信。

          4. 隧道

          HTTP/SSL 隧道

          隧道是會(huì)在建立起來(lái)之后,就會(huì)在兩條連接之間對(duì)原始數(shù)據(jù)進(jìn)行盲轉(zhuǎn)發(fā)的 HTTP 應(yīng)用程序。HTTP 隧道通常用來(lái)在一條或多條 HTTP 連接上轉(zhuǎn)發(fā)非 HTTP 數(shù)據(jù),轉(zhuǎn)發(fā)時(shí)不會(huì)窺探數(shù)據(jù)。

          HTTP 隧道的一種常見(jiàn)用途就是通過(guò) HTTP 連接承載加密的安全套接字層(SSL)流量,這樣 SSL 流量就可以穿過(guò)只允許 Web 流量通過(guò)的防火墻了。

          5. Agent 代理

          自動(dòng)搜索引擎“網(wǎng)絡(luò)蜘蛛”

          Agent 代理是代表用戶(hù)發(fā)起 HTTP 請(qǐng)求的客戶(hù)端應(yīng)用程序。所有發(fā)布 Web 請(qǐng)求的應(yīng)用程序都是 HTTP Agent 代理。

          來(lái)源:簡(jiǎn)書(shū) 鏈接:https://www.jianshu.com/p/6e9e4156ece3

          今日內(nèi)容:

          1. Servlet

          2. HTTP協(xié)議

          3. Request


          一、Servlet補(bǔ)充內(nèi)容:

          1.1 Servlet的體系結(jié)構(gòu):

          Servlet -- 接口

          |

          GenericServlet -- 抽象類(lèi)

          |

          HttpServlet -- 抽象類(lèi)


          1.2 GenericServlet:將Servlet接口中其他的方法做了默認(rèn)空實(shí)現(xiàn),只將service()方法作為抽象,將來(lái)定義Servlet類(lèi)時(shí),可以繼承GenericServlet,實(shí)現(xiàn)service()方法即可


          1.3 HttpServlet:對(duì)http協(xié)議的一種封裝,簡(jiǎn)化操作

          1. 定義類(lèi)繼承HttpServlet

          2. 復(fù)寫(xiě)doGet/doPost方法

          1.2 Servlet相關(guān)配置

          1.2.1 urlpartten:Servlet訪(fǎng)問(wèn)路徑

          1. 一個(gè)Servlet可以定義多個(gè)訪(fǎng)問(wèn)路徑 : @WebServlet({"/d4","/dd4","/ddd4"})

          2. 路徑定義規(guī)則:

          1. /xxx:路徑匹配

          2. /xxx/xxx:多層路徑,目錄結(jié)構(gòu)

          3. *.do:擴(kuò)展名匹配


          二、HTTP:

          2.1 概念:Hyper Text Transfer Protocol 超文本傳輸協(xié)議

          * 傳輸協(xié)議:定義了,客戶(hù)端和服務(wù)器端通信時(shí),發(fā)送數(shù)據(jù)的格式

          * 特點(diǎn):

          1. 基于TCP/IP的高級(jí)協(xié)議

          2. 默認(rèn)端口號(hào):80

          3. 基于請(qǐng)求/響應(yīng)模型的:一次請(qǐng)求對(duì)應(yīng)一次響應(yīng)

          4. 無(wú)狀態(tài)的:每次請(qǐng)求之間相互獨(dú)立,不能交互數(shù)據(jù)


          * 歷史版本:

          * 1.0:每一次請(qǐng)求響應(yīng)都會(huì)建立新的連接

          * 1.1:復(fù)用連接


          2.2 請(qǐng)求消息數(shù)據(jù)格式

          2.2.1 請(qǐng)求行:

          請(qǐng)求方式 請(qǐng)求url 請(qǐng)求協(xié)議/版本

          GET /login.html HTTP/1.1


          2.2.2 請(qǐng)求方式:

          * HTTP協(xié)議有7中請(qǐng)求方式,常用的有2種

          * GET:

          1. 請(qǐng)求參數(shù)在請(qǐng)求行中,在url后。

          2. 請(qǐng)求的url長(zhǎng)度有限制的

          3. 不太安全

          * POST:

          1. 請(qǐng)求參數(shù)在請(qǐng)求體中

          2. 請(qǐng)求的url長(zhǎng)度沒(méi)有限制的

          3. 相對(duì)安全

          2.2.3 請(qǐng)求頭:客戶(hù)端瀏覽器告訴服務(wù)器一些信息

          請(qǐng)求頭名稱(chēng): 請(qǐng)求頭值

          * 常見(jiàn)的請(qǐng)求頭:

          1. User-Agent:瀏覽器告訴服務(wù)器,我訪(fǎng)問(wèn)你使用的瀏覽器版本信息

          * 可以在服務(wù)器端獲取該頭的信息,解決瀏覽器的兼容性問(wèn)題


          2. Referer:http://localhost/login.html

          * 告訴服務(wù)器,我(當(dāng)前請(qǐng)求)從哪里來(lái)?

          * 作用:

          1. 防盜鏈:

          2. 統(tǒng)計(jì)工作:

          2.2.4 請(qǐng)求空行

          空行,就是用于分割POST請(qǐng)求的請(qǐng)求頭,和請(qǐng)求體的。

          2.2.5 請(qǐng)求體(正文):

          * 封裝POST請(qǐng)求消息的請(qǐng)求參數(shù)的


          2.2.6 請(qǐng)求消息舉例:

          POST /login.html HTTP/1.1

          Host: localhost

          User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0

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

          Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

          Accept-Encoding: gzip, deflate

          Referer: http://localhost/login.html

          Connection: keep-alive

          Upgrade-Insecure-Requests: 1

          username=zhangsan


          三、Request:

          3.1 request對(duì)象和response對(duì)象的原理

          1. request和response對(duì)象是由服務(wù)器創(chuàng)建的。我們來(lái)使用它們

          2. request對(duì)象是來(lái)獲取請(qǐng)求消息,response對(duì)象是來(lái)設(shè)置響應(yīng)消息

          3.2 request對(duì)象繼承體系結(jié)構(gòu):

          ServletRequest -- 接口

          | 繼承

          HttpServletRequest -- 接口

          | 實(shí)現(xiàn)

          org.apache.catalina.connector.RequestFacade 類(lèi)(tomcat)


          3.3 request功能:

          3.3.1 獲取請(qǐng)求消息數(shù)據(jù)

          1. 獲取請(qǐng)求行數(shù)據(jù)

          * GET /day14/demo1?name=zhangsan HTTP/1.1

          * 方法:

          1. 獲取請(qǐng)求方式 :GET

          * String getMethod()

          2. (*)獲取虛擬目錄:/day14

          * String getContextPath()

          3. 獲取Servlet路徑: /demo1

          * String getServletPath()

          4. 獲取get方式請(qǐng)求參數(shù):name=zhangsan

          * String getQueryString()

          5. (*)獲取請(qǐng)求URI:/day14/demo1

          * String getRequestURI(): /day14/demo1

          * StringBuffer getRequestURL() :http://localhost/day14/demo1

          * URL:統(tǒng)一資源定位符 : http://localhost/day14/demo1

          * URI:統(tǒng)一資源標(biāo)識(shí)符 : /day14/demo1

          6. 獲取協(xié)議及版本:HTTP/1.1

          * String getProtocol()

          7. 獲取客戶(hù)機(jī)的IP地址:

          * String getRemoteAddr()

          2. 獲取請(qǐng)求頭數(shù)據(jù)

          * 方法:

          * (*)String getHeader(String name):通過(guò)請(qǐng)求頭的名稱(chēng)獲取請(qǐng)求頭的值

          * Enumeration<String> getHeaderNames():獲取所有的請(qǐng)求頭名稱(chēng)

          3. 獲取請(qǐng)求體數(shù)據(jù):

          * 請(qǐng)求體:只有POST請(qǐng)求方式,才有請(qǐng)求體,

          在請(qǐng)求體中封裝了POST請(qǐng)求的請(qǐng)求參數(shù)

          * 步驟:

          1. 獲取流對(duì)象

          * BufferedReader getReader():獲取字符輸入流,只能操作字符數(shù)據(jù)

          * ServletInputStream getInputStream():獲取字節(jié)輸入流,可以操作所有類(lèi)型數(shù)據(jù)

          2. 再?gòu)牧鲗?duì)象中拿數(shù)據(jù)

          3.3.2 其他功能:獲取請(qǐng)求參數(shù)通用方式:不論get還是post請(qǐng)求方式都可以使用下列方法來(lái)獲取請(qǐng)求參數(shù):

          1. String getParameter(String name):根據(jù)參數(shù)名稱(chēng)獲取值 username=zs

          2. String[] getParameterValues(String name):根據(jù)參數(shù)名稱(chēng)獲取參數(shù)值的數(shù)組 hobby=xx&hobby=game

          3. Enumeration<String> getParameterNames():獲取所有請(qǐng)求的參數(shù)名稱(chēng)

          4. Map<String,String[]> getParameterMap():獲取所有參數(shù)的map集合


          * 中文亂碼問(wèn)題:

          * get方式:tomcat 8 已經(jīng)將get方式亂碼問(wèn)題解決了

          * post方式:會(huì)亂碼

          * 解決:在獲取參數(shù)前,設(shè)置request的編碼為

          request.setCharacterEncoding("utf-8");

          3.3.3 請(qǐng)求轉(zhuǎn)發(fā):一種在服務(wù)器內(nèi)部的資源跳轉(zhuǎn)方式

          1. 步驟:

          1. 通過(guò)request對(duì)象獲取請(qǐng)求轉(zhuǎn)發(fā)器對(duì)象:

          RequestDispatcher getRequestDispatcher(String path)

          2. 使用RequestDispatcher對(duì)象來(lái)進(jìn)行轉(zhuǎn)發(fā):

          forward(ServletRequest request, ServletResponse response)


          2. 特點(diǎn):

          1. 瀏覽器地址欄路徑不發(fā)生變化

          2. 只能轉(zhuǎn)發(fā)到當(dāng)前服務(wù)器內(nèi)部資源中。

          3. 轉(zhuǎn)發(fā)是一次請(qǐng)求


          3.3.4. 共享數(shù)據(jù):

          * 域?qū)ο螅阂粋€(gè)有作用范圍的對(duì)象,可以在范圍內(nèi)共享數(shù)據(jù)

          * request域:代表一次請(qǐng)求的范圍,一般用于請(qǐng)求轉(zhuǎn)發(fā)的多個(gè)資源中共享數(shù)據(jù)

          * 方法:

          1. void setAttribute(String name,Object obj):存儲(chǔ)數(shù)據(jù)

          2. Object getAttitude(String name):通過(guò)鍵獲取值

          3. void removeAttribute(String name):通過(guò)鍵移除鍵值對(duì)


          3.3.5. 獲取ServletContext:

          * ServletContext getServletContext()


          四、案例:用戶(hù)登錄

          * 用戶(hù)登錄案例需求:

          1.編寫(xiě)login.html登錄頁(yè)面

          username & password 兩個(gè)輸入框

          2.使用Druid數(shù)據(jù)庫(kù)連接池技術(shù),操作mysql,day14數(shù)據(jù)庫(kù)中user表

          3.使用JdbcTemplate技術(shù)封裝JDBC

          4.登錄成功跳轉(zhuǎn)到SuccessServlet展示:登錄成功!用戶(hù)名,歡迎您

          5.登錄失敗跳轉(zhuǎn)到FailServlet展示:登錄失敗,用戶(hù)名或密碼錯(cuò)誤



          * 分析


          * 開(kāi)發(fā)步驟

          1. 創(chuàng)建項(xiàng)目,導(dǎo)入html頁(yè)面,配置文件,jar包

          2. 創(chuàng)建數(shù)據(jù)庫(kù)環(huán)境

          CREATE DATABASE day14;

          USE day14;

          CREATE TABLE USER(

          id INT PRIMARY KEY AUTO_INCREMENT,

          username VARCHAR(32) UNIQUE NOT NULL,

          PASSWORD VARCHAR(32) NOT NULL

          );


          3. 創(chuàng)建包c(diǎn)n.itcast.domain,創(chuàng)建類(lèi)User

          package cn.itcast.domain;

          /**

          * 用戶(hù)的實(shí)體類(lèi)

          */

          public class User {

          private int id;

          private String username;

          private String password;

          public int getId() {

          return id;

          }

          public void setId(int id) {

          this.id=id;

          }

          public String getUsername() {

          return username;

          }

          public void setUsername(String username) {

          this.username=username;

          }

          public String getPassword() {

          return password;

          }

          public void setPassword(String password) {

          this.password=password;

          }

          @Override

          public String toString() {

          return "User{" +

          "id=" + id +

          ", username='" + username + '\'' +

          ", password='" + password + '\'' +

          '}';

          }

          }

          4. 創(chuàng)建包c(diǎn)n.itcast.util,編寫(xiě)工具類(lèi)JDBCUtils

          package cn.itcast.util;


          import com.alibaba.druid.pool.DruidDataSourceFactory;

          import javax.sql.DataSource;

          import javax.xml.crypto.Data;

          import java.io.IOException;

          import java.io.InputStream;

          import java.sql.Connection;

          import java.sql.SQLException;

          import java.util.Properties;

          /**

          * JDBC工具類(lèi) 使用Durid連接池

          */

          public class JDBCUtils {

          private static DataSource ds ;

          static {

          try {

          //1.加載配置文件

          Properties pro=new Properties();

          //使用ClassLoader加載配置文件,獲取字節(jié)輸入流

          InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");

          pro.load(is);

          //2.初始化連接池對(duì)象

          ds=DruidDataSourceFactory.createDataSource(pro);

          } catch (IOException e) {

          e.printStackTrace();

          } catch (Exception e) {

          e.printStackTrace();

          }

          }

          /**

          * 獲取連接池對(duì)象

          */

          public static DataSource getDataSource(){

          return ds;

          }

          /**

          * 獲取連接Connection對(duì)象

          */

          public static Connection getConnection() throws SQLException {

          return ds.getConnection();

          }

          }

          5. 創(chuàng)建包c(diǎn)n.itcast.dao,創(chuàng)建類(lèi)UserDao,提供login方法

          package cn.itcast.dao;


          import cn.itcast.domain.User;

          import cn.itcast.util.JDBCUtils;

          import org.springframework.dao.DataAccessException;

          import org.springframework.jdbc.core.BeanPropertyRowMapper;

          import org.springframework.jdbc.core.JdbcTemplate;

          /**

          * 操作數(shù)據(jù)庫(kù)中User表的類(lèi)

          */

          public class UserDao {

          //聲明JDBCTemplate對(duì)象共用

          private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());

          /**

          * 登錄方法

          * @param loginUser 只有用戶(hù)名和密碼

          * @return user包含用戶(hù)全部數(shù)據(jù),沒(méi)有查詢(xún)到,返回null

          */

          public User login(User loginUser){

          try {

          //1.編寫(xiě)sql

          String sql="select * from user where username=? and password=?";

          //2.調(diào)用query方法

          User user=template.queryForObject(sql,

          new BeanPropertyRowMapper<User>(User.class),

          loginUser.getUsername(), loginUser.getPassword());

          return user;

          } catch (DataAccessException e) {

          e.printStackTrace();//記錄日志

          return null;

          }

          }

          }

          6. 編寫(xiě)cn.itcast.web.servlet.LoginServlet類(lèi)

          package cn.itcast.web.servlet;


          import cn.itcast.dao.UserDao;

          import cn.itcast.domain.User;

          import javax.servlet.ServletException;

          import javax.servlet.annotation.WebServlet;

          import javax.servlet.http.HttpServlet;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import java.io.IOException;

          @WebServlet("/loginServlet")

          public class LoginServlet extends HttpServlet {

          @Override

          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

          //1.設(shè)置編碼

          req.setCharacterEncoding("utf-8");

          //2.獲取請(qǐng)求參數(shù)

          String username=req.getParameter("username");

          String password=req.getParameter("password");

          //3.封裝user對(duì)象

          User loginUser=new User();

          loginUser.setUsername(username);

          loginUser.setPassword(password);

          //4.調(diào)用UserDao的login方法

          UserDao dao=new UserDao();

          User user=dao.login(loginUser);

          //5.判斷user

          if(user==null){

          //登錄失敗

          req.getRequestDispatcher("/failServlet").forward(req,resp);

          }else{

          //登錄成功

          //存儲(chǔ)數(shù)據(jù)

          req.setAttribute("user",user);

          //轉(zhuǎn)發(fā)

          req.getRequestDispatcher("/successServlet").forward(req,resp);

          }

          }

          @Override

          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

          this.doGet(req,resp);

          }

          }


          7. 編寫(xiě)FailServlet和SuccessServlet類(lèi)

          @WebServlet("/successServlet")

          public class SuccessServlet extends HttpServlet {

          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

          //獲取request域中共享的user對(duì)象

          User user=(User) request.getAttribute("user");

          if(user !=null){

          //給頁(yè)面寫(xiě)一句話(huà)

          //設(shè)置編碼

          response.setContentType("text/html;charset=utf-8");

          //輸出

          response.getWriter().write("登錄成功!"+user.getUsername()+",歡迎您");

          }

          }



          @WebServlet("/failServlet")

          public class FailServlet extends HttpServlet {

          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

          //給頁(yè)面寫(xiě)一句話(huà)

          //設(shè)置編碼

          response.setContentType("text/html;charset=utf-8");

          //輸出

          response.getWriter().write("登錄失敗,用戶(hù)名或密碼錯(cuò)誤");

          }

          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

          this.doPost(request,response);

          }

          }




          8. login.html中form表單的action路徑的寫(xiě)法

          * 虛擬目錄+Servlet的資源路徑


          9. BeanUtils工具類(lèi),簡(jiǎn)化數(shù)據(jù)封裝

          * 用于封裝JavaBean的

          1. JavaBean:標(biāo)準(zhǔn)的Java類(lèi)

          1. 要求:

          1. 類(lèi)必須被public修飾

          2. 必須提供空參的構(gòu)造器

          3. 成員變量必須使用private修飾

          4. 提供公共setter和getter方法

          2. 功能:封裝數(shù)據(jù)



          2. 概念:

          成員變量:

          屬性:setter和getter方法截取后的產(chǎn)物

          例如:getUsername() --> Username--> username



          3. 方法:

          1. setProperty()

          2. getProperty()

          3. populate(Object obj , Map map):將map集合的鍵值對(duì)信息,封裝到對(duì)應(yīng)的JavaBean對(duì)象中

          文共2678字,預(yù)計(jì)學(xué)習(xí)時(shí)長(zhǎng)15分鐘


          圖源:unsplash


          使用JavaScript時(shí),總會(huì)有各種需要發(fā)出調(diào)用請(qǐng)求的情況,進(jìn)行ajax調(diào)用什么技術(shù)更適合呢?


          最初,盡管有一些方法可以在不刷新頁(yè)面的情況下從服務(wù)器提取數(shù)據(jù),但它們通常依賴(lài)于笨拙的技術(shù)。直到微軟為Outlook電子郵件客戶(hù)端的替代瀏覽器開(kāi)發(fā)了XMLHttpRequest。它在2006年成為了Web標(biāo)準(zhǔn)。


          2015年,F(xiàn)etch API隨ES6引入。通用的Request和Response接口提供了一致性,而Promises允許更容易的鏈接和沒(méi)有回調(diào)的異步/等待。Fetch簡(jiǎn)潔,優(yōu)雅且易于理解,但是還有其他不錯(cuò)的選擇,本文將簡(jiǎn)要的含義、語(yǔ)法以及利弊。


          以下代碼展示了使用不同替代方法的基本HTTP GET和POST示例。現(xiàn)在開(kāi)始吧~

          XMLHttpRequest


          XMLHttpRequest對(duì)象可用于從Web服務(wù)器請(qǐng)求數(shù)據(jù)。它是這次比較中最早的方法,盡管其他選擇都優(yōu)于它,但由于其向后兼容性和成熟度,它仍然有效且有用。


          得到:


          var req=new XMLHttpRequest();//The onreadystatechange property
          //specifies a function to be
          //executed every time the status
          //of the XMLHttpRequest changes
          req.onreadystatechange=function() {
              if (this.readyState==4 &&this.status==200) {
                 //The responseText property
                 //returns a text string          
                 console.log(xhttp.responseText)
                 //Do some stuff
              }
          };req.open("GET", "http://dataserver/users", true);
          req.send();


          發(fā)送:


          varformData=new FormData();
          formData.append("name", "Murdock");
          var req=new XMLHttpRequest();
          req.open("POST", "http://dataserver/update");
          req.send(formData);


          優(yōu)點(diǎn):


          · 不需要從外部源加載

          · 向后兼容性

          · 成熟/穩(wěn)定

          · 在所有瀏覽器中均可使用

          · 是原生瀏覽器API


          缺點(diǎn):


          · 支持回調(diào)地獄

          · 笨拙冗長(zhǎng)的語(yǔ)法

          · Fetch能自然地替代它


          圖源:unsplash


          Qwest


          Qwest是一個(gè)基于Promise的簡(jiǎn)單ajax庫(kù),它支持XmlHttpRequest2的獨(dú)立數(shù)據(jù),例如ArrayBuffer,Blob和FormData。


          得到:


          qwest.get('http://dataserver/data.json')
               .then(function(xhr, response) {
                  // ...do some stuff whith data
               });


          發(fā)送:


          qwest.post('http://dataserver/update',{
                  firstname: 'Murdock',      
                  age: 30
               })
               .then(function(xhr, response) {
                  // Make some useful actions
               })
               .catch(function(e, xhr, response) {
                  // Process the error
               });


          優(yōu)點(diǎn):


          · 可以建立請(qǐng)求限制

          · 基于Promise


          缺點(diǎn):


          · 并非所有瀏覽器上都可使用XmlHttpRequest2

          · 非原生

          · 必須從外部源加載


          JQuery.ajax


          該庫(kù)在不久前被廣泛用于發(fā)出HTTP異步請(qǐng)求。jQuery的所有Ajax方法都返回XMLHTTPRequest對(duì)象的超集


          得到:

          $.ajax({
              url: 'http://dataserver/data.json'
            }).done(function(data) {
              // ...do some stuff whith data
            }).fail(function() {
              // Handle error
          });


          發(fā)送:


          $.ajax({
            type: "POST",
            url: 'http://dataserver/update',
            data: data,
            success: successCallBack,
            error: errorCallBack,
            dataType: dataType
          });


          優(yōu)點(diǎn):


          · 良好的支持和文檔

          · 可配置的對(duì)象

          · 在許多項(xiàng)目中使用

          · 學(xué)習(xí)曲線(xiàn)低

          · 它返回XMLHttpRequest對(duì)象,因此可以中止請(qǐng)求


          缺點(diǎn):


          · 非原生

          · 必須從外部源加載

          · 沒(méi)有與Promises結(jié)合

          · 對(duì)于原生ES6 Fetch不是必需的。


          Axios


          圖源:unsplash


          基于Promise的HTTP庫(kù),用于在瀏覽器和Nodejs上執(zhí)行HTTP請(qǐng)求。


          得到:


          axios({
            url: 'http://dataserver/data.json',
            method: 'get'
          })


          發(fā)送:


          axios.post('http://dataserver/update',{
              name: 'Murdock'
            })
            .then(function (response) {
              console.log(response);
            })
            .catch(function (error) {
              console.log(error);
            });


          優(yōu)點(diǎn):


          · 使用promise避免回調(diào)地獄

          · 在瀏覽器和Nodejs上均可使用

          · 支持上傳進(jìn)度

          · 可以設(shè)置響應(yīng)超時(shí)

          · 通過(guò)簡(jiǎn)單地向其傳遞配置對(duì)象即可配置請(qǐng)求

          · Axios已實(shí)現(xiàn)可撤銷(xiāo)的promise提議

          · 自動(dòng)將數(shù)據(jù)轉(zhuǎn)換為JSON


          缺點(diǎn):


          · 非原生

          · 必須從外部源加載


          SuperAgent


          SuperAgent是ajax API,旨在提供靈活性,可讀性和較低的學(xué)習(xí)曲線(xiàn)。它也可以與Node.js一起使用。


          得到:

          request('GET','http://dataserver/data.json').then(
          success, failure);


          .query()方法接受對(duì)象,這些對(duì)象與GET方法一起使用時(shí)將形成查詢(xún)字符串。以下代碼將產(chǎn)生路徑/ dataserver / search?name=Manny&lastName=Peck&order=desc。


          request
             .get('/dataserver/search')
             .query({ name: 'Templeton' })
             .query({ lastname: 'Peck' })
             .query({ order: 'desc' })
             .then(res=> {console.dir(res)}
          });


          發(fā)送:


          request
             .post('http://dataserver/update')
             .send({ name: 'Murdock' })
             .set('Accept', 'application/json')
             .then(res=> {
                console.log('result' +JSON.stringify(res.body));
             });


          優(yōu)點(diǎn):


          · 基于Promise

          · 在Node.js和瀏覽器中均可使用

          · 可以調(diào)用request.abort()方法中止請(qǐng)求

          · 社區(qū)的知名庫(kù)

          · 發(fā)出HTTP請(qǐng)求的無(wú)縫接口

          · 出現(xiàn)故障時(shí)支持重試請(qǐng)求


          缺點(diǎn):


          · 它不支持以XMLHttpRequest的形式監(jiān)視加載進(jìn)度

          · 非原生

          · 必須從外部源加載


          圖源:unsplash


          Http-client


          Http-client允許使用JavaScript的訪(fǎng)存API組成HTTP客戶(hù)端。


          得到:

          //usingES6 modules
          import { createFetch, base, accept, parse } from 'http-client'const fetch=createFetch(
           base('http://dataserver/data.json'), 
            accept('application/json'),    
            parse('json')                     
          )fetch('http://dataserver/data.json').then(response=> {
            console.log(response.jsonData)
          })


          發(fā)送:


          //usingES6 modules
          import { createFetch, method, params } from 'http-client'const fetch=createFetch(
            params({ name: 'Murdock' }),
            base('http://dataserver/update')
          )


          優(yōu)點(diǎn):


          · 在Node.js和瀏覽器中均可使用

          · 由服務(wù)器端工作人員使用

          · 基于Promise

          · 提供頭部保護(hù)裝置,以提高CORS的安全性


          缺點(diǎn):


          · 必須從外部源加載

          · 非原生

          Fetch


          Fetch是原生瀏覽器API,用于發(fā)出替代XMLHttpRequest的請(qǐng)求。與XMLHttpRequest相比,F(xiàn)etch使網(wǎng)絡(luò)請(qǐng)求更容易。Fetch API使用Promises避免XMLHttpRequest回調(diào)地獄。


          得到:


          //WithES6 fetch
          fetch('http://dataserver/data.json')
            .then(data=> {
              // ...do some stuff whith data
            }).catch(error=> {
              // Handle error
          });


          發(fā)送:


          fetch('http://dataserver/update',{
            method: 'post',
            headers: {
              'Accept': 'application/json,text/plain, */*',
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({name: 'Murdock'})
          }).then(res=>res.json())
            .then(res=> console.log(res));//ORwith ES2017 for example(async ()=> {
           
            const response=awaitfetch('http://dataserver/update', {
              method: 'POST',
              headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
              },
              body:JSON.stringify({name='Murdock'})
            });const result=awaitresponse.json();console.log(result);
          })();


          優(yōu)點(diǎn):


          · 是原生瀏覽器API

          · Fetch基本上是經(jīng)過(guò)完善的XMLHttpRequest

          · 友好且易于學(xué)習(xí)

          · 與大多數(shù)最近使用的瀏覽器兼容

          · 是原生XMLHttpRequest對(duì)象的自然替代

          · 學(xué)習(xí)曲線(xiàn)低

          · 不需要從外部源加載它

          · 使用promises避免回調(diào)地獄

          · 不需要更多依賴(lài)項(xiàng)


          缺點(diǎn):


          · 處理JSON數(shù)據(jù)的過(guò)程分為兩步。第一個(gè)是發(fā)出請(qǐng)求,然后第二個(gè)是在響應(yīng)時(shí)調(diào)用.json()方法。對(duì)于Axios,默認(rèn)情況下會(huì)收到JSON響應(yīng)。


          · 從Fetch()返回的Promise僅在網(wǎng)絡(luò)故障或任何阻止請(qǐng)求完成的情況發(fā)生時(shí)拒絕。即使響應(yīng)為HTTP 404或500,也不會(huì)拒絕HTTP錯(cuò)誤狀態(tài)。


          · 缺乏其他庫(kù)的一些有用功能,例如:取消請(qǐng)求。


          · 默認(rèn)情況下,F(xiàn)etch不會(huì)從服務(wù)器發(fā)送或接收Cookie,如果站點(diǎn)依賴(lài)于維持用戶(hù)會(huì)話(huà),則會(huì)導(dǎo)致未經(jīng)身份驗(yàn)證的請(qǐng)求。但是可以通過(guò)添加以下內(nèi)容來(lái)啟用:


          {credentials: “same-origin.”}


          圖源:unsplash


          Fetch是一個(gè)新標(biāo)準(zhǔn),新版本的Chrome和Firefox無(wú)需使用任何其他庫(kù)就可支持它。


          此外,Axios,SuperAgent或其他庫(kù)都有適合的文檔,易于使用,并且學(xué)習(xí)曲線(xiàn)不太高。在某些情況下,它們可以提供Fetch不具有的功能。


          Fetch在JavaScript里是原生的,足以滿(mǎn)足項(xiàng)目需求。如果沒(méi)有特殊需求,我認(rèn)為Fetch就是最合適的選擇。


          留言點(diǎn)贊關(guān)注

          我們一起分享AI學(xué)習(xí)與發(fā)展的干貨

          如轉(zhuǎn)載,請(qǐng)后臺(tái)留言,遵守轉(zhuǎn)載規(guī)范


          主站蜘蛛池模板: 精品女同一区二区| 国产成人一区二区精品非洲| 日本不卡一区二区视频a| 国产剧情国产精品一区| 无码人妻精品一区二区三区99性 | 国产精品无码一区二区三级| 国产午夜精品一区理论片| 亚洲一区中文字幕久久| 加勒比精品久久一区二区三区| 中文无码AV一区二区三区| 亚洲香蕉久久一区二区三区四区| 麻豆AV天堂一区二区香蕉 | 国产精品被窝福利一区| 精品国产a∨无码一区二区三区 | 亚洲视频一区网站| 99久久精品国产免看国产一区| 末成年女A∨片一区二区| 伊人激情AV一区二区三区| 日韩高清一区二区| 久久精品无码一区二区三区免费 | 亚洲午夜日韩高清一区| 精品无码一区二区三区在线| 国产色情一区二区三区在线播放| 国产视频一区在线播放| 国产91大片精品一区在线观看 | 亚洲一区二区电影| 国99精品无码一区二区三区| 日本免费一区二区久久人人澡| 丰满岳乱妇一区二区三区| 无码日韩人妻av一区免费| 亚洲国产精品一区| 一区二区在线视频| 在线观看精品视频一区二区三区| 国产激情无码一区二区| 国产suv精品一区二区33| 亚洲电影国产一区| 无码人妻一区二区三区兔费| 日本在线视频一区二区三区 | 久久一区二区精品| 午夜福利一区二区三区在线观看| 无码人妻AⅤ一区二区三区|