日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《图解HTTP》摘录

發布時間:2024/1/8 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《图解HTTP》摘录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

# 圖解HTTP

第 1 章 了解Web及網絡基礎

1.1使用http協議訪問web

客戶端:通過發送請求獲取服務器資源的Web瀏覽器等。
Web使用一種名為 HTTP(HyperText Transfer Protocol,超文本傳輸協議)的協議作為規范,完成從客戶端到服務器端等一系列運作流程。而協議是指規則的約定。可以說,Web是建立在HTTP協議上通信的。

1.2 HTTP的誕生

1.2.1 為知識共享而規劃Web

? 最初的基本理念:借助多文檔之間相互關聯形成的超文本(HyperText),連成可相互參閱的WWW(World Wide Web,萬維網)。
現在提出了3項WWW構建技術,分別是:把SGML(Standard Generalized markup Language,標準通用標記語言)作為頁面的文本標記語言的HTML(HyperText Markup Language,超文本標記語言);作為文檔傳遞協議的HTTP;指定文檔所在地址的URL(Uniform Resource Locatou,統一資源定位符)。

? WWW這一名稱,是Web瀏覽器當年用來瀏覽超文本的客戶端應用程序時的名稱。現在則用來表示這一系列的集合,也可稱為Web。

? 1995年微軟與網景爆發瀏覽器大戰。2000年前后隨著網景通信公司的衰落而告一段落。04年,Mozilla基金會發布了Firefox瀏覽器,第二次瀏覽器大戰隨即爆發。

? HTTP于1990年問世。那時的HTTP并沒有作為正式的標準被建立。現在的HTTP其實含有HTTP1.0之前版本的意思,因此被稱為HTTP/0.9。

HTTP/1.0:作為標準被公布(1996年5月),版本被命名為HTTP/1.0。

HTTP/1.1: 97年1月公布,是目前主流的HTTP協議版本。當初的標準是RFC2068,之后發布的修訂版RFC2626就是當前的最新版本。

2.0在修訂,但是離普及還有很遠一段路。

1.3 網絡基礎TCP/IP

? 通常使用的網絡(包括互聯網)是在TCP/IP協議族的基礎上運作的。而HTTP屬于它內部的一個子集。

計算機與網絡設備要相互通信,雙方就必須基于相同的方法。而我們就把這種規則稱為 協議。(protocol)

? TCP/IP是互聯網相關的各類協議族的總稱。也有說法認為,TCP/IP是指TCP和IP這兩種協議。還有一種說法認為,TCP/IP是在IP協議的通信過程中,使用到的協議族的統稱。

1.3.2 TCP/IP的分層管理

? TCP/IP協議族按層次分別分為以下4層:應用層、傳輸層、網絡層和數據鏈路層。
層次化之后,設計簡單,替換方便。

應用層: 應用層決定了向用戶提供應用服務時通信的活動。

? TCP/IP協議族內預存了各類通用的應用服務。比如,FTP(File Transfer Protocol,文件傳輸協議)和DNS(Domain Name System,域名系統)服務就是其中的兩類。
HTTP協議也處于該層。

傳輸層: 傳輸層對上層應用層,提供處于網絡連接中的兩臺計算機之間的數據傳輸。

? 在傳輸層有兩個性質不同的協議:TCP(Transmission Control Protocol,傳輸控制協議)和UDP(User Data Protocol,用戶數據報協

議)。

網絡層(又名網絡互連層): 網絡層用來處理在網絡上流動的數據包。數據包是網絡傳輸的最小數據單位。該層規定了通過怎樣的路徑(所謂的傳輸路線)到達對方計算機,并把數據包傳送給對方。

? 與對方計算機之間通過多臺計算機或網絡設備進行傳輸時,網絡層所起的作用就是在眾多的選項內選擇一條傳輸路線。

鏈路層(又名數據鏈路層,網絡接口層): 用來處理連接網絡的硬件部分。包括控制操作系統、硬件的設備驅動、NIC(Network Interface Card,網絡適配器,即網卡),及光纖等物理可見部分(還包括連接器等一切傳輸媒介)。硬件上的范疇均在鏈路層的作用范圍之內。

1.3.3 TCP/IP通信傳輸流

? 利用TCP/IP協議族進行網絡通信時,會通過分層順序與對方進行通信。發送端從應用層往下走,接收端則往應用層往上走。

? 我們用HTTP舉例來說明,首先作為發送端的客戶端在應用層(HTTP協議)發出一個想看某個Web頁面的HTTP請求。

? 接著,為了傳輸方便,在傳輸層(TCP協議)把從應用層處收到的數據(HTTP請求報文)進行分割,并在各個報文上打上標記序號及端口號后轉發給網絡層。

? 在網絡層(IP協議),增加作為通信目的地的MAC地址后轉發給鏈路層。這樣一來,發往網絡的通信請求就準備齊全了。

? 發送端在層與層之間傳輸數據時,沒經過一層時必定會被打上一個該層所屬的首部信息。反之,接收端在層與層傳輸數據時,沒經過一層時會把對應的首部消去。

封裝(encapsulate):這種把數據包裝起來的做法。

1.4 與HTTP關系密切的協議:IP/TCP和DNS

1.4.1 負責傳輸的IP協議

? 按層次分,IP(Internet Protocol)網際協議位于網絡層。幾乎所有使用網絡的系統都會用到IP協議。
IP和IP地址不是一回事。這里的 IP其實是一種協議的名稱。

? IP協議的作用是把各種數據包傳送給對方。而要保證確實傳送到對方那里,則需要滿足各類條件。其中兩個重要的條件是IP地址和MAC地址(Media Access Control Address)。

? IP地址指明了節點被分配到的地址,MAC地址是指網卡所屬的固定地址。IP地址可以和MAC地址進行配對。IP地址可變換,但MAC地址基本上不會更改。

1.4.2 使用ARP協議憑借MAC地址進行通信

? IP間的通信依賴MAC地址。在網絡上,通信的雙方在同一局域網(LAN)內的情況是很少的,通常是經過多臺計算機和網絡設備中轉才能連接到對方。而在進行中轉時,會利用下一站中轉設備的MAC地址來搜索下一個中轉目標。這時,會采用ARP協議(Address Resolution Protocol)。ARP是一種用以解析地址的協議,根據通信方的IP地址就可以反查出對方的MAC地址。

沒有人能夠全面掌握互聯網中的傳輸狀況

? 在到達通信目標前的中轉過程中,那些計算機和路由器等網絡設備只能獲悉很粗略的傳輸路線。
這種機制稱為路由選擇。(routing)(中轉)

1.4.2 確保可靠性的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協議會再次以相同的順序發送相同的數據包。

1.5 負責域名解析的DNS服務

? DNS(Domain Name System)服務是和 HTTP 協議一樣位于應用層的協議。它提供域名到IP地址之間的解析服務。
計算機既可以被賦予IP地址,也可以被賦予主機名和域名。用戶通常用主機名和域名,因為好記,而計算機擅長處理數字。
為了解決上述問題,DNS服務應運而生。DNS協議提供通過域名查找IP地址,或逆向從IP地址反查域名的服務。

1.6 各種協議與 HTTP 協議的關系

客戶端想要瀏覽某個頁面,比如是https:www.google.com,要經歷如下步驟:

1.DNS解析,DNS服務器根據域名返回對應IP地址。

2.HTTP協議,生成針對目標Web服務器的HTTP請求報文。

3.TCP協議,為了方便通信,將HTTP請求報文分割成報文段,按序號分別多個報文段,把每個報文段可靠(三次握手)的傳給對方。

4.IP協議,搜索對方的地址,一邊中轉一邊傳送。

5.TCP協議,重組從對方那里接受到的報文段,按序號以原來的順序重組請求報文。

6.HTTP,對Web服務器請求的內容的處理。

請求的處理結果也同樣利用TCP/IP通信協議向用戶進行回傳

1.7 URI和URL

與 URI (統一資源標識符)相比,我們更熟悉 URL ( Uniform Resource Locator ,統一資源定位符)。 URL正是使用 Web 瀏覽器等訪問 Web 頁面時需要輸入的網頁地址。

1.7.1 統一資源標識符

URI 是 Uniform Resource Identifier 的縮寫。 RFC2396 分別對這 3 個單詞進行了如下定義。

Uniform

規定統一的格式可方便處理多種不同類型的資源,而不用根據上下文環境來識別資源指定的訪問方式。另外,加入新增的協議方案(如 http: 或 ftp: )也更容易。

Resource

資源的定義是 “ 可標識的任何東西 ” 。除了文檔文件、圖像或服務(例如當天的天氣預報)等能夠區別于其他類型的,全都可作為資源。另外,資源不僅可以是單一的,也可以是多數的集合體。

Identifier

表示可標識的對象。也稱為標識符。

綜上所述, URI 就是由某個協議方案表示的資源的定位標識符。協議方案是指訪問資源所使用的協議類型名稱。

采用 HTTP 協議時,協議方案就是 http 。除此之外,還有 ftp 、 mailto 、 telnet 、 file 等。標準的 URI 協議方案有30種左右。

URI 用字符串標識某一互聯網資源,而 URL 表示資源的地點(互聯網上所處的位置)。可見 URL 是 URI 的子集。
在充分理解的基礎上,也可用 URL 替換 URI 。

1.7.2 URI格式

表示指定的 URI,要使用涵蓋全部必要信息的絕對 URI、絕對 URL 以及相對 URL 。相對 URL ,是指從瀏覽器中基本 URI 處指定的 URL ,形如 /image/logo.gif 。

絕對URI格式

http://user:pass@www.example.jp:80/dir/index.htm?uid=1#ch1

http://
: 協議/方案名
使用 http: 或 https: 等協議方案名獲取訪問資源時要指定協議類型。不區分字母大小寫,最后附一個冒號( : )。

user:pass
: 登錄信息(認證)
指定用戶名和密碼作為從服務器端獲取資源時必要的登錄信息(身份認證)。此項是可選項。

www.example.jp
: 服務器地址
使用絕對 URI 必須指定待訪問的服務器地址。地址可以是類似 hackr.jp 這種 DNS 可解析的名稱,或是 192.168.1.1 這類 IPv4 地址 名,還可以是 [0:0:0:0:0:0:0:1] 這樣用方括號括起來的 IPv6 地址名。

80
: 服務器端口號
指定服務器連接的網絡端口號。此項也是可選項,若用戶省略則自動使用默認端口號。

dir/index.htm
: 帶層次的文件路徑
指定服務器上的文件路徑來定位特指的資源。這與 UNIX 系統的文件目錄結構相似。

uid=1
: 查詢字符串
針對已指定的文件路徑內的資源,可以使用查詢字符串傳入任意參數。此項可選。

ch1
: 片段標識符
使用片段標識符通常可標記出已獲取資源中的子資源(文檔內的某個位置)。但在 RFC 中并沒有明確規定其使用方法。該項也為可選項。

RFC
: 有一些用來制定 HTTP 協議技術標準的文檔,它們被稱為 RFC ( Request for Comments ,征求修正意
見書)。

第 2 章 簡單的HTTP協議

2.1 HTTP協議用于客戶端和服務器端之間的通信

HTTP 協議和 TCP/IP 協議族內的其他眾多的協議相同,用于客戶端和服務器之間的通信。
請求訪問文本或圖像等資源的一端稱為客戶端,而提供資源響應的一端稱為服務器端。

應用 HTTP 協議時,必定是一端擔任客戶端角色,另一端擔任服務器端角色。
有時候,按實際情況,兩臺計算機作為客戶端和服務器端的角色有可能會互換。但就僅從一條通信路線來說,服務器端和客戶端的角色是確定的,而用 HTTP 協議能夠明確區分哪端是客戶端,哪端是服務器端。

2.2 通過請求和響應的交換達成通信

HTTP 協議規定,請求從客戶端發出,最后服務器端響應該請求并返回。換句話說,肯定是先從客戶端開始建立通信的,服務器端在沒有接收到請求之前不會發送響應。

GET /index.htm HTTP/1.1
Host: hackr.jp

起始行開頭的 GET 表示請求訪問服務器的類型,稱為方法( method )。隨后的字符串 /index.htm 指明了請求訪問的資源對象,也叫做請求 URI ( request-URI )。最后的 HTTP/1.1 ,即 HTTP 的版本號,用來提示客戶端使用的 HTTP 協議功能。

綜合來看,這段請求內容的意思是:請求訪問某臺 HTTP 服務器上的 /index.htm 頁面資源。

請求報文是由請求方法、請求 URI 、協議版本、可選的請求首部字段和內容實體構成的。

POST /form/entry HTTP/1.1 方法 URI 協議版本 Host: hackr.jp Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length" 16 請求首部字段 name-uenomage-37 內容實體

接收到請求的服務器,會將請求內容的處理結果以響應的形式返回。

HTTP/1.1 200 OK 協議版本 狀態碼 狀態碼的原因短語 Date: Tue, 10 Jul 2012 06:50:15 GMT Content-Length: 362 Content-Type: text/html 響應首部字段<html> …… 主體

在起始行開頭的 HTTP/1.1 表示服務器對應的 HTTP 版本。
緊挨著的 200 OK 表示請求的處理結果的狀態碼( status code )和原因短語( reason-phrase )。下一行顯示了創建響應的日期時間,是首部字段( header field )內的一個屬性。

接著以一空行分隔,之后的內容稱為資源實體的主體( entity body )。

響應報文基本上由協議版本、狀態碼(表示請求成功或失敗的數字代碼)、用以解釋狀態碼的原因短語、可選的響應首部字段以及實體主體構成。

2.3 HTTP 是不保存狀態的協議

HTTP 是一種不保存狀態,即無狀態( stateless )協議。 HTTP 協議自身不對請求和響應之間的通信狀態進行保存。也就是說在 HTTP 這個級別,協議對于發送過的請求或響應都不做持久化處理。

使用 HTTP 協議,每當有新的請求發送時,就會有對應的新響應產生。協議本身并不保留之前一切的請求或響應報文的信息。這是為了更快地處理大量事務,確保協議的可伸縮性,而特意把 HTTP 協議設計成如此簡單的。

可是,隨著 Web 的不斷發展,因無狀態而導致業務處理變得棘手的情況增多了。比如,用戶登錄到一家購物網站,即使他跳轉到該站的其他頁面后,也需要能繼續保持登錄狀態。針對這個實例,網站為了能夠掌握是誰送出的請求,需要保存用戶的狀態。

HTTP/1.1 雖然是無狀態協議,但為了實現期望的保持狀態功能,于是引入了 Cookie 技術。有了 Cookie 再用 HTTP 協議通信,就可以管理狀態了。

2.4 請求 URI 定位資源

當客戶端請求訪問資源而發送請求時, URI 需要將作為請求報文中的請求 URI 包含在內。
URI為完整的請求URI

GET http://hackr.jp/index.htm HTTP/1.1

在首部字段Host中寫明網絡域名或IP地址

GET /index.htm HTTP/1.1 Host: hackr.jp

除此之外,如果不是訪問特定資源而是對服務器本身發起請求,可以用一個 * 來代替請求 URI 。下面這個例子是查詢 HTTP 服務器端支持 的 HTTP 方法種類。

OPTIONS * HTTP/1.1

2.5 告知服務器意圖的 HTTP 方法

GET
: 獲取資源

GET 方法用來請求訪問已被 URI 識別的資源。指定的資源經服務器端解析后返回 響應內容。也就是說,如果請求的資源是文本,那就保持原樣返回;如果是像 CGI ( Common Gateway Interface ,通用網關接口)那樣的程序,則返回經過執行后的輸出結果。

請求:GET /index.html HTTP/1.1Host:www.hackr.jp 響應:返回index.html的頁面資源 請求:GET /index.html HTTP/1.1Host:www.hackr.jpIf-Modified-Since: Thu, 12 Jul 2012 07:30:00 GMT 響應:僅返回 2012 年 7 月 12 日 7 點 30 分以后更新過的 index.html 頁面資源。如果未有內容更新,則以狀態碼 304 Not Modified 作為響應返回

POST
: 傳輸實體主體

雖然用 GET 方法也可以傳輸實體的主體,但一般不用 GET 方法進行傳輸,而是用 POST 方法。雖說 POST
的功能與 GET 很相似,但 POST 的主要目的并不是獲取響應的主體內容。

請求:POST /submit.cgi HTTP/1.1Host: www.hackr.jpContent-Length: 1560 ( 1560 字節的數據) 響應:返回 submit.cgi 接收數據的處理結果

PUT
: 傳輸文件

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

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

請求:PUT /example.html HTTP/1.1Host: www.hackr.jpContent-Type: text/htmlContent-Length: 1560 ( 1560 字節的數據) 響應:響應返回狀態碼 204 No Content (比如 :該 html 已存在于服務器上)

此處響應的意思其實是請求執行成功了,但無數據返回。

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

請求:HEAD /index.html HTTP/1.1Host: www.hackr.jp 響應:返回 index.html 有關的響應首部

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

但是, HTTP/1.1 的 DELETE 方法本身和 PUT 方法一樣不帶驗證機制,所以一般的 Web 網站也不使用 DELETE 方法。當配合 Web 應用程序的驗證機制,或遵守 REST 標準時還是有可能會開放使用的。

請求:DELETE /example.html HTTP/1.1Host: www.hackr.jp 響應:響應返回狀態碼 204 No Content (比如 :該 html 已從該服務器上刪除)

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

請求:OPTIONS * HTTP/1.1Host: www.hackr.jp 響應:HTTP/1.1 200 OKAllow: GET, POST, HEAD,OPTIONS(返回服務器支持的方法)

TRACE
: 追蹤路徑

TRACE 方法是讓 Web 服務器端將之前的請求通信環回給客戶端的方法。

發送請求時,在 Max-Forwards 首部字段中填入數值,每經過一個服務器端就將該數字減 1 ,當數值剛好減到 0 時,就停止繼續傳輸,最后接收到請求的服務器端則返回狀態碼 200 OK的響應。

客戶端通過 TRACE 方法可以查詢發送出去的請求是怎樣被加工修改 / 篡改的。這是因為,請求想要連接到源目標服務器可能會通過代理中轉, TRACE 方法就是用來確認連接過程中發生的一系列操作。

但是, TRACE 方法本來就不怎么常用,再加上它容易引發 XST ( Cross-Site Tracing ,跨站追蹤)攻擊,通常就更不會用到了。

請求:TRACE / HTTP/1.1Host: hackr.jpMax-Forwards: 2 響應:HTTP/1.1 200 OKContent-Type: message/httpContent-Length: 1024TRACE / HTTP/1.1Host: hackr.jpMax-Forwards: 2 (返回響應包含請求內 容)

CONNECT
: 要求用隧道協議連接代理

CONNECT 方法要求在與代理服務器通信時建立隧道,實現用隧道協議進行 TCP通信。主要使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全) 協議把通信內容加密后經網絡隧道傳輸。

CONNECT 代理服務器名 : 端口號 HTTP 版本 請求:CONNECT proxy.hackr.jp:8080 HTTP/1.1Host: proxy.hackr.jp 響應:HTTP/1.1 200 OK (之后進入網絡隧道)

2.6 使用方法下達命令

向請求 URI 指定的資源發送請求報文時,采用稱為方法的命令。

方法的作用在于,可以指定請求的資源按期望產生某種行為。方法中有 GET 、 POST 和 HEAD 等。

方法說明支持的HTTP 協議版本
GET獲取資源1.0、1.1
POST傳輸實體主體1.0 、 1.1
PUT傳輸文件1.0 、 1.1
HEAD獲得報文首部1.0 、 1.1
DELETE刪除文件1.0 、 1.1
OPTIONS詢問支持的方法1.1
TRACE追蹤路徑1.1
CONNECT要求用隧道協議連接代理1.1
LINK建立和資源之間的聯系1.0
UNLINE斷開連接關系1.0

2.7 持久連接節省通信量

HTTP 協議的初始版本中,每進行一次 HTTP 通信就要斷開一次 TCP 連接。

以當年的通信情況來說,因為都是些容量很小的文本傳輸,所以即使這樣也沒有多大問題。可隨著 HTTP 的普及,文檔中包含大量圖片的情況多了起來。

比如,使用瀏覽器瀏覽一個包含多張圖片的 HTML 頁面時,在發送請求訪問 HTML 頁面資源的同時,也會請求該 HTML 頁面里包含的其他資源。因此,每次的請求都會造成無謂的 TCP 連接建立和斷開,增加通信量的開銷。

2.7.1 持久連接

為解決上述 TCP 連接的問題, HTTP/1.1 和一部分的 HTTP/1.0 想出了持久連接( HTTP Persistent Connections ,也稱為 HTTP keep-alive 或 HTTP connection reuse)的方法。持久連接的特點是,只要任意一端沒有明確提出斷開連接,則保持 TCP 連接狀態。

持久連接旨在建立 1 次 TCP 連接后進行多次請求和響應的交互。

持久連接的好處在于減少了 TCP 連接的重復建立和斷開所造成的額外開銷,減輕了服務器端的負載。另外,減少開銷的那部分時間,使 HTTP 請求和響應能夠更早地結束,這樣 Web 頁面的顯示速度也就相應提高了。

在 HTTP/1.1 中,所有的連接默認都是持久連接,但在 HTTP/1.0 內并未標準化。雖然有一部分服務器通過非標準的手段實現了持久連接,但服務器端不一定能夠支持持久連接。毫無疑問,除了服務器端,客戶端也需要支持持久連接。

2.7.2 管線化

持久連接使得多數請求以管線化( pipelining )方式發送成為可能。從前發送請求后需等待并收到響應,才能發送下一個請求。管線化技術出現后,不用等待響應亦可直接發送下一個請求。

這樣就能夠做到同時并行發送多個請求,而不需要一個接一個地等待響應了。

比如,當請求一個包含 10 張圖片的 HTML Web 頁面,與挨個連接相比,用持久連接可以讓請求更快結束。
而管線化技術則比持久連接還要快。請求數越多,時間差就越明顯。

HTTP 是無狀態協議,它不對之前發生過的請求和響應的狀態進行管理。也就是說,無法根據之前的狀態進行本次的請求處理。

假設要求登錄認證的 Web 頁面本身無法進行狀態的管理(不記錄已登錄的狀態),那么每次跳轉新頁面不是要再次登錄,就是要在每次請求報文中附加參數來管理登錄狀態。

不可否認,無狀態協議當然也有它的優點。由于不必保存狀態,自然可減少服務器的 CPU 及內存資源的消耗。從另一側面來說,也正是因為 HTTP 協議本身是非常簡單的,所以才會被應用在各種場景里。

保留無狀態協議這個特征的同時又要解決類似的矛盾問題,于是引入了 Cookie 技術。 Cookie 技術通過在請求和響應報文中寫入 Cookie 信息來控制客戶端的狀態。

Cookie 會根據從服務器端發送的響應報文內的一個叫做 Set-Cookie 的首部字段信息,通知客戶端保存 Cookie 。當下次客戶端再往該服務器發送請求時,客戶端會自動在請求報文中加入 Cookie 值后發送出去。

服務器端發現客戶端發送過來的 Cookie 后,會去檢查究竟是從哪一個客戶端發來的連接請求,然后對比服務器上的記錄,最后得到之前的狀態信息。

1、請求報文(沒有 Cookie 信息的狀態)

GET /reader/ HTTP/1.1 Host: hackr.jp * 首部字段內沒有 Cookie 的相關信息

2、響應報文(服務器端生成 Cookie 信息)

HTTP/1.1 200 OK Date: Thu, 12 Jul 2012 07:12:20 GMT Server: Apache < Set-Cookie: sid=1342077140226724; path=/; expires=Wed, 10-Oct-12 07:12:20 GMT > Content-Type: text/plain; charset=UTF-8

3、請求報文(自動發送保存著的 Cookie 信息)

GET /image/ HTTP/1.1 Host: hackr.jp Cookie: sid=1342077140226724

第 3 章 HTTP報文內的HTTP信息

3.1 HTTP報文

用于 HTTP 協議交互的信息被稱為 HTTP 報文。請求端(客戶端)的 HTTP 報文叫做請求報文,響應端(服務器端)的叫做響應報文。 HTTP 報文本身是由多行(用 CR+LF 作換行符)數據構成的字符串文本。

HTTP 報文大致可分為報文首部和報文主體兩塊。兩者由最初出現的空行( CR+LF )來劃分。通常,并不一定要有報文主體。

報文首部【報文首部】服務器端或客戶端處理的請求或響應的內容及屬性
空行(CR+LF)CR(Carrage Return,回車符:16進制0x0d)和LF(Line Feed,換行符:16進制0x0a)
報文主體應被發送的數據

3.2 請求報文及響應報文的結構

請求行 請求首部字段 通用首部字段 實體首部字段 其他 狀態行 響應首部字段 通用首部字段 實體首部字段 其他

請求報文和響應報文的首部內容由以下數據組成。

請求行
: 包含用于請求的方法,請求你URI和HTTP版本。

狀態行
: 包含表明響應結果的狀態碼,原因短語和HTTP版本。

首部字段
: 包含表示請求和響應的各種條件和屬性的各類首部。
一般有4種首部,分別是:通用首部、請求首部、響應首部和實體首部。

其他
: 可能包含HTTP的RFC里未定義的首部(Cookie等)

3.3 編碼提升傳輸速率

HTTP 在傳輸數據時可以按照數據原貌直接傳輸,但也可以在傳輸過程中通過編碼提升傳輸速率。通過在傳輸時編碼,能有效地處理大量的訪問請求。但是,編碼的操作需要計算機來完成,因此會消耗更多的 CPU 等資源。

3.3.1 報文主體和實體主體的差異

報文(message)
: 是HTTP通信中的基本單位,由 8 位組字節流(octet sequence,其中 octet 為 8 個比特)組成,通過 HTTP 通信傳輸。

實體(entity)
: 作為請求或響應的有效載荷數據(補充項)被傳輸,其內容由實體首部和實體主體組成。

HTTP 報文的主體用于傳輸請求或響應的實體主體。

通常,報文主體等于實體主體。只有當傳輸中進行編碼操作時,實體主體的內容發生變化,才導致它和報文主體產生差異。

報文和實體這兩個術語在之后會經常出現,請事先理解兩者的差異。

3.3.2 壓縮傳輸的內容編碼

向待發送郵件內增加附件時,為了使郵件容量變小,我們會先用 ZIP壓縮文件之后再添加附件發送。 HTTP協議中有一種被稱為內容編碼的功能也能進行類似的操作。

內容編碼指明應用在實體內容上的編碼格式,并保持實體信息原樣壓縮。內容編碼后的實體由客戶端接收并負責解碼。

常用的內容編碼有以下幾種:

  • gzip ( GNU zip )
  • compress ( UNIX 系統的標準壓縮)
  • deflate ( zlib )
  • identity (不進行編碼)

3.3.3 分割發送的分塊傳輸編碼

在 HTTP 通信過程中,請求的編碼實體資源尚未全部傳輸完成之前,瀏覽器無法顯示請求頁面。在傳輸大容量數據時,通過把數據分割成多塊,能夠讓瀏覽器逐步顯示頁面。

這種把實體主體分塊的功能稱為分塊傳輸編碼( Chunked Transfer Coding)。

分塊傳輸編碼會將實體主體分成多個部分(塊)。每一塊都會用十六進制來標記塊的大小,而實體主體的最后一塊會使用 “0(CR+LF)” 來標記。

使用分塊傳輸編碼的實體主體會由接收的客戶端負責解碼,恢復到編碼前的實體主體。

HTTP/1.1中存在一種稱為傳輸編碼(Transfer Coding)的機制,它可以在通信時按某種編碼方式傳輸,但只定義作用于分塊傳輸編碼中。

3.4 發送多種數據的多部分對象集合

發送郵件時,我們可以在郵件里寫入文字并添加多份附件。這是因為采用了 MIME ( Multipurpose Internet Mail Extensions,多用途因特網郵件擴展)機制,它允許郵件處理文本、圖片、視頻等多個不同類型的數據。例如,圖片等二進制數據以 ASCII 碼字符串編碼的方式指明,就是利用 MIME 來描述標記數據類型。而在 MIME 擴展中會使用一種稱為多部分對象集合( Multipart)的方法,來容納多份不同類型的數據。

相應地, HTTP 協議中也采納了多部分對象集合,發送的一份報文主體內可含有多類型實體。通常是在圖片或文本文件等上傳時使用。

多部分對象集合包含的對象如下:

multipart/form-data
: 在 Web 表單文件上傳時使用。

multipart/byteranges
: 狀態碼 206 ( Partial Content ,部分內容)響應報文包含了多個范圍的內容時使用。

在 HTTP 報文中使用多部分對象集合時,需要在首部字段里加上 Content-type 。有關這個首部字段,我們稍后講解。

3.5 獲取部分內容的范圍請求

以前,用戶不能使用現在這種高速的帶寬訪問互聯網,當時,下載一個尺寸稍大的圖片或文件就已經很吃力了。如果下載過程中遇到網絡中斷的情況,那就必須重頭開始。為了解決上述問題,需要一種可恢復的機制。所謂恢復是指能從之前下載中斷處恢復下載。

要實現該功能需要指定下載的實體范圍。像這樣,指定范圍發送的請求叫做范圍請求( Range Request )。

對一份 10 000字節大小的資源,如果使用范圍請求,可以只請求 5001~10 000 字節內的資源。

執行范圍請求時,會用到首部字段 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的響應報文。另外,對于多重范圍的范圍請求,響應會在首部字段 Content-Type 標明 multipart/byteranges 后返回響應報文。

如果服務器端無法響應范圍請求,則會返回狀態碼 200 OK 和完整的實體內容。

3.6 內容協商返回最合適的內容

同一個 Web 網站有可能存在著多份相同內容的頁面。比如英語版和中文版的 Web 頁面,它們內容上雖相同,但使用的語言卻不同。

當瀏覽器的默認語言為英語或中文,訪問相同 URI 的 Web 頁面時,則會顯示對應的英語版或中文版的 Web 頁面。這樣的機制稱為內容協商( Content Negotiation )。

內容協商機制是指客戶端和服務器端就響應的資源內容進行交涉,然后提供給客戶端最為適合的資源。內容協商會以響應資源的語言、字符集、編碼方式等作為判斷的基準。

包含在請求報文中的某些首部字段(如下)就是判斷的基準。

  • Accept
  • Accept-Charset
  • Accept-Encoding
  • Accept-Language
  • Content-Language

內容協商技術有以下 3 種類型:
服務器驅動協商( Server-driven Negotiation )
: 由服務器端進行內容協商。以請求的首部字段為參考,在服務器端自動處理。但對用戶來說,以瀏覽器發送的信息作為判定的依據,并不一定能篩選出最優內容。

客戶端驅動協商( Agent-driven Negotiation )
: 由客戶端進行內容協商的方式。用戶從瀏覽器顯示的可選項列表中手動選擇。還可以利用 JavaScript 腳本在 Web 頁面上自動進行上述選擇。比如按 OS 的類型或瀏覽器類型,自行切換成 PC 版頁面或手機版頁面。

透明協商( Transparent Negotiation )
: 是服務器驅動和客戶端驅動的結合體,是由服務器端和客戶端各自進行內容協商的一種方法。

第 4 章 返回結果的 HTTP 狀態碼

4.1 狀態碼告知從服務器端返回的請求結果

狀態碼的職責是當客戶端向服務器端發送請求時,描述返回的請求結果。借助狀態碼,用戶可以知道服務器端是正常處理了請求,還是出現了錯誤。

狀態碼如 200 OK ,以 3 位數字和原因短語組成。

數字中的第一位指定了響應類別,后兩位無分類。響應類別有以下 5 種。

|編號|類別|原因短語|
|---|||
|1XX|Informational(信息性狀態碼)|接受的請求正在處理|
|2XX|Success(成功狀態碼)|請求正常處理完畢|
|3XX|Redirection(重定向狀態碼)|需要進行附加操作以完成請求|
|4XX|Client Error(客戶端錯誤狀態碼)|服務器無法處理請求|
|5XX|Server Error(服務器錯誤狀態碼)|服務器處理請求出錯|

只要遵守狀態碼類別的定義,即使改變 RFC2616 中定義的狀態碼,或服務器端自行創建狀態碼都沒問題。

HTTP 狀態碼就達很多,有60多種,但是常用的只有14個。

4.2 2XX成功

2XX的響應結果表明請求被正常處理了。

4.2.1 200 OK

  • 表示從客戶端發來的請求在服務器端被正常處理了。

在響應報文內,隨狀態碼一起返回的信息會因方法的不同而發生改變。比如,使用 GET 方法時,對應請求資源的實體會作為響應返回;而使用 HEAD 方法時,對應請求資源的實體首部不隨報文主體作為響應返回(即在響應中只返回首部,不會返回實體的主體部分)。

4.2.2 204 No Content

該狀態碼代表服務器接收的請求已成功處理,但在返回的響應報文中不含實體的主體部分。另外,也不允許返回任何實體的主體。比如,當從瀏覽器發出請求處理后,返回 204 響應,那么瀏覽器顯示的頁面不發生更新。

一般在只需要從客戶端往服務器發送信息,而對客戶端不需要發送新信息內容的情況下使用。

4.2.3 206 Partial Content

該狀態碼表示客戶端進行了范圍請求,而服務器成功執行了這部分的 GET 請求。響應報文中包含由Content-Range 指定范圍的實體內容。

4.3 3XX 重定向

3XX 響應結果表明瀏覽器需要執行某些特殊的處理以正確處理請求。

4.3.1 301 Moved Permanently

永久性重定向。該狀態碼表示請求的資源已被分配了新的 URI ,以后應使用資源現在所指的 URI 。也就是說,如果已經把資源對應的 URI 保存為書簽了,這時應該按 Location 首部字段提示的 URI 重新保存。

像下方給出的請求 URI ,當指定資源路徑的最后忘記添加斜杠 “/” ,就會產生 301 狀態碼。

http://example.com/sample

4.3.2 302 Found

臨時性重定向。該狀態碼表示請求的資源已被分配了新的 URI ,希望用戶(本次)能使用新的 URI 訪問。

和 301 Moved Permanently 狀態碼相似,但 302 狀態碼代表的資源不是被永久移動,只是臨時性質的。換句話說,已移動的資源對應的 URI 將來還有可能發生改變。比如,用戶把 URI 保存成書簽,但不會像 301 狀態碼出現時那樣去更新書簽,而是仍舊保留返回 302 狀態碼的頁面對應的 URI 。

4.3.3 303 See Other

該狀態碼表示由于請求對應的資源存在著另一個 URI ,應使用 GET 方法定向獲取請求的資源。

303 狀態碼和 302 Found 狀態碼有著相同的功能,但 303 狀態碼明確表示客戶端應當采用 GET 方法獲取資
源,這點與 302 狀態碼有區別。

比如,當使用 POST 方法訪問 CGI 程序,其執行后的處理結果是希望客戶端能以 GET 方法重定向到另一個
URI 上去時,返回 303 狀態碼。雖然 302 Found 狀態碼也可以實現相同的功能,但這里使用 303 狀態碼是
最理想的。

本書采用的是 HTTP/1.1 ,而許多 HTTP/1.1 版以前的瀏覽器不能正確理解 303 狀態碼。雖然 RFC 1945 和 RFC 2068 規范不允許客戶端在重定向時改變請求的方法,但是很多現存的瀏覽器將 302 響應視為 303 響應,并且使用 GET 方式訪問在 Location 中規定的 URI ,而無視原先請求的方法。所以作者說這里使用 303 是最理想的。


當 301 、 302 、 303 響應狀態碼返回時,幾乎所有的瀏覽器都會把 POST 改成 GET ,并刪除請求報文內的主體,之后請求會自動再次發送。
301 、 302 標準是禁止將 POST 方法改變成 GET 方法的,但實際使用時大家都會這么做。

4.3.4 304 Not Modified

該狀態碼表示客戶端發送附帶條件的請求 2 時,服務器端允許請求訪問資源,但未滿足條件的情況。 304 狀態碼返回時,不包含任何響應的主體部分。 304 雖然被劃分在 3XX 類別中,但是和重定向沒有關系。

4.3.5 307 Temporary Redirect

臨時重定向。該狀態碼與 302 Found 有著相同的含義。盡管 302 標準禁止 POST 變換成 GET ,但實際使用
時大家并不遵守。

307 會遵照瀏覽器標準,不會從 POST 變成 GET 。但是,對于處理響應時的行為,每種瀏覽器有可能出現不同的情況。

4.4 4XX 客戶端錯誤

4XX 的響應結果表明客戶端是發生錯誤的原因所在。

4.4.1 400 Bad Request

該狀態碼表示請求報文中存在語法錯誤。當錯誤發生時,需修改請求的內容后再次發送請求。另外,瀏覽器會像 200 OK 一樣對待該狀態碼。

4.4.2 401 Unauthorized

該狀態碼表示發送的請求需要有通過 HTTP 認證( BASIC 認證、 DIGEST 認證)的認證信息。另外若之前已進行過 1 次請求,則表示用戶認證失敗。

返回含有 401 的響應必須包含一個適用于被請求資源的 WWW-Authenticate 首部用以質詢( challenge )用戶信息。當瀏覽器初次接收到 401 響應,會彈出認證用的對話窗口。

4.4.3 403 Forbidden

該狀態碼表明對請求資源的訪問被服務器拒絕了。服務器端沒有必要給出拒絕的詳細理由,但如果想作說明的話,可以在實體的主體部分對原因進行描述,這樣就能讓用戶看到了。

未獲得文件系統的訪問授權,訪問權限出現某些問題(從未授權的發送源 IP 地址試圖訪問)等列舉的情況都可能是發生 403 的原因。

4.4.4 404 Not Found

該狀態碼表明服務器上無法找到請求的資源。除此之外,也可以在服務器端拒絕請求且不想說明理由時使用。

4.5 5XX 服務器錯誤

5XX 的響應結果表明服務器本身發生錯誤。

4.5.1 500 Internal Server Error

該狀態碼表明服務器端在執行請求時發生了錯誤。也有可能是 Web 應用存在的 bug 或某些臨時的故障。

4.5.2 503 Service Unavailable

該狀態碼表明服務器暫時處于超負載或正在進行停機維護,現在無法處理請求。如果事先得知解除以上狀況需要的時間,最好寫入 RetryAfter 首部字段再返回給客戶端。

狀態碼和狀況的不一致
不少返回的狀態碼響應都是錯誤的,但是用戶可能察覺不到這點。比如 Web 應用程序內部發生錯誤,狀態碼依然返回 200 OK ,這種情況也經常遇到。

第 5 章與 HTTP 協作的Web服務器

5.1  用單臺虛擬主機實現多個域名

HTTP/1.1 規范允許一臺 HTTP 服務器搭建多個 Web 站點。比如,提供 Web 托管服務( Web Hosting Service )的供應商,可以用一臺服務器為多位客戶服務,也可以以每位客戶持有的域名運行各自不同的網站。這是因為利用了虛擬主機( Virtual Host ,又稱虛擬服務器)的功能。

即使物理層面只有一臺服務器,但只要使用虛擬主機的功能,則可以假想已具有多臺服務器。

在互聯網上,域名通過 DNS 服務映射到 IP 地址(域名解析)之后訪問目標網站。可見,當請求發送到服務器時,已經是以 IP 地址形式訪問了。

所以,如果一臺服務器內托管了 www.tricorder.jp 和 www.hackr.jp 這兩個域名,當收到請求時就需要弄清楚究竟要訪問哪個域名。

在相同的 IP 地址下,由于虛擬主機可以寄存多個不同主機名和域名的 Web 網站,因此在發送 HTTP 請求時,必須在 Host 首部內完整指定主機名或域名的 URI 。

5.2 通信數據轉發程序:代理、網關、隧道

HTTP 通信時,除客戶端和服務器以外,還有一些用于通信數據轉發的應用程序,例如代理、網關和隧道。它們可以配合服務器工作。
這些應用程序和服務器可以將請求轉發給通信線路上的下一站服務器,并且能接收從那臺服務器發送的響應再轉發給客戶端。

代理
: 代理是一種有轉發功能的應用程序,它扮演了位于服務器和客戶端 “ 中間人 ” 的角色,接收由客戶端發送的請求并轉發給服務器,同時也接收服務器返回的響應并轉發給客戶端。

網關
: 網關是轉發其他服務器通信數據的服務器,接收從客戶端發送來的請求時,它就像自己擁有資源的源服務器一樣對請求進行處理。有時客戶端可能都不會察覺,自己的通信目標是一個網關。

隧道
: 隧道是在相隔甚遠的客戶端和服務器兩者之間進行中轉,并保持雙方通信連接的應用程序。

代理服務器的基本行為就是接收客戶端發送的請求后轉發給其他服務器。代理不改變請求 URI ,會直接發送給前方持有資源的目標服務器。
持有資源實體的服務器被稱為源服務器。從源服務器返回的響應經過代理服務器后再傳給客戶端。

在 HTTP 通信過程中,可級聯多臺代理服務器。請求和響應的轉發會經過數臺類似鎖鏈一樣連接起來的代理服務器。轉發時,需要附加 Via 首部字段以標記出經過的主機信息。

使用代理服務器的理由有:利用緩存技術(稍后講解)減少網絡帶寬的流量,組織內部針對特定網站的訪問控制,以獲取訪問日志為主要目的,等等。

代理有多種使用方法,按兩種基準分類。一種是是否使用緩存,另一種是是否會修改報文。

緩存代理
: 代理轉發響應時,緩存代理( Caching Proxy )會預先將資源的副本(緩存)保存在代理服務器上。

當代理再次接收到對相同資源的請求時,就可以不從源服務器那里獲取資源,而是將之前緩存的資源作為響應返回。

透明代理
: 轉發請求或響應時,不對報文做任何加工的代理類型被稱為透明代理( Transparent Proxy )。反之,對報文內容進行加工的代理被稱為非透明代理。

5.2.2  網關

網關的工作機制和代理十分相似。而網關能使通信線路上的服務器提供非 HTTP 協議服務。

利用網關能提高通信的安全性,因為可以在客戶端與網關之間的通信線路上加密以確保連接的安全。比如,網關可以連接數據庫,使用 SQL 語句查詢數據。另外,在 Web 購物網站上進行信用卡結算時,網關可以和信用卡結算系統聯動。

5.2.3  隧道

隧道可按要求建立起一條與其他服務器的通信線路,屆時使用 SSL 等加密手段進行通信。隧道的目的是確保客戶端能與服務器進行安全的通信。

隧道本身不會去解析 HTTP 請求。也就是說,請求保持原樣中轉給之后的服務器。隧道會在通信雙方斷開連接時結束。

5.3  保存資源的緩存

緩存是指代理服務器或客戶端本地磁盤內保存的資源副本。利用緩存可減少對源服務器的訪問,因此也就節省了通信流量和通信時間。

緩存服務器是代理服務器的一種,并歸類在緩存代理類型中。換句話說,當代理轉發從服務器返回的響應時,代理服務器將會保存一份資源的副本。

緩存服務器的優勢在于利用緩存可避免多次從源服務器轉發資源。因此客戶端可就近從緩存服務器上獲取資源,而源服務器也不必多次處理相同的請求了。

5.3.1  緩存的有效期限

即便緩存服務器內有緩存,也不能保證每次都會返回對同資源的請求。因為這關系到被緩存資源的有效性問題。

當遇上源服務器上的資源更新時,如果還是使用不變的緩存,那就會演變成返回更新前的 “ 舊 ” 資源了。

即使存在緩存,也會因為客戶端的要求、緩存的有效期等因素,向源服務器確認資源的有效性。若判斷緩存失效,緩存服務器將會再次從源服務器上獲取 “ 新 ” 資源。

5.3.2  客戶端的緩存

緩存不僅可以存在于緩存服務器內,還可以存在客戶端瀏覽器中。以 Internet Explorer 程序為例,把客戶端緩存稱為臨時網絡文件( Temporary Internet File )。

瀏覽器緩存如果有效,就不必再向服務器請求相同的資源了,可以直接從本地磁盤內讀取。

另外,和緩存服務器相同的一點是,當判定緩存過期后,會向源服務器確認資源的有效性。若判斷瀏覽器緩存失效,瀏覽器會再次請求新資源。

第 6 章 HTTP首部

HTTP 協議的請求和響應報文中必定包含 HTTP 首部,只是我們平時在使用 Web 的過程中感受不到它。

6.1 HTTP 報文首部

請求報文

報文首部在客戶端和服務器處理時起至關重要作用的信息幾乎都在這邊
空行(CR+LF)
報文主體所需要的用戶和資源的信息都在這邊

HTTP 協議的請求和響應報文中必定包含 HTTP 首部。首部內容為客戶端和服務器分別處理請求和響應提供所需要的信息。對于客戶端用戶來說,這些信息中的大部分內容都無須親自查看。
報文首部由幾個字段構成。

HTTP 請求報文
: 在請求中,HTTP 報文由方法、URI 、HTTP 版本、 HTTP 首部字段等部分構成。

報文首部

請求行方法、URI、HTTP版本
請求首部字段HTTP首部字段
通用首部字段HTTP首部字段
實體首部字段HTTP首部字段
其他
GET / HTTP/1.1 Host: hackr.jp User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*; q=0.8 Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Connection: keep-alive If-Modified-Since: Fri, 31 Aug 2007 02:02:20 GMT If-None-Match: "45bae1-16a-46d776ac" Cache-Control: max-age=0

HTTP 響應報文
在響應中, HTTP 報文由 HTTP 版本、狀態碼(數字和原因短語)、 HTTP 首部字段 3 部分構成。

狀態行方法、URI、HTTP版本
響應首部字段HTTP首部字段
通用首部字段HTTP首部字段
實體首部字段HTTP首部字段
其他
HTTP/1.1 304 Not Modified Date: Thu, 07 Jun 2012 07:21:36 GMT Server: Apache Connection: close Etag: "45bae1-16a-46d776ac"

6.2 HTTP 首部字段

6.2.1 HTTP 首部字段傳遞重要信息

HTTP 首部字段是構成 HTTP 報文的要素之一。在客戶端與服務器之間以 HTTP 協議進行通信的過程中,無論是請求還是響應都會使用首部字段,它能起到傳遞額外重要信息的作用。

使用首部字段是為了給瀏覽器和服務器提供報文主體大小、所使用的語言、認證信息等內容。

6.2.2 HTTP 首部字段結構

HTTP 首部字段是由首部字段名和字段值構成的,中間用冒號 “:” 分隔。

首部字段名 : 字段值

另外,字段值對應單個 HTTP 首部字段可以有多個值,如下所示。

Keep-Alive: timeout=15, max=100

若 HTTP 首部字段重復了會如何
: 當 HTTP 報文首部中出現了兩個或兩個以上具有相同首部字段名時會怎么樣?這種情況在規范內尚未明確,根據瀏覽器內部處理邏輯的不同,結果可能并不一致。有些瀏覽器會優先處理第一次出現的首部字段,而有些則會優先處理最后出現的首部字段。

6.2.3 4 種 HTTP 首部字段類型

通用首部字段( General Header Fields )
: 請求報文和響應報文兩方都會使用的首部。

請求首部字段( Request Header Fields )
: 從客戶端向服務器端發送請求報文時使用的首部。補充了請求的附加內容、客戶端信息、響應內容相關優先級等信息。

響應首部字段( Response Header Fields )
: 從服務器端向客戶端返回響應報文時使用的首部。補充了響應的附加內容,也會要求客戶端附加額外的內容信息。

實體首部字段( Entity Header Fields )
: 針對請求報文和響應報文的實體部分使用的首部。補充了資源內容更新時間等與實體有關的信息。

6.2.4 HTTP/1.1 首部字段一覽

通用首部字段

首部字段名說明
Cache-Control控制緩存的行為
Connection逐跳首部、連接的管理
Date創建報文的日期時間
Pragma報文指令
Trailer報文末端的首部一覽
Transfer-Encoding指定報文主體的傳輸編碼方式
Upgrade升級為其他協議
Via代理服務器的相關信息
Warning錯誤通知

請求首部字段

Accept用戶代理可處理的媒體類型
Accept-Charset優先的字符集
Accept-Encoding優先的內容編碼
Accept-Language優先的語言(自然語言)
AuthorizationWeb認證信息
Expect期待服務器的特定行為
From用戶的電子郵箱地址
Host請求資源所在服務器
If-Match比較實體標記( ETag )
If-Modified-Since比較資源的更新時間
If-None-Match比較實體標記(與 If-Match 相反)
If-Range資源未更新時發送實體 Byte 的范圍請求
If-Unmodified-Since比較資源的更新時間(與 If-Modified-Since 相反)
Max-Forwards最大傳輸逐跳數
Proxy-Authorization代理服務器要求客戶端的認證信息
Range實體的字節范圍請求
Referer對請求中 URI 的原始獲取方
TE傳輸編碼的優先級
User-AgentHTTP 客戶端程序的信息

響應首部字段

Accept-Ranges是否接受字節范圍請求
Age推算資源創建經過時間
ETag資源的匹配信息
Location令客戶端重定向至指定 URI
Proxy-Authenticate代理服務器對客戶端的認證信息
Retry-After對再次發起請求的時機要求
Server HTTP服務器的安裝信息
Vary代理服務器緩存的管理信息
WWW-Authenticate服務器對客戶端的認證信息

實體首部字段

Allow資源可支持的 HTTP 方法
Content-Encoding實體主體適用的編碼方式
Content-Language實體主體的自然語言
Content-Length實體主體的大小(單位:字節)
Content-Location替代對應資源的 URI
Content-MD5實體主體的報文摘要
Content-Range實體主體的位置范圍
Content-Type實體主體的媒體類型
Expires實體主體過期的日期時間
Last-Modified資源的最后修改日期時間

6.2.5  非 HTTP/1.1 首部字段

在 HTTP 協議通信交互中使用到的首部字段,不限于 RFC2616 中定義的 47 種首部字段。還有 Cookie 、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部字段,它們的使用頻率也很高。

這些非正式的首部字段統一歸納在 RFC4229 HTTP Header Field Registrations 中。

6.2.6   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

6.3 HTTP/1.1 通用首部字段

通用首部字段是指,請求報文和響應報文雙方都會使用的首部。

6.3.1   Cache-Control

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

指令的參數是可選的,多個指令之間通過 “,” 分隔。首部字段 Cache-Control 的指令可用于請求及響應時。

Cache-Control: private, max-age=0, no-cache

Cache-Control 指令一覽
緩存請求指令

指令參數說明
no-cache強制向源服務器再次驗證
no-store不緩存請求或響應的任何內容
max-age = [ 秒 ]必需響應的最大 Age 值
max-stale( = [ 秒 ])可省略接收已過期的響應
min-fresh = [ 秒 ]必需期望在指定時間內的響應仍有效
no-transform代理不可更改媒體類型
only-if-cached從緩存獲取資源
cache-extension-新指令標記( token )

緩存響應指令

指令參數說明
public可向任意方提供響應的緩存
private可省略僅向特定用戶返回響應
no-cache可省略緩存前必須先確認其有效性
no-store不緩存請求或響應的任何內容
no-transform代理不可更改媒體類型
must-revalidate可緩存但必須再向源服務器進行確認
proxy-revalidate要求中間緩存服務器對緩存的響應有效性再進行確認
max-age = [ 秒 ]必需響應的最大 Age 值
s-maxage = [ 秒 ]必需公共緩存服務器響應的最大 Age 值
cache-extension-新指令標記( token )

表示是否能緩存的指令
public 指令
:

Cache-Control: public

當指定使用 public 指令時,則明確表明其他用戶也可利用緩存。

private 指令
:

Cache-Control: private

當指定 private 指令后,響應只以特定的用戶作為對象,這與 public 指令的行為相反。

緩存服務器會對該特定用戶提供資源緩存的服務,對于其他用戶發送過來的請求,代理服務器則不會返回緩存。

no-cache 指令
:

Cache-Control: no-cache

使用 no-cache 指令的目的是為了防止從緩存中返回過期的資源。

客戶端發送的請求中如果包含 no-cache 指令,則表示客戶端將不會接收緩存過的響應。于是, “ 中間 ” 的緩存服務器必須把客戶端請求轉發給源服務器。

如果服務器返回的響應中包含 no-cache 指令,那么緩存服務器不能對資源進行緩存。源服務器以后也將不再對緩存服務器請求中提出的資源有效性進行確認,且禁止其對響應資源進行緩存操作。

Cache-Control: no-cache=Location

由服務器返回的響應中,若報文首部字段 Cache-Control 中對 no-cache 字段名具體指定參數值,那么客戶端在接收到這個被指定參數值的首部字段對應的響應報文后,就不能使用緩存。換言之,無參數值的首部字段可以使用緩存。只能在響應指令中指定該參數。

控制可執行緩存的對象的指令
no-store 指令
:

Cache-Control: no-store

當使用 no-store 指令 時,暗示請求(和對應的響應)或響應中包含機密信息。

從字面意思上很容易把 no-cache 誤解成為不緩存,但事實上 no-cache 代表不緩存過期的資源,緩存會向源服務器進行有效期確認后處理資源,也許稱為 do-not-serve-from-cache-without-revalidation 更合適。 no-store 才是真正地不進行緩存,請讀本文檔由Linux公社 www.linuxidc.com 整理者注意區別理解。

指定緩存期限和認證的指令
s-maxage 指令
:

Cache-Control: s-maxage=604800 (單位 :秒)

s-maxage 指令的功能和 max-age 指令的相同,它們的不同點是 s-maxage 指令只適用于供多位用戶使用的公共緩存服務器。也就是說,對于向同一用戶重復返回響應的服務器來說,這個指令沒有任何作用。

max-age 指令
:

Cache-Control: max-age=604800 (單位:秒)

當客戶端發送的請求中包含 max-age 指令時,如果判定緩存資源的緩存時間數值比指定時間的數值更小,那
么客戶端就接收緩存的資源。另外,當指定 max-age 值為 0 ,那么緩存服務器通常需要將請求轉發給源服務器。

當服務器返回的響應中包含 max-age 指令時,緩存服務器將不對資源的有效性再作確認,而 max-age 數值代表資源保存為緩存的最長時間。

應用 HTTP/1.1 版本的緩存服務器遇到同時存在 Expires 首部字段的情況時,會優先處理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的緩存服務器的情況卻相反, max-age 指令會被忽略掉。

min-fresh 指令
:

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

min-fresh 指令要求緩存服務器返回至少還未過指定時間的緩存資源。
比如,當指定 min-fresh 為 60 秒后,過了 60 秒的資源都無法作為響應返回了。

6.3.2 Connection

1、 控制不再轉發給代理的首部字段
2、 管理持久連接

Connection: 不再轉發的首部字段名
Connection:Upprade

在客戶端發送請求和服務器返回響應內,使用 Connection 首部字段,可控制不再轉發給代理的首部字段

Connection: close

HTTP/1.1 版本的默認連接都是持久連接。為此,客戶端會在持久連接上連續發送請求。當服務器端想明確斷開連接時,則指定 Connection 首部字段的值為 Close

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

6.3.3 Date

首部字段 Date 表明創建 HTTP 報文的日期和時間。

HTTP/1.1 協議使用在 RFC1123 中規定的日期時間的格式
Date: Tue, 03 Jul 2012 04:40:59 GMT

HTTP 協議版本中使用在 RFC850 中定義的格式
Date: Tue, 03-Jul-12 04:40:59 GMT

還有一種格式。它與 C 標準庫內的 asctime() 函數的輸出格式一致。
Date: Tue Jul 03 04:40:59 2012

6.3.4 Pragma

Pragma 是 HTTP/1.1 之前版本的歷史遺留字段,僅作為與 HTTP/1.0 的向后兼容而定義。
規范定義的形式唯一
Pragma: no-cache

該首部字段屬于通用首部字段,但只用在客戶端發送的請求中。客戶端會要求所有的中間服務器不返回緩存的資源。
Cache-Control: no-cache
Pragma: no-cache

6.3.5 Trailer

首部字段 Trailer 會事先說明在報文主體后記錄了哪些首部字段。該首部字段可應用在 HTTP/1.1 版本分塊傳輸編碼時。 HTTP/1.1 200 OK Date: Tue, 03 Jul 2012 04:40:56 GMT Content-Type: text/html ... Transfer-Encoding: chunked Trailer: Expires ...( 報文主體 )... 0 Expires: Tue, 28 Sep 2004 23:59:59 GMT 以上用例中,指定首部字段 Trailer 的值為 Expires ,在報文主體之后(分塊長度 0 之后)出現了首部字段Expires 。

6.3.6   Transfer-Encoding

首部字段 Transfer-Encoding 規定了傳輸報文主體時采用的編碼方式 HTTP/1.1 200 OK Date: Tue, 03 Jul 2012 04:40:56 GMT Cache-Control: public, max-age=604800 Content-Type: text/javascript; charset=utf-8 Expires: Tue, 10 Jul 2012 04:40:56 GMT X-Frame-Options: DENY X-XSS-Protection: 1; mode=block Content-Encoding: gzip Transfer-Encoding: chunked Connection: keep-alive cf0 ←16 進制 (10 進制為 3312) ...3312 字節分塊數據 ... 392 ←16 進制 (10 進制為 914) ...914 字節分塊數據 ... 0 以上用例中,正如在首部字段 Transfer-Encoding 中指定的那樣,有效使用分塊傳輸編碼,且分別被分成3312 字節和 914 字節大小的分塊數據。

6.3.7   Upgrade

首部字段 Upgrade 用于檢測 HTTP 協議及其他協議是否可使用更高的版本進行通信,其參數值可以用來指定一個完全不同的通信協議。 Upgrade 首部字段產生作用的 Upgrade 對象僅限于客戶端和鄰接服務器之間。因此,使用首部字段 Upgrade 時,還需要額外指定 Connection:Upgrade 。 GET /index.html HTTP/1.1 Upgrade:TLS/1.0 Connection:UpgradeHTTP/1.1 101 Switching Protocols Upgrade:TLS/1.0,HTTP/1.1 Connection:Upgrade

首部字段 Upgrade 指定的值為 TLS/1.0 。請注意此處兩個字段首部字段的對應關
系, Connection 的值被指定為 Upgrade 。 Upgrade 首部字段產生作用的 Upgrade 對象僅限于客戶端和鄰接
服務器之間。因此,使用首部字段 Upgrade 時,還需要額外指定 Connection:Upgrade 。
對于附有首部字段 Upgrade 的請求,服務器可用 101 Switching Protocols 狀態碼作為響應返回。

6.3.8 Via

使用首部字段 Via 是為了追蹤客戶端與服務器之間的請求和響應報文的傳輸路徑。 報文經過代理或網關時,會先在首部字段 Via 中附加該服務器的信息,然后再進行轉發。這個做法和traceroute 及電子郵件的 Received 首部的工作機制很類似。 首部字段 Via 不僅用于追蹤報文的轉發,還可避免請求回環的發生。所以必須在經過代理時附加該首部字段內容。 GET /HTTP/1.1GET /HTTP/1.1 Via: 1.0 gw.hackr.jp(Squid/3.1)GET /HTTP/1.1 Via: 1.0 gw.hackr.jp(Squid/3.1), 1.1 a1.example.com(Squid/2.7) Via 首部是為了追蹤傳輸路徑,所以經常會和 TRACE 方法一起使用。比如,代理服務器接收到由 TRACE 方法發送過來的請求(其中 Max-Forwards: 0 )時,代理服務器就不能再轉發該請求了。這種情況下,代理服務器會將自身的信息附加到 Via 首部后,返回該請求的響應。

6.3.9   Warning

HTTP/1.1 的 Warning 首部是從 HTTP/1.0 的響應首部( Retry-After )演變過來的。該首部通常會告知用戶一些與緩存相關的問題的警告。 Warning: 113 gw.hackr.jp:8080 "Heuristic expiration" Tue, 03 Jul 2012 05:09:44 GMT

Warning 首部的格式如下。最后的日期時間部分可省略。

Warning: [ 警告碼 ][ 警告的主機 : 端口號 ]“[ 警告內容 ]”([ 日期時間 ])

HTTP/1.1 中定義了 7 種警告。

警告碼警告內容說明
110Response is stale (響應已過期)代理返回已過期的資源
111Revalidation failed (再驗證失敗)代理再驗證資源有效性時失敗(服務器無法到達等原因)
112Disconnection operation (斷開連接操作)代理與互聯網連接被故意切斷
113Heuristic expiration (試探性過期)響應的使用期超過 24 小時(有效緩存的設定時間大于 24 小時的情況下)
199Miscellaneous warning (雜項警告)任意的警告內容
214Transformation applied (使用了轉換)代理對內容編碼或媒體類型等執行了某些處理時
299Miscellaneous persistent warning (持久雜項警告)任意的警告內容

6.4 請求首部字段

6.4.1   Accept

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

Accept 首部字段可通知服務器,用戶代理能夠處理的媒體類型及媒體類型的相對優先級。可使用type/subtype 這種形式,一次指定多種媒體類型。

文本文件

text/html, text/plain, text/css ...
application/xhtml+xml, application/xml ...

圖片文件

image/jpeg, image/gif, image/png ...

視頻文件

video/mpeg, video/quicktime ...

應用程序使用的二進制文件

application/octet-stream, application/zip ...

比如,如果瀏覽器不支持 PNG 圖片的顯示,那 Accept 就不指定 image/png ,而指定可處理的 image/gif 和image/jpeg 等圖片類型。 若想要給顯示的媒體類型增加優先級,則使用 q= 來額外表示權重值 1 ,用分號( ; )進行分隔。權重值 q 的范圍是 0~1 (可精確到小數點后 3 位),且 1 為最大值。不指定權重 q 值時,默認權重為 q=1.0 。

6.4.2   Accept-Charset

Accept-Charset: iso-8859-5, unicode-1-1;q=0.8 Accept-Charset 首部字段可用來通知服務器用戶代理支持的字符集及字符集的相對優先順序。另外,可一次性指定多種字符集。與首部字段 Accept 相同的是可用權重 q 值來表示相對優先級。 該首部字段應用于內容協商機制的服務器驅動協商。

6.4.3   Accept-Encoding

Accept-Encoding: gzip, deflate Accept-Encoding 首部字段用來告知服務器用戶代理支持的內容編碼及內容編碼的優先級順序。可一次性指定多種內容編碼。

gzip

由文件壓縮程序 gzip ( GNU zip )生成的編碼格式( RFC1952 ),采用 Lempel-Ziv 算法( LZ77 )及 32位循環冗余校驗( Cyclic Redundancy Check ,通稱 CRC )。

compress

由 UNIX 文件壓縮程序 compress 生成的編碼格式,采用 Lempel-Ziv-Welch 算法( LZW )。

deflate

組合使用 zlib 格式( RFC1950 )及由 deflate 壓縮算法( RFC1951 )生成的編碼格式。

identity
不執行壓縮或不會變化的默認編碼格式

6.4.4   Accept-Language

Accept-Language: zh-cn,zh;q=0.7,en-us,en;q=0.3 首部字段 Accept-Language 用來告知服務器用戶代理能夠處理的自然語言集(指中文或英文等),以及自然語言集的相對優先級。可一次指定多種自然語言集。

6.4.5   Authorization

1.客戶端 GET /index.htm2.服務器:該頁面需要HTTP認證,把認證信息發給我 401 Unauthorized WWW-Authenticate:Basic...3.客戶端 GET /index.htm Authorization:Basic dWVub3NlbjpwYXNzd29yZA== 首部字段 Authorization 是用來告知服務器,用戶代理的認證信息(證書值)。通常,想要通過服務器認證的用戶代理會在接收到返回的 401 狀態碼響應后,把首部字段 Authorization 加入請求中。共用緩存在接收到含有 Authorization 首部字段的請求時的操作處理會略有差異。

6.4.6   Expect

Expect: 100-continue 客戶端使用首部字段 Expect 來告知服務器,期望出現的某種特定行為。因服務器無法理解客戶端的期望作出回應而發生錯誤時,會返回狀態碼 417 Expectation Failed 。 客戶端可以利用該首部字段,寫明所期望的擴展。雖然 HTTP/1.1 規范只定義了 100-continue (狀態碼 100Continue 之意)。 等待狀態碼 100 響應的客戶端在發生請求時,需要指定 Expect:100-continue 。

6.4.7   From

From:info@hackr.jp 首部字段 From 用來告知服務器使用用戶代理的用戶的電子郵件地址。通常,其使用目的就是為了顯示搜索引擎等用戶代理的負責人的電子郵件聯系方式。使用代理時,應盡可能包含 From 首部字段(但可能會因代理不同,將電子郵件地址記錄在 User-Agent 首部字段內)。

6.4.8   Host

Host: www.hackr.jp 首部字段 Host 會告知服務器,請求的資源所處的互聯網主機名和端口號。 Host 首部字段在 HTTP/1.1 規范內是唯一一個必須被包含在請求內的首部字段。 首部字段 Host 和以單臺服務器分配多個域名的虛擬主機的工作機制有很密切的關聯,這是首部字段 Host 必須存在的意義。 請求被發送至服務器時,請求中的主機名會用 IP 地址直接替換解決。但如果這時,相同的 IP 地址下部署運行著多個域名,那么服務器就會無法理解究竟是哪個域名對應的請求。因此,就需要使用首部字段 Host 來明確指出請求的主機名。若服務器未設定主機名,那直接發送一個空值即可。

轉載于:https://www.cnblogs.com/dongye95/p/10056271.html

總結

以上是生活随笔為你收集整理的《图解HTTP》摘录的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。