1. HTTP介紹
- HTTP是
Hyper Text Transfer Protocol
的縮寫,即超文本傳輸協議。它是一種請求/響應式的協議,客戶端在與服務器端建立連接后,就可以向服務器端發送請求,這種請求被稱作HTTP請求,服務器端接收到請求后會做出響應,稱為HTTP響應,客戶端與服務器端在HTTP 下的交互過程如圖3-1所示。
- 從圖3-1中可以清楚地看到客戶端與服務端使用HTTP通信的過程,接下來總結一下HTTP協議的特點,具體如下。
(1) 支持客戶端(瀏覽器就是一種 Web客戶端)/服務器模式。
(2) 簡單快速:客戶端向服務器請求服務時,只需傳送請求方式和路徑。常用的請求方式有GET、POST等,每種方式規定了客戶端與服務器聯系的類型不同。由於 HTTP簡單,使得HTTP服務器的程序規模小,因而通信速度很快。
(3) 靈活:HTTP 允許傳輸任意類型的數據,正在傳輸的數據類型由Content-Type
加以標記。
(4) 無狀態:HTTP是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力,如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。
2. HTTP 1.0 和 HTTP 1.1
- HTTP自誕生以來,先后經歷了很多版本,其中,最早的版本是 HTTP 0.9,它1990年被提出。后來,為了進一步完善HTTP,先后在1996年提出了版本1.0,在1997年提出了版本1.1。由於HTTP 0.9版本已經過時,這里不作過多講解。接下來,只針對HTTP 1.0和 HTTP 1.1進行詳細地講解。
2.1 HTTP 1.0
- 基於HTTP1.0協議的客戶端與服務器在交互過程中需要經過建立連接、發送請求信息、回送響應信息、關閉連接4個步驟,具體交互過程如圖3-2所示。
- 從圖3-2中可以看出,客戶端與服務器建立連接后,每次只能處理一個 HTTP請求。對於內容豐富的網頁來說,這樣的通信方式明顯有缺陷。例如,下面的一段HTML代碼:
<html>
<body>
<img src="/image01.jpg">
<img src="/image02.jpg">
<img src="/image03.jpg">
</body>
</html>
- 上面的 HTML文檔中包含三個
<img>
標記,由於<img>
標記的src
屬性指明的是圖片的URL
地址,因此,當客戶端訪問這些圖片時,還需要發送三次請求,並且每次請求都需要與服務器重新建立連接。如此一來,必然導致客戶端與服務器端交互耗時,影響網頁的訪問速度。
2.2 HTTP 1.1
- 為了克服上述HTTP 1.0的缺陷,HTTP1.1版本應運而生,它支持持久連接,也就是說在一個 TCP 連接上可以傳送多個 HTTP 請求和響應,從而減少了建立和關閉連接的消耗和延時。基於 HTTP 1.1的客戶端和服務器端的交互過程,如圖3-3所示。
- 從圖3-3中可以看出,當客戶端與服務器端建立連接后,客戶端可以向服務器端發送多個請求,並且在發送下個請求時,無須等待上次請求的返回結果。但服務器必須按照接受客戶端請求的先后順序依次返回響應結果,以保證客戶端能夠區分出每次請求的響應內容。由此可見,HTTP 1.1不僅繼承了HTTP 1.0的優點,而且有效解決了HTTP 1.0的性能問題,顯著地減少了瀏覽器與服務器交互所需要的時間。
3. HTTP消息
- 當用戶在瀏覽器中訪問某個
URL
地址,單擊網頁的某個超鏈接或者提交網頁上的form
表單時,瀏覽器都會向服務器發送請求數據,即HTTP請求消息
。服務器接收到請求數據后,會將處理后的數據回送給客戶端,即HTTP 響應消息
。HTTP請求消息和HTTP響應消息統稱為HTTP消息。 - 在HTTP消息中,除了服務器端的
響應實體內容(HTML 網頁、圖片等)
以外,其他信息對用戶都是不可見的,要想觀察這些“隱藏”的信息,需要借助一些網絡查看工具,如:F12等。
(1) 在瀏覽器的地址欄中輸入 www.baidu.com
訪問百度首頁,在F12中可以看到請求的 URL地址,如圖所示。
(2) 單擊URL地址左邊的Name,在展開的默認頭信息選項卡中可以看到格式化后的響應頭信息和請求頭信息。單擊請求頭信息一欄左邊的“原始頭信息”,可以看到原始的請求頭信息,具體如下所示;
- 在上述請求消息中,第一行為請求行,請求行后面的為請求頭消息,空行代表請求頭的結束。
(3) 單擊響應頭信息一欄左邊的“原始頭信息”,可以看到原始的響應頭信息,如下所示:
- 在上面的響應消息中,第一行為響應狀態行,響應狀態行后面的為響應消息頭,空行代表響應消息頭的結束。
4. HTTP請求消息
- 在 HTTP中,一個完整的請求消息是由請求行、請求頭和實體內容三部分組成,其中,每部分都有各自不同的作用。本節將圍繞HTTP請求消息的每個組成部分進行詳細的講解。
4.1 HTTP請求行
- HTTP請求行位於請求消息的第一行,它包括三個部分,分別是請求方式、資源路名以及所使用的HTTP版本,具體示例如下:
GET /index.html HTTP/1.1
- 上面的示例就是一個HTTP請求行,其中,
GET
是請求方式,index.html
是請求源路徑,HTTP/1.1
是通信使用的協議版本。需要注意的是,請求行中的每個部分需要用空格分隔,最后要以回車換行結束。 - 關於請求資源和協議版本,讀者都比較容易理解,而 HTTP請求方式對讀者來說比較陌生,接下來就針對HTTP的請求方式進行具體分析。
- 在 HTTP的請求消息中,請求方式有
GET,POST、 HEAD、OPTIONS、 DELETE,TRACE、PUT和 CONNECT
共8種,每種方式都指明了操作服務器中指定URI
資源的方式,它們表示的含義如表3-1所示。
- 表3-1中列舉了HTTP的8種請求方式,其中最常用的就是
GET
和POST
方式,接下來,針對這兩種請求方式進行詳細講解,具體如下所示。
1. GET 請求方式
- 當用戶在瀏覽器地址欄中直接輸入某個
URL
地址或者單擊網頁上的一個超鏈接時,瀏覽器將使用GET
方式發送請求。如果將網頁上的form
表單的method
屬性設置為“GET
”或者不設置method
屬性(默認值是GET
),當用戶提交表單時,瀏覽器也將使用GET
方式發送請求。 - 如果瀏覽器請求的
URL
中有參數部分,在瀏覽器生成的請求消息中,參數部分將附加在請求行中的資源路徑后面。先來看一個URL
地址,具體如下,
http://wwrw.xdr630.com/javaForm?username=xdr630&password=123456
- 在上述
URL
中,“?
”后面的內容為參數信息。參數是由參數名和參數值組成的,並且中間使用等號(=
)進行連接。需要注意的是,如果URL地址中有多個參數,參數之間需要用“&
”分隔。 - 當瀏覽器向服務器發送請求消息時,上述
URL
中的參數部分會附加在要訪問的URI
咨源后面.具體加下所示,
GET /javaForm?username=xdr630&password=123456 HTTP/1.1
- 需要注意的是,使用
GET
方式傳送的數據量有限,最多不能超過1KB
.
2. POST 請求方式
- 如果網頁上
form
表單的method
屬性設置為“POST
”,當用戶提交表單時,瀏覽器將使用POST
方式提交表單內容,並把各個表單元素及數據作為HTTP消息的實體內容發送給服務器,而不是作為URI
地址的參數傳遞。另外,在使用POST
方式向服務器傳遞數據時,Content-Type
消息頭會自動設為“application/x-www-form-urlencoded
”,Content-Length
消息頭會自動設置為實體內容的長度,具體示例如下:
POST /javaForm HTTP/1.1
Host: www.xdr630.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
username=xdr630&password=123456
- 對於使用
POST
方式傳遞的請求信息,服務器端程序會采用與獲取URI
后面參數相同的方式來獲取表單各個字段的數據。 - 需要注意的是,在實際開發中,通常都會使用
POST
方式發送請求,其原因主要有兩個,具體如下。
POST
傳輸數據大小無限制
由於GET
請求方式是通過請求參數傳遞數據的,因此最多可傳遞1KB
的數據。而POST
請求方式是通過實體內容傳遞數據的,因此可以傳遞數據的大小沒有限制POST
比GET
請求方式更安全
由於GET
請求方式的參數信息都會在URL
地址欄明文顯示,而POST
請求方式傳遞的參數隱藏在實體內容中,用戶是看不到的,因此,POST
比GET
請求方式更安全。
5. 測試GET請求方式
(1) 創建一個HTML文件,GET.html
,如下所示:
GET.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="get">
用戶名:<input type="text" name="username" style="width: 150px"><br>
密碼: <input type="text" name="password" style="width: 150px"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
-
提交后:這時地址欄中的URL地址發生了變化,在原有的URL地址后面附加上了參數信息
-
查看顯示的請求頭信息,發現在請求行的URL請求資源后附加了參數信息,如圖
-
而在Query String Parameters
6. 測試POST請求方式
POST.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
用戶名:<input type="text" name="username" style="width: 150px"><br>
密碼: <input type="text" name="password" style="width: 150px"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
- 提交后,URL地址欄沒有變化。F12查看發現請求的參數被加密了
- F12查看,發現在請求消息中多了兩個請求消息頭
- 新添加的兩個消息頭中,
Content-Type
表示實體內容的數據格式,Content-Length
表示實體的內容長度。 - F12 中看到 Form Data 就是提交的表單信息,也就是HTTP請求消息的實體內容,也就是說,在POST請求方式中,表單的內容將作為實體內容提交給服務器。
7. HTTP請求消息頭
- 在HTTP請求消息中,請求行之后,便是若干請求消息頭。請求消息頭主要用於向服務器端傳遞附加消息,例如,客戶端可以接收的數據類型、壓縮方法、語言以及發送請求的超鏈接所屬頁面的URL地址等信息,具體示例如下:
- 從上面的請求消息頭中可以看出,每個請求消息頭都是由一個頭字段名稱和一個值構成,頭字段名稱和值之間用冒號(
:
)和空格()
分隔,每個請求消息頭之后使用一個回車換行符標志結束。需要注意的是,頭字段名稱不區分大小寫,但習慣上將單詞的第一個字母大寫。 - 當瀏覽器發送請求給服務器時,根據功能需求的不同,發送的請求消息頭也不相同,接下來,針對一些常用的請求頭字段進行詳細講解。
1. Accept
- Accept頭字段用於指出客戶端程序(通常是瀏覽器)能夠處理的
MIME(Multi-purpose Internet Mail Extensions,多用途互聯網郵件擴展)
類型。例如如果瀏覽器和服
務器同時支持png
類型的圖片,則瀏覽器可以發送包含image/png
的Accept頭字段,服務器檢查到Accept頭中包含image/png
這種MIME
類型,可能在網頁中的img
元素中使用png
類型的文件。MIME
類型有很多種,例如,下面的這些 MIME類型都可以作為Accept頭字段的值。
2. Accept-Charset
- Accept-Charset 頭字段用於告知服務器端客戶端所使用的字符集,具體示例如下:
Accept-Charset: ISO-8859-1
- 在上面的請求頭中,指出客戶端服務器使用
ISO-8859-1
字符集。如果想指定多種字符集,則可以在Accept-Charset
頭字段中將指定的多個字符集以逗號分隔,具體示例如下:
Accept-Charset: ISO-8859-1,unicode-1-1
- 需要注意的是,如果
Accept-Charset
頭字段沒有在請求頭中出現,則說明客戶端能接受使用任何字符集的數據。 - 如果Accept-Charset頭出現在請求消息里,但是服務器不能發送采用客戶端期望字符集編碼的文檔,那么服務器將發送一個
406
錯誤狀態響應,406
是一個響應狀態碼,表示服務器返回內容使用的字符集與Accept-Charset
頭字段指定的值不兼容,關於狀態碼的相關知識,將在后面的章節進行詳細講解。
3. Accept-Encoding
- Accept-Encoding頭字段用於指定客戶端能夠進行解碼的數據編碼方式,這里的編碼方式通常指的是某種壓縮方式。在 Accept-Encoding頭字段中,可以指定多個數據編碼方式,它們之間以逗號分隔,具體示例如下:
Accept-Encoding: gzip,compress
- 在上面的頭字段中,
gzip
和compress
這兩種格式是最常見的數據編碼方式。在傳輸較大的實體內容之前,對其進行壓縮編碼,可以節省網絡帶寬和傳輸時間。服務器接收到這個請求頭,它使用其中指定的一種格式對原始文檔內容進行壓縮編碼,然后再將其作為響應消息的實體內容發送給客戶端,並且在Content-Encoding
響應頭中指出實體內容所使用的壓縮編碼格式。瀏覽器在接收到這樣的實體內容之后,需要對其進行反向解壓縮。 - 需要注意的是,
Accept-Encoding
和Accept
消息頭不同,Accept
請求頭指定的MIME
類型是指解壓后的實體內容類型,Accept-Encoding
消息頭指定的是實體內容壓縮的方式。
4. Accept-Language
- Accept-Language頭字段用於指定客戶端期望服務器返回哪個國家語言的文檔,它的值可以指定多個國家的語言,語言之間用逗號分隔,具體示例如下:
Accept-Language: zh-CN,en-us
- 在上述示例中,
zh-cn
代表中文(中國),en-us
代表英語(美國),這些值不需要記憶。 - 需要注意的是,瀏覽器會根據“語言首選項”對話框中語言列表的先后順序,生成相應的Accept-Language消息頭。
- 服務器只要檢查Accept-Language請求頭中的信息,按照其中設置的國家語言的先后順序,首先選擇返回位於前面的國家語言的網頁文檔,如果不能返回,則依次返回后面的國家語言的網頁文檔。
5. Authorization(授權)與Proxy-Authorization
- 當客戶端訪問受口令保護的網頁時, Web服務器會發送401響應狀態碼和
WWW-Authenticate
響應頭,要求客戶端使用Authorization
請求頭來應答。根據WWW-Authenticate
響應頭指定的認證方式不同,Authorization
請求頭中的內容格式也不一樣。WWW-Authenticate
響應頭指定的認證方式有兩種:BASIC
和DIGEST
。對於BASIC
認證方式,客戶端需要把用戶名和密碼用“:”分隔,然后經過Base64
編碼之后傳送給Web服務器。 - 例如,將用戶名為
Ann
、密碼為666888
的用戶信息“Ann:666888
”進行Base64
編碼,形成的Authorization
請求頭字段內容如下所示:
Authorization: Basic Qw5uOjY2Njg4OA==
- 然而,使用
Base64
編碼的數據很容易被解碼,這實際上相當於是一種未加密的明文傳送方式,裝備了網絡監視工具的計算機截獲到該信息后,很容易破解出用戶名和密碼。 - 如果使用
DIGEST
認證方式,服務器首先向瀏覽器發送一些用於驗證過程的信息及附加信息,瀏覽器將這些信息與用戶名和密碼以及某些其他信息進行混合后,再執行MD5
加密算法,將得到的結果和附加信息一起以明文文本通過網絡發送給服務器。服務器也使用與客戶端一樣的信息和附加信息,將它們和所保存的客戶端密碼執行散列算法,然后將計算結果和客戶端的結果進行比較,只有這兩個數字完全相同才允許訪問。 Proxy-Authorization
頭字段的作用和用法與Authorization
頭字段基本相同,只不過Proxy-Authorization
請求頭是服務器端向代理服務器發送的驗證信息。
6. Host
- Host頭字段用於指定資源所在的主機名和端口號,格式與資源的完整URL中的主機名和端口號部分相同,具體示例如下所示:
Host: www.xdr630.top
- 在上述示例中,由於瀏覽器連接服務器時默認使用的端口號為80,所以“www.xdr630.top”后面的端口號信息“:80”可以省略。
- 需要注意的是,在HTTP 1.1中,瀏覽器和其他客戶端發送的每個請求包含Host請求頭子段,以便訪問Web站點時,會根據地址欄中的URL地端所要訪問的虛擬Web站點。當瀏覽器訪問Web站點時,會根據地址欄中的URL地址自動生成相應的Host請求頭。
7. If-Match
- 瀏覽器和代理服務器都可以緩存服務器回送的網頁文檔。當用戶再次訪問已緩存的頁面時,只有網頁內容已被更新,服務器才需要把該頁面的內容重新回送到客戶端,否則會通知瀏覽器訪問本地緩存的頁面,以減少不必要的網絡傳輸流量。當服務器為客戶端傳送網頁文件的內容時,可以傳輸一些代表實體內容特征的頭字段,這些頭字段被稱為實體標簽。當客戶機再次向服務器請求這個網頁文件時,可以使用If-Match頭字段附帶以前緩存的實體標簽內容,這個請求被視為一個條件請求,例如:
If-Match: "repository"
- 其中,"
repository
"是客戶端上次訪問Web服務器中的該頁面時,服務器使用ETag實體標簽傳送的內容,具體示例如下所示:
ETag: "repository"
- 服務器收到客戶端的請求后,會檢索If-Match頭中的實體標簽內容,並與服務器端的代表當前網頁內容特征的實體標簽內容進行比較。如果兩者相同,則表示網頁內容沒有更改,Web服務器不返回網頁文檔,讓客戶端仍然使用以前緩存的網頁文檔。否則,服務器返回新的網頁文件和新的實體標簽內容頭字段。
8. If-Modified-Since
- If-Modified-Since請求頭的作用和 If-Mach類似,只不過它的值為GMT格式的時間。If-Modified-Since請求頭被視作一個請求條件,只有服務器中文檔的修改時間比IF-Modified-Since請求頭指定的時間新,服務器才會返回文檔內容。否則,服務器將返回一個304(Not Modified)狀態碼來表示瀏覽器緩存的文檔是最新的,而不向瀏覽器返回文檔內容,這時,瀏覽器仍然使用以前緩存的文檔。通過這種方式,可以在一定程度上減少瀏覽器與服務器之間的通信數據量,從而提高了通信效率。
9. Range和If-Range
- Range頭字段用於指定服務器只需返回文檔中的部分內容及內容范圍,這對較大文檔的斷點續傳非常有用。如果客戶端在一次請求中只接收到服務器返回的部分內容就中斷了,可以在第二次請求中,使用 Range頭字段要求服務器只返回中斷位置以后的內容。Range頭有以下幾種使用格式。
(1)Range: bytes=1000-2000
(2) Range: bytes=1000-
(3) Range:bytes=-1000 - 在上面列舉的三種格式中,第一種格式請求服務器返回文檔中的第1000~2000個字節之間的內容,包括第1000個和第2000個字節的內容。第二種格式請求服務器返回文檔中的第1000個字節以后的所有內容。第三種格式請求服務器返回文檔中的最后1000個字節的內容。
- If-Range頭字段只能伴隨着Range頭字段一起使用,其設置值可以是實體標簽或GMT格式的時間。如果設置值為實體標簽,且該標簽內容與服務器端代表當前網頁內容特征的實體標簽內容相同,則服務器按Range頭的要求返回網頁中的部分內容,否則,服務器返回當前網頁的所有內容。如果設置值為GMT格式的時間,並且自從這個時間以來,服務器上保存的該網頁文件沒有發生修改,服務器會按Range頭的要求返回網頁中的部分內容,否則,服務器返回當前網頁的所有內容。
10. Max-Forward
- Max-Forward頭字段指定當前請求可以途經的代理服務器數量,每經過一個代理服務器,此數值就減1。當Max-Forward請求頭的值為0時,如果請求還沒有到達最終的Web服務器,那么代理服務器將終止轉發這個請求,由它來完成對客戶機的最終響應。
11. Referer
- 瀏覽器向服務器發出的請求,可能是直接在瀏覽器中輸入 URL地址而發出,也可能是單擊一個網頁上的超鏈接而發出。對於第一種直接在瀏覽器地址欄中輸入 URL地址的情況,瀏覽器不會發送 Referer請求頭,而對於第二種情況,瀏覽器會使用Referer頭字段標識發出請求的超鏈接所在網頁的URL。例如,本地Tomcat服務器的 chapter03項目中有一個 HTML文件 GET.html,GET.html中包含一個指向遠程服務器的超鏈接,當單擊這個超鏈接向服務器發送GET請求時,瀏覽器會在發送的請求消息中包含Referer頭空段.如下所示.
Referer: http://localhost:8080/Test01/GET.html
- Referer頭字段非常有用,常被網站管理人員用來追蹤網站的訪問者是如何導航進入網站的。同時,Referer頭字段還可以用於網站的防盜鏈。有R提太機,版什么是盜鏈呢?假設一個網站的首頁中想顯示一些圖片信息,而在該網站的服務器中並沒有這些圖片資源,它通過在 HTML 文件中使用img標記鏈接到其他網站的圖片資源,將其展示給瀏覽者,這就是盜鏈。盜鏈的網站提高了自己網站的訪問量,卻加重了被鏈接網站服務器的負擔,損害了其合法利益。所以,一個網站為了保護自己的資源,可以通過Referer頭檢測出從哪里鏈接到當前的網頁或資源,一旦檢測到不是通過本站的鏈接進行的訪問,可以進行阻止訪問或者跳轉到指定的頁面。
12. User-Agent
- User-Agent中文名為用戶代理;簡稱
UA
,它用於指定瀏覽器或者其他客戶端程序使用的操作系統及版本、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語言等,以便服務器針對不同類型的瀏覽器而返回不同的內容。例如,服務器可以通過檢查User-Agent
頭,如果發現客戶端是一個無線手持終端,就返回一個WML文檔;如果客戶端是一個普通的瀏覽器,則返回通常HTML文檔。例如,IE瀏覽器生成的User-Agent請求信息如下:
User-Agent: Mozilla/4.0(compatible;MSIE 8.0; Windows NT 5.1: Trident/4.0)
- 在上面的請求頭中,User-Agent頭字段首先列出了Mozilla版本,然后列出了瀏覽器的版本(MSIE 8.0表示 Microsoft IE 8.0)、操作系統的版本(Windows NT 5.1表示Windows XP)以及瀏覽器的引擎名稱(Trident/4.0)。
8. HTTP 響應消息
- 當服務器收到瀏覽器的請求后,會回送響應消息給客戶端。一個完整的響應消息主要包括響應狀態行、響應消息頭和實體內容,其中,每個組成部分都代表了不同的含義,本節將圍繞HTTP響應消息的每個組成部分進行詳細的講解。
1. HTTP響應狀態行
- HTTP響應狀態行位於響應消息的第一行,它包括三個部分,分別是 HTTP版本一個表示成功或錯誤的整數代碼(狀態碼)和對狀態碼進行描述的文本信息,具體示例如下:
HTTP/1.1 200 OK
- 上面的示例就是一個 HTTP 響應消息的狀態行,其中 HTTP 1.1是通信使用的協議版本(200是狀態碼),OK是狀態描述,說明客戶端請求成功。需要注意的是,請求行中的每個部分需要用空格分隔,最后要以回車換行結束。
- 狀態代碼由三位數字組成,表示請求是否被理解或被滿足。HTTP響應狀態碼的第一個數字定義了響應的類別,后面兩位沒有具體的分類,第一個數字有5種可能的取值,具體介紹如下所示。
1xx
:表示請求已接收,需要繼續處理。監嘩斯分認工源店,價出戰條細出網此額海2xx
:表示請求已成功被服務器接收、理解並接受。3xx
:為完成請求,客戶端需進一步細化請求。4xx
:客戶端的請求有錯誤。5xx
:服務器端出現錯誤。
- 下面通過表3-2~表3-6對 HTTP 1.1協議版本下的5種類別的狀態碼、狀態信息(每個狀態碼后面小括號中的內容就是狀態信息)及其作用分別進行說明。
- 表3-2~表3-6列舉了HTTP的大多數狀態碼,這些狀態碼無須記憶。接下來列舉幾個Web開發中比較常見的狀態碼,具體如下。
(1)200
:表示服務器成功處理了客戶端的請求。
(2)302
:表示請求的資源臨時從不同的URI響應請求,但請求者應繼續使用原有位置來進行以后的請求。例如,在請求重定向中,臨時 URI應該是響應的Location頭字段所指向的資源。
(3)404
;表示服務器找不到請求的資源。例如,訪問服務器不存在的網頁經常返回此狀態碼。
(4)500
:表示服務器發生錯誤,無法處理客戶端的請求。
2. HTTP 響應消息頭
- 在HTTP響應消息中,第一行為響應狀態行,緊接着的是若干響應消息頭,服務器端通過響應消息頭向客戶端傳遞附加信息,包括服務程序名、被請求資源需要的認證方式,客戶端請求資源的最后修改時間、重定向地址等信息。HTTP響應消息頭的具體示例如下所示:
- 從上面的響應消息頭可以看出,它們的格式和 HTTP請求消息頭的格式相同。當服務器向客戶端回送響應消息時,根據情況的不同,發送的響應消息頭也不相同。接下來,針對―些常用的響應消息頭字段進行詳細講解。
1. Accept-Range
- Accept-Range頭字段用於說明服務器是否接收客戶端使用
Range
請求頭字段請求資源。如果服務器想告訴客戶機不要使用Range頭字段,則使用下面的頭信息
Accept-Range: none
- 如果服務器想告訴客戶端可以使用以
bytes
為單位的Range請求,則應該使用下面的頭信息:
2. Age
- Age頭字段用於指出當前網頁文檔可以在客戶端或代理服務器中緩存的有效時間,設置值為一個以秒為單位的時間數,具體示例如下所示:
Age: 1234567
- 客戶端再次訪問已緩存的某個網頁文檔內容時,先用當前的時間值減去服務器返回該網頁時所設置的Date頭字段值,如果結果值小於服務器上返回該網頁時所設置的Age頭字段的時間值,客戶端直接使用緩存中的網頁內容。否則,客戶端將向服務器發出針對該頁面的網頁請求。
3. Etag
- Etag頭字段用於向客戶端傳送代表實體內容特征的標記信息,這些標記信息稱為實體標簽,每個版本的資源的實體標簽是不同的,通過實體標簽可以判斷在不同時間獲得的同一資源路徑下的實體內容是否相同。例如,在一個文檔最后添加一個回車換行,Etag頭字段的值就能標識出不同。Etag頭字段的格式如下所示:
Etag: abc1234
4. Location
- Location頭字段用於通知客戶端獲取請求文檔的新地址,其值為一個使用絕對路徑的URL地址,如下所示;
Location: http://www.xdr630.top
- Location頭字段和大多數
3xx
狀態碼配合使用,以便通知客戶端自動重新連接到新的地址請求文檔。由於當前響應並沒有直接返回內容給客戶端,所以使用 Location頭的HTTP消息不應該有實體內容,由此可見,在HTTP消息頭中不能同時出現Location
和Content-Type
這兩個頭空段
5. Retry-After
- Retry-After頭字段可以與503狀態碼配合使用,告訴客戶端在什么時間可以重新發送請求。也可以與任何一個3xx狀態碼配合使用,告訴客戶端處理重定向的最小延時時間。Retry-After頭字段的值可以是GMT格式的時間,也可是一個以秒為單位的時間數,具體示例如下:
Retry-After: Sun, 21 Mar 2021 10:00:00
GMTRetry-After: 120 //120秒
6. Server
- Server頭字段用於指定服務器軟件產品的名稱,具體示例如下:
Server: Apache- Coyote/1.1
7. Vary
- Vary用於指定影響了服務器所生成的響應內容的那些請求頭字段名,具體示例如下:
Vary: Accept-Language
- 上面的響應頭字段說明了服務器響應的內容受到了客戶端發送的Accept-Language請求頭的影響,服務器根據Accept-Language請求頭的值,返回相應語言種類的網頁內容。當客戶端再次訪問已經緩存的資源時,需要檢查Vary頭字段中指定的請求頭字段,檢查請求頭字段的這次設置與上次的設置是否相同,以此作為是否使用緩存的條件。-例如,上次的請求中Accept-Language頭字段的值為en-us,而這次的 Accept-Language頭字段的值為zh-cn,即使客戶端使用請求資源路徑的本地緩存的其他條件都成立,但客戶端也不能使用緩存,它仍需向服務器發出訪問請求。
8. WWW-Authenticate和Proxy-Authenticate
- 當客戶端訪問受口令保護的網頁文件時,服務器會在響應消息中回送401(Unauthrized)響應狀態碼和WWW-Authoricate響應頭,指示客戶端應該在Author-ization請求頭中使用WWW-Authoricate響應頭指定的認證方式提供用戶名和密碼信息。WWW-Authenticate響應頭中可以指定兩種認證方式:
BASIC
和DIGEST
。如果要求客戶端采用 BASIC方式傳送認證信息,語法格式如下:
WWW-Authenticate: BASIC realm= "xdr630"
- 其中, realm屬性用於指定當前資源所屬的域,域定義了同一個主機內的一個受保護區間(一組需要保護的資源),它可以是任意字符串。同一台主機上可以有多個域,相同的域內所有的資源都共享相同的賬戶。如果某個賬戶具有訪問某個資源的權限,那么該賬戶就能訪問同一個域中的其他資源。根據HTTP驗證的規范,與某一資源具有相同的目錄路徑或位於其目錄路徑的子目錄中的資源,與該資源使用相同的域。
- DIGEST認證方式細節比較復雜,想對其進行深入研究的讀者可以參閱 RFC2617文檔。
- Proxy-Authenticate頭字段是針對代理服務器的用戶信息驗證,其他的作用與用法與 WWW-Authenticate頭字段類似。
9. Refresh
- Refresh頭字段用於告訴瀏覽器自動刷新頁面的時間,它的值是一個以秒為單位的時間數,具體示例如下所示:
Refresh:3
- 上面所示的Refresh頭字段用於告訴瀏覽器在3秒后自動刷新此頁面。
- 需要注意的是,在 Refresh頭字段的時間值后面還可以增加一個URL參數,時間值與URL之間用分號(﹔)分隔,用於告訴瀏覽器在指定的時間值后跳轉到其他網頁,例如告訴瀏覽器經過3秒跳轉到www.xdr630.top網站,具體示例如下:
Refresh:3; url=http://www.xdr630.top
10. Content-Disposition
- 如果服務器希望瀏覽器不是直接處理響應的實體內容,而是讓用戶選擇將響應的實體內容保存到一個文件中,這需要使用Content-Disposition頭字段。Content-Disposition頭字段沒有在 HTTP的標准規范中定義,它是從 RFC 2183中借鑒過來的。在RFC 2183中,Content-Disposition指定了接收程序處理數據內容的方式,有inline和attachment兩種標准方式, inline表示直接處理,而attachment則要求用戶干預並控制接收程序處理數據內容的方式。而在 HTTP應用中,只有attachment是 Content-Disposition的標准方式。attachment后面還可以指定filename參數。filename參數值是服務器建議瀏覽器保存實體內容的文件名稱,瀏覽器應該忽略filename參數值中的目錄部分,只取參數中的最后部分作為文件名。在設置Content-Disposition之前,一定要設置Content-Type頭字段,具體示例如下.
Content-Type: application/octet-stream
Content- Disposition: attachment; filename=lee.zip
3. HTTP其他頭字段
1. 通用頭字段
- 在 HTTP消息中,有些頭字段既適用於請求消息也適用於響應消息,這樣的字段被稱為通用頭字段。通用頭字段有如下幾種:Cache-Control、 Connection、Date, Pragma,Trailer、 Transfer-Encoding,Upgrade、 Via, Warning,關於這些通用頭字段的相關講解具體如下。
1. Cache-Control
- 如果Cache-Control用在請求消息中,它用於通知位於客戶端和服務器端之間的理服務器如何使用已緩存的頁面。在這種情況下,Cache-Control的值可以是:no-cache、no-store、max-age , max-stale、 min-fresh 、no-transform,only-if-cached等。
- 如果Cache-Control用在響應消息中,它用於通知客戶端和代理服務器如何緩存頁面,在這種情況下,Cache-Control 的取值可以為public、 private , no-cache、no-store、no-transform,must-revalidate、proxy-revalidate 、 max-age,s-max-age等。
- 在一個Cache-Control頭字段中可以設置多個值,它們之間用過號分隔,具體示例如下:
Cache-Control: no- stroe,no-cache,must-revalidage
- 在上面的Cache-Control頭字段中,設置的每個值都有特定的含義,接下來,通過表3-7對Cache-Control頭字段的一些常用值進行介紹說明。
2. Connection
- Connection頭字段用於指定處理完本次請求/響應后,客戶端和服務器端是否還要繼續保持連接。Connection頭字段可以指定兩個值,如下所示:罐必監中來都鼓
Connection: Keep-Alive
Connection: close
- 當Connection頭字段的值為Keep-Alive時,客戶端與服務器在完成本次交互后繼續保持連接,當Connection頭字段的值為close 時,客戶端與服務器在完成本次交互后關閉連接。對於HTTP1.1版本來說,默認采用持久連接,也就是說默認情況下,Connection頭字段的值為Keep- Alive.
3. Data
- Date頭字段用於表示 HTTP消息產生的當前時間,它的值為GMT格式,具體示例如下:
Mon, 22 Feb 2021 08:29:02 GMT
- 一般情況下,服務器返回的所有響應中必須包括一個 Date頭字段.除了下而這此情況。
- 響應狀態代碼表示服務器的錯誤,如500(內部服務器錯誤)或503(服務不可用),那么服務器就不可能產生一個有效的日期。
- 服務器沒有時鍾,不能提供當前時間,響應就不能設置Date頭,這種情況下,服務器也不能設置如 Expire、Last-Modified等這樣的頭字段。
4. Pragma
- Pragma頭字段主要在HTTP 1.0中通知代理服務器和客戶端如何使用緩存頁面,它的值只能固定設置為no-cache,如下所示:
Pragma: no-cache
- 當Pragma頭字段用於響應消息時,指示客戶端不要緩存文檔;當用於請求消息時,指示代理服務器必須返回一個最新的文檔,而不能返回緩存的文檔。在HTTP 1.0中,一些瀏覽器對Pragma頭字段的支持不是非常可靠,因此,人們常常通過設置Expires頭字段的值為0來實現同樣功能。
- 而在 HTTP 1.1中,
Cache-Control
頭字段也基本替代了Pragma
頭字段的使用。
5. Transfer-Encoding
- 對於HTTP 1.0協議,服務器端和客戶端不是持久化連接,當服務器端關閉了TCP連接,客戶端就知道響應的數據已經發送完畢。而對於HTTP 1.1來說,由於服務器端和客戶端保持持久連接,服務器端必須在響應消息中通過Content-Length頭字段通知客戶端響應數據的長度,客戶端才能知道數據何時傳輸完畢。然而,在服務器端,有些數據是動態生成的,服務器必須等到所有的內容都生成后才能准確地計算出響應數據的長度,也就是說只有當所有數據生成完畢后服務器端才能響應客戶端的請求,這樣勢必會影響效率。為了解決這個問題,Transfer-Encoding頭字段被引人,這個頭字段指定響應消息的實體內容采用哪種傳輸編碼方式,目前標准設置值只有chunked,具體示例如下:
Transfer-Encoding: chunked
- 當響應消息中設置了Transfer-Encoding頭字段后,會把響應消息的整個實體內容分成一連串分段后再進行傳輸。每個分段的開始都是一個十六進制的數字,用來表示整個分段的大小。最后一個分段必須是0,用於表示整個 chunked編碼數據的結束,如下所示:
HTTP/1.1 200 OK
Content-Type: text/htm1Transfer-Encoding: chunked
7f
<html>
<head>
<title>trailer Example</title>
</head>
<body>
<p> Please wait while we complete your transaction ...</p>
2c
<p>Transaction complete!</p>
</body>
</html>
0
- 上面的響應消息中,7f和2c代表兩個分段內容的大小標識信息,所以這種情況下不必用 Content-Length頭字段來指定整個實體內容的大小。
6. Trailer
- 一些頭字段可以放置在整個 HTTP消息的尾部,也就是可以在實體內容部分之后放置頭字段信息。對於放置在尾部的頭字段,需要在消息頭中使用Trailer字段說明,具體示例如下,
Trailer:Date
- 需要注意的是,Trailer頭字段必須在 chunked傳輸編碼的方式下使用。
7. Upgrade
- Upgrade頭字段用在客戶端,用於指定客戶端想要從當前協議切換的新的通信協議。如果服務器端認為切換的協議合適,會在響應消息中設置Upgrade頭字段指定切換的協議,Upgrade響應頭字段需要和101狀態碼配合使用,具體示例如下:
//請求消息
GET /HTTP/1.1
Host: 127.0.0.1
Upgrade: TLS/1.0
//響應消息
HTTP/1.1 101 Switching Protocols
Upgrade: TLS/1.0
8. Via
- Via頭字段用於指定HTTP 消息所途經的代理服務器所使用的協議和主機名稱,這個頭字段由代理服務器產生,每個代理服務器必須把它的信息追加到Via字段的最后,以反映 HTTP消息途經的多個代理服務器的順序,具體示例如下:
Via: HTTP/1.1 Proxy1,HTTP/1.1 Proxy2
- 如果代理服務器所使用的協議為HTTP,Via頭字段中的協議名稱可以省略,如下所示:
Via: 1.1 Proxy1,1.1 Proxy2
9. Warning
- Warning頭字段主要用於說明其他頭字段和狀態碼不能說明的一些附加警告信息,例如提示代理服務器斷開網絡,如下所示:
warning:112 Disconnected operation
2. 實體頭字段
- 請求消息和響應消息中都可以傳遞實體信息,實體信息包括實體頭字段和實體內容,實體頭字段是實體內容的元信息,描述了實體內容的屬性,例如實體內容的類型、長度、壓縮方法、最后的修改時間、數據的有效期等。接下來,本節將針對實體頭字段進行詳細的講解。
1. Allow
- Allow頭字段指定了請求資源所支持的請求方式(如 GET,POST等),用於通知客戶端應該嚴格按照指定的方式請求資源,如下所示:
Al1ow: GET,HEAD,PUT
- 需要注意的是,Allow頭字段必須和405響應狀態碼一起使用。
2. Content-Language
- Content-Language用於指定返回網頁文檔的國家語言類型,其設置值是zh-cn,en-us,ja等國家語言的標准名稱。由於同一個字符在不同的國家語言中的樣式和意義上能有略微區別,如果一些客戶端軟件正好要對字符文本按不同的國家語言進行不同處理時, Content-Language頭字段就比較重要了。Content-Language的具體示例如下所示:
Content-Language: en-us
3. Content-Length
- Content-Length頭字段用於表示實體內容的長度(字節數),首先來看一個帶有Content-Length頭字段的簡單的響應消息,具體如下所示:
HTTP/1.1 200 OK
Date: Mon, 22 Feb 2021 09:29:57 GMT
Content- Length:109
<html>
<head>
<title> content-Length Example</title>
</head>
<body>
Content-Length:109
</body>
</html>
- 在上面的響應消息中,從
<html>
中的第一個字符“<”到</hml>
中的最后一個字符“>”,內容的長度為109。 - 在 HTTP 1.1中,瀏覽器與服務器之間保持持久連接,服務器允許客戶端在一個TCP連接上發送多個請求,服務器必須在每個響應中發送一個 Content-Length響應頭來標識各個實體內容的長度,以便客戶端能分清每個響應內容的結束位置,而不會將上一個響應和下一個響應混淆。
- 如果響應消息中包含 Transfer-Encoding響應頭,也就是說響應內容以chunked編碼方式返回,那么,Content-Length響應頭就不應該設置了。
4. Content-Location
- Content-Location頭字段用於指定響應消息中實體內容的實際位置路徑(不能簡單地認為響應消息中的實體內容所在的路徑就是請求資源的路徑),當一個請求資源路徑對應有多種實體內容形式時,例如,同一請求資源可能有多個國家語言的版本,每個國家語言的版本都有自己的位置,在這種情況下,請求資源路徑與響應的實體內容所在的路徑可能是不同的,具體示例如下:
//請求消息
GET /docs/index.html HTTP/1.1
Host: httpd.apache.org
Accept- Language: en-us
//響應消息
HTTP/1.1 200 OK
Date: Mon, 22 Feb 2021 09:29:57 GMT
Server: Apache(UNIX)
Content-Location: index_en_us.html
Content-Type: text/html
Content-Language: en-us
- 在上面的示例中,請求消息中需要請求index. html文檔,而且要求是英文文檔,服務器中發現有可用的英文文檔index_en_us.html,就會在響應消息中將Content-Location消息頭的值設置為index_en_us. html文檔的路徑,並把該文檔回送給客戶端。
- Content-Location的設置值可以是絕對路徑,也可以是相對路徑,如果是相對路徑,則是相對請求資源路徑而言的,對於上面的響應消息來說, index, html和 index_en_us.html在同一目錄下。
5. Content-Range
- Content-Range頭字段用於指定服務器返回的部分實體內容的位置信息。只有客戶機使用了Range請求頭要求服務器返回實體的部分內容時,服務器的響應頭中才會包含Content-Range頭,具體示例如下所示:
HTTP/1.1 206 Partial content
Date: wed,15 Nov 1995 06:25:24 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-Range: bytes 21010-47021/47022
Content- Length:26012
Content-Type: image/gif
- 在Content-Range頭字段中, bytes說明后面的數據以byte為單位,21010~47021說明返回的內容從第21010個字節開始到第47021個字節結束,47022說明整個實體內容的大小為47022個字節,從 Content-Length頭字段可以看出返回的實體內容的長度為26012(47 021-21 010+1)個字節。
6. Content-MD5
- Content-MD5頭字段用於提供對實體內容的完整性檢查,它的值是對實體內容MD5 數字摘要后再進行 Base64編碼的結果。
- MD5 數字摘要算法是一種散列算法,能夠通過對一段信息進行運算,產生一個16個字節的數字摘要。如果對輸人信息做了任何形式的改變,對改變后的信息再次進行MD5運算所產生的數字摘要和改變之前的數字摘要都不相同。由於通過MD5算法計算的16個字節摘要信息可能無法轉化成可打印的 ASCII字符顯示,因此需要對這16個字節進行 Base64編碼,將其轉換為可打印的 ASCII字符。Content-MD5的頭字段如下所示:
Content-MD5: ZTFmZDA5MDYyYTMzZGQzMDMxMmixMjc4YThhNTMyM21=
7. Content-Type
- Content-Type用於指出實體內容的MIME類型。MIME(Multipurpose InternetMail Extensions,多用途互聯網郵件擴展類型)是一個互聯網標准,它設計之初是為了在發送電子郵件時附加多媒體數據,讓郵件客戶程序能根據其類型進行處理。由於通過HTTP傳輸的數據也有各種類型,因此,HTTP 也采用了MIME來標識不同的數據類型。客戶端通過檢查響應頭字段 Content-Type中的 MIME類型,就能知道接收到的實體內容代表哪種格式的數據類型,從而進行正確的處理。
- 大多數服務器會在配置文件中設置文件擴展名與MIME類型的映射關系,從而可以根據請求資源的擴展名自動確定 Content-Type的 MIME類型。在Tomcat的 web.xml文件中有大量的
元素,來實現文件擴展名和 MIME類型的映射,下面是web. xml文件的片段:
...
<mime-mapping>
<extension>pdf</extension>
<mime-type>application/pdf</mime-type>
</mime-mapping>
...
- 其中
<mime-mapping >
元素的<extension>
子元素用於指定文件的擴展名,<mime-type>
子元素用於指定該文件擴展名映射的 MIME類型。 - MIME類型包含主類型和子類型,兩者之間用“/”分隔,上面的文件片段中的 MIM類型“application/pdf”, application為主類型,pdf為子類型。MIME類型也可以使用“
*
”號通配符,“*/ *
”代表所有的MIME類型,"image/ *
”代表所有image的子類型如果子類型以“x-
”開頭,則表示該類型目前還處於實驗性的階段。Content-Type頭字段中的 MIME類型后面還可以指定響應內容所使用的字符碼表,兩者之間用分號(;)和空格隔開,如 Content-Type: text/html; charset=GB2312。如果Content-Type頭字段中沒有指定字符碼表,默認使用的是ISO-8859-1字符碼表。