HTTP是一個(gè)client-server協(xié)議:請(qǐng)求通過(guò)一個(gè)實(shí)體被發(fā)出,實(shí)體也就是用戶代理。大多數(shù)情況下,這個(gè)用戶代理都是指瀏覽器,當(dāng)然它也可能是任何東西,比如一個(gè)爬取網(wǎng)頁(yè)生成維護(hù)搜索引擎索引的機(jī)器爬蟲。
每一個(gè)發(fā)送到服務(wù)器的請(qǐng)求,都會(huì)被服務(wù)器處理并返回一個(gè)消息,也就是response。在這個(gè)請(qǐng)求與響應(yīng)之間,還有許許多多的被稱為proxies的實(shí)體,他們的作用與表現(xiàn)各不相同,比如有些是網(wǎng)關(guān),還有些是caches等。

實(shí)際上,在一個(gè)瀏覽器和處理請(qǐng)求的服務(wù)器之間,還有路由器、調(diào)制解調(diào)器等許多計(jì)算機(jī)。由于Web的層次設(shè)計(jì),那些在網(wǎng)絡(luò)層和傳輸層的細(xì)節(jié)都被隱藏起來(lái)了。HTTP位于最上層的應(yīng)用層。雖然底層對(duì)于分析網(wǎng)絡(luò)問題非常重要,但是大多都跟對(duì)HTTP的描述不相干。
客戶端:user-agent
user-agent 就是任何能夠?yàn)橛脩舭l(fā)起行為的工具。這個(gè)角色通常都是由瀏覽器來(lái)扮演。一些例外情況,比如是工程師使用的程序,以及Web開發(fā)人員調(diào)試應(yīng)用程序。
瀏覽器總是作為發(fā)起一個(gè)請(qǐng)求的實(shí)體,他永遠(yuǎn)不是服務(wù)器(雖然近幾年已經(jīng)出現(xiàn)一些機(jī)制能夠模擬由服務(wù)器發(fā)起的請(qǐng)求消息了)。
要展現(xiàn)一個(gè)網(wǎng)頁(yè),瀏覽器首先發(fā)送一個(gè)請(qǐng)求來(lái)獲取頁(yè)面的HTML文檔,再解析文檔中的資源信息發(fā)送其他請(qǐng)求,獲取可執(zhí)行腳本或CSS樣式來(lái)進(jìn)行頁(yè)面布局渲染,以及一些其它頁(yè)面資源(如圖片和視頻等)。然后,瀏覽器將這些資源整合到一起,展現(xiàn)出一個(gè)完整的文檔,也就是網(wǎng)頁(yè)。瀏覽器執(zhí)行的腳本可以在之后的階段獲取更多資源,并相應(yīng)地更新網(wǎng)頁(yè)。
一個(gè)網(wǎng)頁(yè)就是一個(gè)超文本文檔。也就是說(shuō),有一部分顯示的文本可能是鏈接,啟動(dòng)它(通常是鼠標(biāo)的點(diǎn)擊)就可以獲取一個(gè)新的網(wǎng)頁(yè),使得用戶可以控制客戶端進(jìn)行網(wǎng)上沖浪。瀏覽器來(lái)負(fù)責(zé)發(fā)送HTTP請(qǐng)求,并進(jìn)一步解析HTTP返回的消息,以向用戶提供明確的響應(yīng)。
Web服務(wù)端
在上述通信過(guò)程的另一端,是由Web Server來(lái)服務(wù)并提供客戶端所請(qǐng)求的文檔。Server只是虛擬意義上代表一個(gè)機(jī)器:它可以是共享負(fù)載(負(fù)載均衡)的一組服務(wù)器組成的計(jì)算機(jī)集群,也可以是一種復(fù)雜的軟件,通過(guò)向其他計(jì)算機(jī)(如緩存,數(shù)據(jù)庫(kù)服務(wù)器,電子商務(wù)服務(wù)器 ...)發(fā)起請(qǐng)求來(lái)獲取部分或全部資源。
Server 不一定是一臺(tái)機(jī)器,但一個(gè)機(jī)器上可以裝載的眾多Servers。在HTTP/1.1 和Host頭部中,它們甚至可以共享同一個(gè)IP地址。
代理(Proxies)
在瀏覽器和服務(wù)器之間,有許多計(jì)算機(jī)和其他設(shè)備轉(zhuǎn)發(fā)了HTTP消息。由于Web棧層次結(jié)構(gòu)的原因,它們大多都出現(xiàn)在傳輸層、網(wǎng)絡(luò)層和物理層上,對(duì)于HTTP應(yīng)用層而言就是透明的,雖然它們可能會(huì)對(duì)應(yīng)用層性能有重要影響。還有一部分是表現(xiàn)在應(yīng)用層上的,被稱為代理(Proxies)。代理(Proxies)既可以表現(xiàn)得透明,又可以不透明(“改變請(qǐng)求”會(huì)通過(guò)它們)。代理主要有如下幾種作用:
- 緩存(可以是公開的也可以是私有的,像瀏覽器的緩存)
- 過(guò)濾(像反病毒掃描,家長(zhǎng)控制...)
- 負(fù)載均衡(讓多個(gè)服務(wù)器服務(wù)不同的請(qǐng)求)
- 認(rèn)證(對(duì)不同資源進(jìn)行權(quán)限管理)
- 日志記錄(允許存儲(chǔ)歷史信息)
創(chuàng)建Cookie
當(dāng)服務(wù)器收到HTTP請(qǐng)求時(shí),服務(wù)器可以在響應(yīng)頭里面添加一個(gè)Set-Cookie選項(xiàng)。瀏覽器收到響應(yīng)后通常會(huì)保存下Cookie,之后對(duì)該服務(wù)器每一次請(qǐng)求中都通過(guò)Cookie請(qǐng)求頭部將Cookie信息發(fā)送給服務(wù)器。另外,Cookie的過(guò)期時(shí)間、域、路徑、有效期、適用站點(diǎn)都可以根據(jù)需要來(lái)指定。
Set-Cookie響應(yīng)頭部和Cookie請(qǐng)求頭部
服務(wù)器使用Set-Cookie響應(yīng)頭部向用戶代理(一般是瀏覽器)發(fā)送Cookie信息。一個(gè)簡(jiǎn)單的Cookie可能像這樣:
Set-Cookie: <cookie名>=<cookie值>
服務(wù)器通過(guò)該頭部告知客戶端保存Cookie信息。
提示: 如何在以下幾種服務(wù)端程序中設(shè)置 Set-Cookie 響應(yīng)頭信息 :
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[頁(yè)面內(nèi)容]
現(xiàn)在,對(duì)該服務(wù)器發(fā)起的每一次新請(qǐng)求,瀏覽器都會(huì)將之前保存的Cookie信息通過(guò)Cookie請(qǐng)求頭部再發(fā)送給服務(wù)器。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
會(huì)話期Cookie
會(huì)話期Cookie是最簡(jiǎn)單的Cookie:瀏覽器關(guān)閉之后它會(huì)被自動(dòng)刪除,也就是說(shuō)它僅在會(huì)話期內(nèi)有效。會(huì)話期Cookie不需要指定過(guò)期時(shí)間(Expires)或者有效期(Max-Age)。需要注意的是,有些瀏覽器提供了會(huì)話恢復(fù)功能,這種情況下即使關(guān)閉了瀏覽器,會(huì)話期Cookie也會(huì)被保留下來(lái),就好像瀏覽器從來(lái)沒有關(guān)閉一樣。
持久性Cookie
和關(guān)閉瀏覽器便失效的會(huì)話期Cookie不同,持久性Cookie可以指定一個(gè)特定的過(guò)期時(shí)間(Expires)或有效期(Max-Age)。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
提示:當(dāng)Cookie的過(guò)期時(shí)間被設(shè)定時(shí),設(shè)定的日期和時(shí)間只與客戶端相關(guān),而不是服務(wù)端。
Cookie的Secure 和HttpOnly 標(biāo)記
標(biāo)記為 Secure 的Cookie只應(yīng)通過(guò)被HTTPS協(xié)議加密過(guò)的請(qǐng)求發(fā)送給服務(wù)端。但即便設(shè)置了 Secure 標(biāo)記,敏感信息也不應(yīng)該通過(guò)Cookie傳輸,因?yàn)镃ookie有其固有的不安全性,Secure標(biāo)記也無(wú)法提供確實(shí)的安全保障。從 Chrome 52 和 Firefox 52 開始,不安全的站點(diǎn)(http:)無(wú)法使用Cookie的 Secure 標(biāo)記。
為避免跨域腳本 (XSS) 攻擊,通過(guò)JavaScript的 Document.cookie API無(wú)法訪問帶有 HttpOnly 標(biāo)記的Cookie,它們只應(yīng)該發(fā)送給服務(wù)端。如果包含服務(wù)端 Session 信息的 Cookie 不想被客戶端 JavaScript 腳本調(diào)用,那么就應(yīng)該為其設(shè)置 HttpOnly 標(biāo)記。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
Cookie的作用域
Domain 和 Path 標(biāo)識(shí)定義了Cookie的作用域:即Cookie應(yīng)該發(fā)送給哪些URL。
Domain 標(biāo)識(shí)指定了哪些主機(jī)可以接受Cookie。如果不指定,默認(rèn)為當(dāng)前文檔的主機(jī)(不包含子域名)。如果指定了Domain,則一般包含子域名。
例如,如果設(shè)置 Domain=mozilla.org,則Cookie也包含在子域名中(如developer.mozilla.org)。
Path 標(biāo)識(shí)指定了主機(jī)下的哪些路徑可以接受Cookie(該URL路徑必須存在于請(qǐng)求URL中)。以字符 %x2F ("/") 作為路徑分隔符,子路徑也會(huì)被匹配。
例如,設(shè)置 Path=/docs,則以下地址都會(huì)匹配:
/docs/docs/Web//docs/Web/HTTP
SameSite Cookies
SameSite Cookie允許服務(wù)器要求某個(gè)cookie在跨站請(qǐng)求時(shí)不會(huì)被發(fā)送,從而可以阻止跨站請(qǐng)求偽造攻擊(CSRF)。但目前SameSite Cookie還處于實(shí)驗(yàn)階段,并不是所有瀏覽器都支持。
HTTP 定義了一組請(qǐng)求方法, 以表明要對(duì)給定資源執(zhí)行的操作。指示針對(duì)給定資源要執(zhí)行的期望動(dòng)作. 雖然他們也可以是名詞, 但這些請(qǐng)求方法有時(shí)被稱為HTTP動(dòng)詞. 每一個(gè)請(qǐng)求方法都實(shí)現(xiàn)了不同的語(yǔ)義, 但一些共同的特征由一組共享:: 例如一個(gè)請(qǐng)求方法可以是 safe, idempotent, 或 cacheable.
GET方法請(qǐng)求一個(gè)指定資源的表示形式. 使用GET的請(qǐng)求應(yīng)該只被用于獲取數(shù)據(jù).
POST方法用于將實(shí)體提交到指定的資源,通常導(dǎo)致在服務(wù)器上的狀態(tài)變化或副作用.
PUT方法用請(qǐng)求有效載荷替換目標(biāo)資源的所有當(dāng)前表示。
DELETE方法刪除指定的資源。
OPTIONS方法用于描述目標(biāo)資源的通信選項(xiàng)。
HEAD方法請(qǐng)求一個(gè)與GET請(qǐng)求的響應(yīng)相同的響應(yīng),但沒有響應(yīng)體.
CONNECT方法建立一個(gè)到由目標(biāo)資源標(biāo)識(shí)的服務(wù)器的隧道。
TRACE方法沿著到目標(biāo)資源的路徑執(zhí)行一個(gè)消息環(huán)回測(cè)試。
PATCH方法用于對(duì)資源應(yīng)用部分修改。
2019-06-22