Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
. HTTP請求格式
做過Socket編程的人都知道,當(dāng)我們設(shè)計一個通信協(xié)議時,“消息頭/消息體”的分割方式是很常用的,消息頭告訴對方這個消息是干什么的,消息體告訴對 方怎么干。HTTP協(xié)議傳輸?shù)南⒁彩沁@樣規(guī)定的,每一個HTTP包都分為HTTP頭和HTTP體兩部分,消息體是可選的,而消息頭是必須的。每當(dāng)我們打 開一個網(wǎng)頁,在上面點擊右鍵,選擇“查看源文件”,這時看到的HTML代碼就是HTTP的消息體,那么消息頭可以通過瀏覽器的開發(fā)工具或者插件可以看到, 如果火狐的Firebug,IE的Httpwatch。
客戶端通過發(fā)送 HTTP 請求向服務(wù)器請求對資源的訪問。 它向服務(wù)器傳遞了一個數(shù)據(jù)塊,也就是請求信息,HTTP 請求由三部分組成:請求行、 請求頭和請求正文。
請求行:請求方法 URI 協(xié)議/版本
請求頭(Request Header)
請求正文
下面是一個HTTP請求的數(shù)據(jù):
POST /index.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://localhost/
Content-Length:25
Content-Type:application/x-www-form-urlencoded
username=aa&password=1234
1、請求行:請求方法URI協(xié)議/版本
請求的第一行是“方法 URL 協(xié)議/版本”,并以 回車換行作為結(jié)尾。請求行以空格分隔。格式如下:
POST /index.php HTTP/1.1
以上代碼中“GET”代表請求方法,“//ndex.php”表示URI,“HTTP/1.1代表協(xié)議和協(xié)議的版本。
根據(jù)HTTP標(biāo)準(zhǔn),HTTP請求可以使用多種請求方法。例如:HTTP1.1支持7種請求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet應(yīng)用中,最常用的方法是GET和POST。
URL完整地指定了要訪問的網(wǎng)絡(luò)資源,通常只要給出相對于服務(wù)器的根目錄的相對目錄即可,因此總是以“/”開頭,最后,協(xié)議版本聲明了通信過程中使用HTTP的版本。
請求方法
在 HTTP 協(xié)議中,HTTP 請求可以使用多種請求方法,這些方法指明了要以何種方式來訪問 Request-URI 所標(biāo)識的資源。HTTP1.1 支持的請求方法如下表所示:
HTTP1.1 中的請求方式:
方法
作用
GET
請求獲取由 Request-URI 所標(biāo)識的資源
POST
請求服務(wù)器接收在請求中封裝的實體,并將其作為由 Request-Line 中的 Request-URI 所標(biāo)識的資源的一部分
HEAD
請求獲取由 Request-URI 所標(biāo)識的資源的響應(yīng)消息報頭
PUT
請求服務(wù)器存儲一個資源,并用 Request-URI 作為其標(biāo)識符
DELETE
請求服務(wù)器刪除由 Request-URI 所標(biāo)識的資源
TRACE
請求服務(wù)器回送到的請求信息,主要用于測試或診斷
CONNECT
保留將來使用
OPTIONS
請求查詢服務(wù)器的性能,或者查詢與資源相關(guān)的選項和需求
重點介紹 GET、POST 和 HEAD 三個方法:
(1)GET
GET 方法用于獲取由 Request-URI 所標(biāo)識的資源的信息,常見的形式是:
GET Request-URI HTTP/1.1
GET方法是默認(rèn)的HTTP請求方法,例如當(dāng)我們通過在瀏覽器的地址欄中直接輸入網(wǎng)址的方式去訪問網(wǎng)頁的時候,瀏覽器采用的就是 GET 方法向服務(wù)器獲取資源。
我們可以使用GET方法來提交表單數(shù)據(jù),用GET方法提交的表單數(shù)據(jù)只經(jīng)過了簡單的編碼,同時它將作為URL的一部分向服務(wù)器發(fā)送,因此,如果使用GET方法來提交表單數(shù)據(jù)就存在著安全隱患上。例如:
Http://localhost/login.php?username=aa&password=1234
從上面的URL請求中,很容易就可以辯認(rèn)出表單提交的內(nèi)容。(?之后的內(nèi)容)另外由于GET方法提交的數(shù)據(jù)是作為URL請求的一部分所以提交的數(shù)據(jù)量不能太大。這是因為瀏覽器對url的長度有限制
各種瀏覽器也會對url的長度有所限制,下面是幾種常見瀏覽器的url長度限制:(單位:字符)
IE : 2803
Firefox:65536
Chrome:8182
Safari:80000
Opera:190000
(2)POST
POST方法是GET方法的一個替代方法,它主要是向Web服務(wù)器提交表單數(shù)據(jù),尤其是大批量的數(shù)據(jù)。 在請求頭信息結(jié)束之后的兩個回車換行之后(實際是空一行),就是表單提交的數(shù)據(jù)。如上面提到的post表單數(shù)據(jù):
username=aa&password=1234
POST方法克服了GET方法的一些缺點。通過POST方法提交表單數(shù)據(jù)時,數(shù)據(jù)不是作為URL請求的一部分而是作為標(biāo)準(zhǔn)數(shù)據(jù)傳送給Web服務(wù)器,這就克 服了GET方法中的信息無法保密和數(shù)據(jù)量太小的缺點。因此,出于安全的考慮以及對用戶隱私的尊重,通常表單提交時采用POST方法。
從編程的角度來講,如果用戶通過GET方法提交數(shù)據(jù),則數(shù)據(jù)存放在QUERY_STRING環(huán)境變量中,而POST方法提交的數(shù)據(jù)則可以從標(biāo)準(zhǔn)輸入流中獲取。
GET與POST方法有以下區(qū)別:
1、 在客戶端,Get方式在通過URL提交數(shù)據(jù),數(shù)據(jù)在URL中可以看到;POST方式,數(shù)據(jù)放在HTTP包的body中。
2、 GET方式提交的數(shù)據(jù)大小有限制(因為瀏覽器對URL的長度有限制),而POST則沒有此限制。
3、安全性問題。正如在(1)中提到,使用 Get 的時候,參數(shù)會顯示在地址欄上,而 Post 不會。所以,如果這些數(shù)據(jù)是中文數(shù)據(jù)而且是非敏感數(shù)據(jù),那么使用 get;如果用戶輸入的數(shù)據(jù)不是中文字符而且包含敏感數(shù)據(jù),那么還是使用 post為好。
4.、服務(wù)器取值方式不一樣。GET方式取值,如php可以使用$_GET來取得變量的值,而POST方式通過$_POST來獲取變量的值。
(3)HEAD
HEAD 方法與 GET 方法幾乎是相同的,它們的區(qū)別在于 HEAD 方法只是請求消息報頭,而不是完整的內(nèi)容。對于 HEAD 請求的回應(yīng)部分來說,它的 HTTP 頭部中包含的信息與通過 GET 請求所得到的信息是相同的。利用這個方法,不必傳輸整個資源內(nèi)容,就可以得到 Request-URI 所標(biāo)識的資源的信息。這個方法通常被用于測試超鏈接的有效性,是否可以訪問,以及最近是否更新。
要注意的是,在 HTML 文檔中,書寫 get 和 post,大小寫都可以,但在 HTTP 協(xié)議中的 GET 和 POST 只能是大寫形式。
2. 請求頭
每個頭域由一個域名,冒號(:)和域值三部分組成。域名是大小寫無關(guān)的,域值前可以添加任何數(shù)量的空格符,頭域可以被擴(kuò)展為多行,在每行開始處,使用至少一個空格或制表符。
HTTP最常見的請求頭如下:
Transport 頭域
Connection:
作用:表示是否需要持久連接。
如果服務(wù)器看到這里的值為“Keep-Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認(rèn)進(jìn)行持久連接),它就可以利用持久連接的優(yōu)點,當(dāng)頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現(xiàn)這一點,服務(wù)器需要在應(yīng)答中發(fā)送一個Content-Length頭,最簡單的實現(xiàn)方法是:先把內(nèi)容寫入 ByteArrayOutputStream,然后在正式寫出內(nèi)容之前計算它的大小;
例如: Connection: keep-alive 當(dāng)一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉,如果客戶端再次訪問這個服務(wù)器上的 網(wǎng)頁,會繼續(xù)使用這一條已經(jīng)建立的連接
例如: Connection: close 代表一個Request完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接會關(guān)閉, 當(dāng)客戶端再次發(fā)送Request,需要重新建立TCP連接。
Host(發(fā)送請求時,該報頭域是必需的)
Host請求報頭域主要用于指定被請求資源的Internet主機(jī)和端口號,它通常從HTTP URL中提取出來的。
eg:http://;localhost/index.html
瀏覽器發(fā)送的請求消息中,就會包含Host請求報頭域,如下:
Host:localhost
此處使用缺省端口號80,若指定了端口號8080,則變成:Host:localhost:8080
Client 頭域
Accept:
作用:瀏覽器可以接受的媒體類型(MIME類型),
例如: Accept: text/html 代表瀏覽器可以接受服務(wù)器回發(fā)的類型為 text/html 也就是我們常說的html文檔, 如果服務(wù)器無法返回text/html類型的數(shù)據(jù),服務(wù)器應(yīng)該返回一個406錯誤(non acceptable)。
通配符 * 代表任意類型。例如 Accept: */* 代表瀏覽器可以處理所有類型,(一般瀏覽器發(fā)給服務(wù)器都是發(fā)這個)
Accept-Encoding:
作用: 瀏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支持壓縮,支持什么壓縮方法(gzip,deflate),(注意:這不是只字符編碼);
例如: Accept-Encoding: gzip, deflate。Server能夠向支持gzip/deflate的瀏覽器返回經(jīng)gzip或者deflate編碼的HTML頁面。 許多情形下這可以減少5到10倍的下載時間,也節(jié)省帶寬。
Accept-Language:
作用: 瀏覽器申明自己接收的語言。
語言跟字符集的區(qū)別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等;
例如: Accept-Language:zh-cn 。如果請求消息中沒有設(shè)置這個報頭域,服務(wù)器假定客戶端對各種語言都可以接受。
User-Agent:
作用:告訴HTTP服務(wù)器, 客戶端使用的操作系統(tǒng)和瀏覽器的名稱和版本.
我們上網(wǎng)登陸論壇的時候,往往會看到一些歡迎信息,其中列出了你的操作系統(tǒng)的名稱和版本,你所使用的瀏覽器的名稱和版本,這往往讓很多人感到很神 奇,實際上, 服務(wù)器應(yīng)用程序就是從User-Agent這個請求報頭域中獲取到這些信息User-Agent請求報頭域允許客戶端將它的操作系統(tǒng)、瀏覽 器和其它屬性告訴服務(wù)器。
例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)
Accept-Charset:
作用:瀏覽器申明自己接收的字符集,這就是本文前面介紹的各種字符集和字符編碼,如gb2312,utf-8(通常我們說Charset包括了相應(yīng)的字符編碼方案);
例如:Accept-Charset:iso-8859-1,gb2312.如果在請求消息中沒有設(shè)置這個域,缺省是任何字符集都可以接受。
Authorization:授權(quán)信息,通常出現(xiàn)在對服務(wù)器發(fā)送的WWW-Authenticate頭的應(yīng)答中;
Authorization請求報頭域主要用于證明客戶端有權(quán)查看某個資源。當(dāng)瀏覽器訪問一個頁面時,如果收到服務(wù)器的響應(yīng)代碼為401(未授權(quán)),可以發(fā)送一個包含Authorization請求報頭域的請求,要求服務(wù)器對其進(jìn)行驗證。
Cookie/Login 頭域
Cookie:
作用: 最重要的header, 將cookie的值發(fā)送給HTTP 服務(wù)器
Entity頭域
Content-Length
作用:發(fā)送給HTTP服務(wù)器數(shù)據(jù)的長度。即請求消息正文的長度;
例如: Content-Length: 38
Content-Type:
作用:
例如:Content-Type: application/x-www-form-urlencoded
Miscellaneous 頭域
Referer:
作用: 提供了Request的上下文信息的服務(wù)器,告訴服務(wù)器我是從哪個鏈接過來的,比如從我主頁上鏈接到一個朋友那里, 他的服務(wù)器就能夠從HTTP Referer中統(tǒng)計出每天有多少用戶點擊我主頁上的鏈接訪問 他的網(wǎng)站。
例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT
Cache 頭域
If-Modified-Since:
作用: 把瀏覽器端緩存頁面的最后修改時間發(fā)送到服務(wù)器去,服務(wù)器會把這個時間與服務(wù)器上實際文件的最后修改時間進(jìn)行對比。如果時間一致,那么返回304,客戶端 就直接使用本地緩存文件。如果時間不一致,就會返回200和新的文件內(nèi)容。客戶端接到之后,會丟棄舊文件,把新文件緩存起來,并顯示在瀏覽器中。
例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT。
If-None-Match:
作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 當(dāng)用戶再次請求該資源時,將在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服務(wù)器驗證資源的ETag沒有改變(該資源沒有更新),將返回一個304狀態(tài)告訴客戶端使用 本地緩存文件。否則將返回200狀態(tài)和新的資源和Etag. 使用這樣的機(jī)制將提高網(wǎng)站的性能
例如: If-None-Match: "03f2b33c0bfcc1:0"
Pragma:
作用: 防止頁面被緩存, 在HTTP/1.1版本中,它和Cache-Control:no-cache作用一模一樣
Pargma只有一個用法, 例如: Pragma: no-cache
注意: 在HTTP/1.0版本中,只實現(xiàn)了Pragema:no-cache, 沒有實現(xiàn)Cache-Control
Cache-Control:
作用: 這個是非常重要的規(guī)則。 這個用來指定Response-Request遵循的緩存機(jī)制。各個指令含義如下
Cache-Control:Public 可以被任何緩存所緩存()
Cache-Control:Private 內(nèi)容只緩存到私有緩存中
Cache-Control:no-cache 所有內(nèi)容都不會被緩存
2. HTTP響應(yīng)格式
在接收和解釋請求消息后,服務(wù)器會返回一個 HTTP 響應(yīng)消息。與 HTTP 請求類似,HTTP 響應(yīng)也是由三個部分組成,分別是:狀態(tài)行、消息報頭和響應(yīng)正文。如:
HTTP/1.1 200 OK
Date: Sun, 17 Mar 2013 08:12:54 GMT
Server: Apache/2.2.8 (Win32) PHP/5.2.5
X-Powered-By: PHP/5.2.5
Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 4393
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
<html>
<head>
<title>HTTP響應(yīng)示例<title>
</head>
<body>
Hello HTTP!
</body>
</html>
1、狀態(tài)行
狀態(tài)行由協(xié)議版本、數(shù)字形式的狀態(tài)代碼,及相應(yīng)的狀態(tài)描述組成,各元素之間以空格分隔,結(jié)尾時回車換行符,格式如下:
HTTP-Version Status-Code Reason-Phrase CRLF
HTTP-Version 表示服務(wù)器 HTTP 協(xié)議的版本,Status-Code 表示服務(wù)器發(fā)回的響應(yīng)代碼,Reason-Phrase 表示狀態(tài)代碼的文本描述,CRLF 表示回車換行。例如:
HTTP/1.1 200 OK (CRLF)
狀態(tài)代碼與狀態(tài)描述
狀態(tài)代碼由 3 位數(shù)字組成, 表示請求是否被理解或被滿足,狀態(tài)描述給出了關(guān)于狀態(tài)碼的簡短的文字描述。狀態(tài)碼的第一個數(shù)字定義了響應(yīng)類別,后面兩位數(shù)字沒有具體分類。第一個數(shù)字有 5 種取值,如下所示。
常見狀態(tài)代碼、狀態(tài)描述、說明:
200 OK //客戶端請求成功
400 Bad Request //客戶端請求有語法錯誤,不能被服務(wù)器所理解
401 Unauthorized //請求未經(jīng)授權(quán),這個狀態(tài)代碼必須和WWW-Authenticate報頭域一起使用
403 Forbidden //服務(wù)器收到請求,但是拒絕提供服務(wù)
404 Not Found //請求資源不存在,eg:輸入了錯誤的URL
500 Internal Server Error //服務(wù)器發(fā)生不可預(yù)期的錯誤
503 Server Unavailable //服務(wù)器當(dāng)前不能處理客戶端的請求,一段時間后可能恢復(fù)正常
2、響應(yīng)正文
響應(yīng)正文就是服務(wù)器返回的資源的內(nèi)容,響應(yīng)頭和正文之間也必須用空行分隔。如:
3 、響應(yīng)頭信息
HTTP最常見的響應(yīng)頭如下所示:
Cache頭域
Date:
作用:生成消息的具體時間和日期,即當(dāng)前的GMT時間。
例如: Date: Sun, 17 Mar 2013 08:12:54 GMT
Expires:
作用: 瀏覽器會在指定過期時間內(nèi)使用本地緩存,指明應(yīng)該在什么時候認(rèn)為文檔已經(jīng)過期,從而不再緩存它。
例如: Expires: Thu, 19 Nov 1981 08:52:00 GMT
Vary
作用:
例如: Vary: Accept-Encoding
Cookie/Login 頭域
P3P
作用: 用于跨域設(shè)置Cookie, 這樣可以解決iframe跨域訪問cookie的問題
例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
Set-Cookie
作用: 非常重要的header, 用于把cookie 發(fā)送到客戶端瀏覽器, 每一個寫入cookie都會生成一個Set-Cookie.
例如: Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
Entity實體頭域:
實體內(nèi)容的屬性,包括實體信息類型,長度,壓縮方法,最后一次修改時間,數(shù)據(jù)有效性等。
ETag:
作用: 和If-None-Match 配合使用。 (實例請看上節(jié)中If-None-Match的實例)
例如: ETag: "03f2b33c0bfcc1:0"
Last-Modified:
作用: 用于指示資源的最后修改日期和時間。(實例請看上節(jié)的If-Modified-Since的實例)
例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT
Content-Type:
作用:WEB服務(wù)器告訴瀏覽器自己響應(yīng)的對象的類型和字符集,
例如:
Content-Type: text/html; charset=utf-8
Content-Type:text/html;charset=GB2312
Content-Type: image/jpeg
Content-Length:
指明實體正文的長度,以字節(jié)方式存儲的十進(jìn)制數(shù)字來表示。在數(shù)據(jù)下行的過程中,Content-Length的方式要預(yù)先在服務(wù)器中緩存所有數(shù)據(jù),然后所有數(shù)據(jù)再一股腦兒地發(fā)給客戶端。
例如: Content-Length: 19847
Content-Encoding:
作用:文檔的編碼(Encode)方法。一般是壓縮方式。
WEB服務(wù)器表明自己使用了什么壓縮方法(gzip,deflate)壓縮響應(yīng)中的對象。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。
例如:Content-Encoding:gzip
Content-Language:
作用: WEB服務(wù)器告訴瀏覽器自己響應(yīng)的對象的語言者
例如: Content-Language:da
Miscellaneous 頭域
Server:
作用:指明HTTP服務(wù)器的軟件信息
例如:Apache/2.2.8 (Win32) PHP/5.2.5
X-Powered-By:
作用:表示網(wǎng)站是用什么技術(shù)開發(fā)的
例如: X-Powered-By: PHP/5.2.5
Transport頭域
Connection:
例如: Connection: keep-alive 當(dāng)一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉,如果客戶端再次訪問這個服務(wù)器上的網(wǎng)頁,會繼續(xù)使用這一條已經(jīng)建立的連接
例如: Connection: close 代表一個Request完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接會關(guān)閉, 當(dāng)客戶端再次發(fā)送Request,需要重新建立TCP連接。
Location頭域
Location:
作用: 用于重定向一個新的位置, 包含新的URL地址
實例請看304狀態(tài)實例
HTTP協(xié)議是無狀態(tài)的和Connection: keep-alive的區(qū)別
無狀態(tài)是指協(xié)議對于事務(wù)處理沒有記憶能力,服務(wù)器不知道客戶端是什么狀態(tài)。從另一方面講,打開一個服務(wù)器上的網(wǎng)頁和你之前打開這個服務(wù)器上的網(wǎng)頁之間沒有任何聯(lián)系。
HTTP是一個無狀態(tài)的面向連接的協(xié)議,無狀態(tài)不代表HTTP不能保持TCP連接,更不能代表HTTP使用的是UDP協(xié)議(無連接)。
從HTTP/1.1起,默認(rèn)都開啟了Keep-Alive,保持連接特性,簡單地說,當(dāng)一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉,如果客戶端再次訪問這個服務(wù)器上的網(wǎng)頁,會繼續(xù)使用這一條已經(jīng)建立的連接。
Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務(wù)器軟件(如Apache)中設(shè)定這個時間。
3. 瀏覽器緩存
瀏覽器緩存:包括頁面html緩存和圖片js,css等資源的緩存。如下圖,瀏覽器緩存是基于把頁面信息保存到用戶本地電腦硬盤里。
1、緩存的優(yōu)點:
1)服務(wù)器響應(yīng)更快:因為請求從緩存服務(wù)器(離客戶端更近)而不是源服務(wù)器被相應(yīng),這個過程耗時更少,讓服務(wù)器看上去響應(yīng)更快。
2)減少網(wǎng)絡(luò)帶寬消耗:當(dāng)副本被重用時會減低客戶端的帶寬消耗;客戶可以節(jié)省帶寬費(fèi)用,控制帶寬的需求的增長并更易于管理。
2、緩存工作原理
頁面緩存狀態(tài)是由http header決定的,一個瀏覽器請求信息,一個是服務(wù)器響應(yīng)信息。主要包括Pragma: no-cache、Cache-Control、 Expires、 Last-Modified、If-Modified-Since。其中Pragma: no-cache由HTTP/1.0規(guī)定,Cache-Control由HTTP/1.1規(guī)定。
工作原理圖:
從圖中我們可以看到原理主要分三步:
與緩存相關(guān)的HTTP擴(kuò)展消息頭
Expires:設(shè)置頁面過期時間,格林威治時間GMT
Cache-Control:更細(xì)致的控制緩存的內(nèi)容
Last-Modified:請求對象最后一次的修改時間 用來判斷緩存是否過期 通常由文件的時間信息產(chǎn)生
ETag:響應(yīng)中資源的校驗值,在服務(wù)器上某個時段是唯一標(biāo)識的。ETag是一個可以 與Web資源關(guān)聯(lián)的記號(token),和Last-Modified功能才不多,也是一個標(biāo)識符,一般和Last-Modified一起使用,加強(qiáng)服務(wù)器判斷的準(zhǔn)確度。
Date:服務(wù)器的時間
If-Modified-Since:客戶端存取的該資源最后一次修改的時間,用來和服務(wù)器端的Last-Modified做比較
If-None-Match:客戶端存取的該資源的檢驗值,同ETag。
Cache-Control的主要參數(shù)
Cache-Control: private/public Public 響應(yīng)會被緩存,并且在多用戶間共享。 Private 響應(yīng)只能夠作為私有的緩存,不能再用戶間共享。
Cache-Control: no-cache:不進(jìn)行緩存
Cache-Control: max-age=x:緩存時間 以秒為單位
Cache-Control: must-revalidate:如果頁面是過期的 則去服務(wù)器進(jìn)行獲取。
2、關(guān)于圖片,css,js,flash的緩存
這個主要通過服務(wù)器的配置來實現(xiàn)這個技術(shù),如果使用apache服務(wù)器的話,可以使用mod_expires模塊來實現(xiàn):
編譯mod_expires模塊:
Cd /root/httpd-2.2.3/modules/metadata
/usr/local/apache/bin/apxs -i -a -c mod_expires.c //編譯
編輯httpd.conf配置:添加下面內(nèi)容
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType text/html "access plus 1 months"
ExpiresByType text/css "access plus 1 months"
ExpiresByType image/gif "access plus 1 months"
ExpiresByType image/jpeg "access plus 1 months"
ExpiresByType image/jpg "access plus 1 months"
ExpiresByType image/png "access plus 1 months"
EXpiresByType application/x-shockwave-flash "access plus 1 months"
EXpiresByType application/x-javascript "access plus 1 months"
#ExpiresByType video/x-flv "access plus 1 months"
</IfModule>
解釋:第一句--開啟服務(wù)
第二句--默認(rèn)時間是一個月
在下面是關(guān)于各種類型的資源的緩存時間設(shè)置
我們開發(fā)Web應(yīng)用的時候,會用到大量的js、css、image、html等靜態(tài)資源資源。
靜態(tài)資源映射
默認(rèn)情況下,我們只需要將靜態(tài)資源放在一下幾個目錄中就可以直接通過url在瀏覽器中訪問了。
如果這四個目錄中有相同的靜態(tài)資源文件,那么優(yōu)先訪問哪個目錄下面的資源啊?
靜態(tài)資源的默認(rèn)訪問優(yōu)先級:/META-INF/resources/>/resources/>/static/>/public/
在四個目錄中都放一個static.html的文件,每個html文件中都說明自己所在的目錄,訪問結(jié)果如下:
SpringBoot關(guān)于靜態(tài)資源的訪問涉及到了application.properties中的兩個屬性:
# 默認(rèn)值為 /* spring.mvc.static-path-pattern= #這里設(shè)置靜態(tài)資源匹配的url-pattern # 默認(rèn)值為 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ spring.resources.static-locations= #這里設(shè)置要指向的路徑,多個使用英文逗號隔開,在前面的優(yōu)先級高
此時,我們豁然開朗,知道默認(rèn)情況下靜態(tài)資源為什么放在/META-INF/resources/、/resources/、/static/、/public/這四個目錄了,還有這四個目錄訪問的優(yōu)先級是怎么來的了。
修改靜態(tài)資源映射的方法:
spring.mvc.static-path-pattern=/mystatic/* spring.resources.static-locations= classpath:mystatic/
在resources資源目錄中創(chuàng)建一個mystatic目錄,在該目錄下面創(chuàng)建一個static.html文件,訪問結(jié)果如下:
注意:還可以設(shè)置外部磁盤目錄,設(shè)置方式不變,格式如下:file:d/mystatic/。
WebJars
WebJars將前端資源(css,js,image,html等等)打包到j(luò)ar中,然后使用基于JVM的包管理器(比如 Maven、Gradle 等)管理前端依賴的方案。SpringBoot中也可以通過WebJars來訪問靜態(tài)資源。
SpringBoot默認(rèn)將/webjars/**映射到 classpath:/META-INF/resources/webjars/。
所以默認(rèn)情況下我們需要訪問WebJars中的資源,需要將其jar包放到classpath:/META-INF/resources/webjars/目錄中。
我們來使用一下WebJars:
<dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>2.1.1</version> </dependency>
<script src="/webjars/jquery/2.1.1/jquery.js"></script>
版本號統(tǒng)一管理
如果我們有很多頁面都是用了WebJars中的資源,而我們現(xiàn)在要升級WebJars的版本,豈不是要在每個頁面中都改動一下,這樣很麻煩啊,有沒有簡單的方法啊。此時,我們可以進(jìn)行版本號統(tǒng)一管理。
<dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> </dependency>
<script src="/webjarslocator/jquery/jquery.js"></script>
靜態(tài)資源版本管理
當(dāng)我們資源內(nèi)容發(fā)生變化時,由于瀏覽器緩存,用戶本地的靜態(tài)資源還是舊的資源,為了防止這種情況導(dǎo)致的問題,我們可能會手動在請求url的時候加個版本號或者其他方式。
<script type="text/javascript" src="/lavor.js?v=1.1"></script>
SpringMVC提供了兩種方式可以幫助我們很容易地解決這類問題。
MD5方式
spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/**
<script src="${urls.getForLookupPath('/lavor.js') }"></script>
<script src="/lavor-fdfa0502716d517c6cad4f2536aa02a1.js"></script>
請求/lavor-fdfa0502716d517c6cad4f2536aa02a1.js,我們MD5配置的paths=/**,所以SpringMVC會嘗試url中是否包含-,如果包含會去掉后面這部分,然后去映射的目錄(如webapp根目錄,上面提到的四大靜態(tài)映射目錄)查找/lavor.js文件,如果能找到就返回。
版本號方式
spring.resources.chain.strategy.fixed.enabled=true #版本號處理的路徑 spring.resources.chain.strategy.fixed.paths=/** # 版本號,可以為所處理路徑中的資源加上/v1.1目錄前綴 spring.resources.chain.strategy.fixed.version=v1.1
<script src="${urls.getForLookupPath('/lavor.js') }"></script>
<script src="/v1.1/lavor.js"></script>
請求/v1.1/lavor.js,會查看v1.1是不是版本號,如果是就去掉前綴目錄,直接查找/lavor.js。
注意:我們發(fā)現(xiàn)如果添加了webapp目錄,那么該目錄也可以存放靜態(tài)資源,并且默認(rèn)情況下訪問優(yōu)先級比/META-INF/resources/還要高。
ndroid高階開發(fā)專欄
Java高級開發(fā)進(jìn)階專欄
TCP連接的三次握手和四次揮手
一文搞懂DNS域名解析的詳細(xì)流程
高并發(fā)與負(fù)載均衡:Nginx的反向代理和負(fù)載均衡
一文搞懂TCP/IP協(xié)議及Web基礎(chǔ)知識
一文搞懂HTTP協(xié)議的核心知識點
一文掌握 HTTP協(xié)議報文 包含的信息類型
一文搞懂HTTP協(xié)議 返回結(jié)果的HTTP狀態(tài)碼
一文搞懂 HTTP協(xié)議的報文首部
作為網(wǎng)絡(luò)專欄的開篇導(dǎo)文,本文概況介紹下經(jīng)典案例:從輸入一個網(wǎng)址到瀏覽器顯示頁面的全過程。
步驟概要介紹如下:
當(dāng)在瀏覽器中輸入網(wǎng)址時,瀏覽器其實就已在智能匹配 url 了,他會從歷史記錄,書簽等地方,找到已經(jīng)輸入的字符串可能對應(yīng)的 url,然后給出智能提示,讓你可以補(bǔ)全url地址。
對于 google的chrome 的瀏覽器,他甚至?xí)苯訌木彺嬷邪丫W(wǎng)頁展示出來,就是說,你還沒有按下 enter,頁面就出來了。
請求一旦發(fā)起,瀏覽器首先要做的事情就是解析這個域名。
在HTTP工作開始之前,web瀏覽器首先要通過網(wǎng)絡(luò)與web服務(wù)器建立連接,該連接是通過TCP來完成的。
PS1:為什么要先建立TCP呢?
因為HTTP是比TCP更高層次的應(yīng)用層協(xié)議,根據(jù)規(guī)則,只有低層協(xié)議建立之后才能進(jìn)行更高層次協(xié)議的連接,因此要先建立TCP連接,一般TCP連接的端口號是80
PS2:擴(kuò)展知識點:
TCP連接的三次握手和斷開的四次揮手 參照站內(nèi)文章:TCP 三次握手和四次揮手
建立了TCP連接之后,web瀏覽器就會向web服務(wù)器發(fā)起一個http請求。
一個典型的 http request header 一般需要包括請求的方法,例如 GET 或者 POST 等,不常用的還有 PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的瀏覽器只能發(fā)起 GET 或者 POST 請求。
客戶端向服務(wù)器發(fā)起http請求的時候,會有一些請求信息,請求信息包含三個部分:
下面是一個完整的HTTP請求例子:
GET/sample.jspHTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate
username=jinqiao&password=1234
4.1、請求行
請求的第一行是“方法URL議/版本”:GET/sample.jsp HTTP/1.1
4.2、請求頭(Request Header)
請求頭包含許多有關(guān)的客戶端環(huán)境和請求正文的有用信息。例如,請求頭可以聲明瀏覽器所用的語言,請求正文的長度等。
Accept:image/gif.image/jpeg.*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible:MSIE5.01:Windows NT5.0)
Accept-Encoding:gzip,deflate.
4.3、請求正文
請求頭和請求正文之間是一個空行,這個行非常重要,它表示請求頭已經(jīng)結(jié)束,接下來的是請求正文。請求正文中可以包含客戶提交的查詢字符串信息:
username=jinqiao&password=1234
服務(wù)器給瀏覽器響應(yīng)一個301永久重定向響應(yīng),這樣瀏覽器就會訪問“http://www.google.com/” 而非“http://google.com/”。
為什么服務(wù)器一定要重定向而不是直接發(fā)送用戶想看的網(wǎng)頁內(nèi)容呢?其中一個原因跟搜索引擎排名有關(guān)。如果一個頁面有兩個地址,就像http://www.yy.com/和http://yy.com/,搜索引擎會認(rèn)為它們是兩個網(wǎng)站,結(jié)果造成每個搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是什么意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網(wǎng)站排名下。還有就是用不同的地址會造成緩存友好性變差,當(dāng)一個頁面有好幾個名字時,它可能會在緩存里出現(xiàn)好幾次。
重定向原因:
這種情況下,如果不做重定向,則用戶收藏夾或搜索引擎數(shù)據(jù)庫中舊地址只能讓訪問客戶得到一個404頁面錯誤信息,訪問流量白白喪失;再者某些注冊了多個域名的網(wǎng)站,也需要通過重定向讓訪問這些域名的用戶自動跳轉(zhuǎn)到主站點等。
現(xiàn)在瀏覽器知道了 "http://www.google.com/"才是要訪問的正確地址,所以它會發(fā)送另一個http請求。這里沒有啥好說的
經(jīng)過前面的步驟,服務(wù)器收到了我們的請求,也處理我們的請求,到這一步,它會把它的處理結(jié)果返回,也就是返回一個HTPP響應(yīng)。
HTTP響應(yīng)與HTTP請求相似,HTTP響應(yīng)也由3個部分構(gòu)成,分別是:
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>http</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>
7.1、狀態(tài)行:
狀態(tài)行由協(xié)議版本、數(shù)字形式的狀態(tài)代碼、及相應(yīng)的狀態(tài)描述,各元素之間以空格分隔。
格式: HTTP-Version Status-Code Reason-Phrase CRLF
例如: HTTP/1.1 200 OK \r\n
-- 協(xié)議版本:是用http1.0還是其他版本
-- 狀態(tài)描述:狀態(tài)描述給出了關(guān)于狀態(tài)代碼的簡短的文字描述。比如狀態(tài)代碼為200時的描述為 ok
-- 狀態(tài)代碼:狀態(tài)代碼由三位數(shù)字組成,第一個數(shù)字定義了響應(yīng)的類別,且有五種可能取值。
狀態(tài)代碼具體協(xié)議定義如下:
1xx:信息性狀態(tài)碼,表示服務(wù)器已接收了客戶端請求,客戶端可繼續(xù)發(fā)送請求。
100 Continue
101 Switching Protocols
2xx:成功狀態(tài)碼,表示服務(wù)器已成功接收到請求并進(jìn)行處理。
200 OK 表示客戶端請求成功
204 No Content 成功,但不返回任何實體的主體部分
206 Partial Content 成功執(zhí)行了一個范圍(Range)請求
3xx:重定向狀態(tài)碼,表示服務(wù)器要求客戶端重定向。
301 Moved Permanently 永久性重定向,響應(yīng)報文的Location首部應(yīng)該有該資源的新URL
302 Found 臨時性重定向,響應(yīng)報文的Location首部給出的URL用來臨時定位資源
303 See Other 請求的資源存在著另一個URI,客戶端應(yīng)使用GET方法定向獲取請求的資源
304 Not Modified 服務(wù)器內(nèi)容沒有更新,可以直接讀取瀏覽器緩存
307 Temporary Redirect 臨時重定向。與302 Found含義一樣。302禁止POST變換為GET,但實際使用時并不一定,307則更多瀏覽器可能會遵循這一標(biāo)準(zhǔn),但也依賴于瀏覽器具體實現(xiàn)
4xx:客戶端錯誤狀態(tài)碼,表示客戶端的請求有非法內(nèi)容。
400 Bad Request 表示客戶端請求有語法錯誤,不能被服務(wù)器所理解
401 Unauthonzed 表示請求未經(jīng)授權(quán),該狀態(tài)代碼必須與 WWW-Authenticate 報頭域一起使用
403 Forbidden 表示服務(wù)器收到請求,但是拒絕提供服務(wù),通常會在響應(yīng)正文中給出不提供服務(wù)的原因
404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL
5xx:服務(wù)器錯誤狀態(tài)碼,表示服務(wù)器未能正常處理客戶端的請求而出現(xiàn)意外錯誤。
500 Internel Server Error 表示服務(wù)器發(fā)生不可預(yù)期的錯誤,導(dǎo)致無法完成客戶端的請求
503 Service Unavailable 表示服務(wù)器當(dāng)前不能夠處理客戶端的請求,在一段時間之后,服務(wù)器可能會恢復(fù)正常
7.2、響應(yīng)頭:
響應(yīng)頭部:由關(guān)鍵字/值對組成,每行一對,關(guān)鍵字和值用英文冒號":"分隔。
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
典型的響應(yīng)頭字段:
7.3、響應(yīng)正文
包含著我們需要的一些具體信息,比如cookie,html,image,后端返回的請求數(shù)據(jù)等等。這里需要注意,響應(yīng)正文和響應(yīng)頭之間有一行空格,表示響應(yīng)頭的信息到空格為止。
在瀏覽器沒有完整接受全部HTML文檔時,它就已經(jīng)開始顯示這個頁面了,瀏覽器是如何把頁面呈現(xiàn)在屏幕上的呢?
不同瀏覽器可能解析的過程不太一樣,這里我們只介紹webkit的渲染過程。下圖對應(yīng)的就是WebKit渲染的過程,這個過程包括:
解析html以構(gòu)建dom樹 -> 構(gòu)建render樹 -> 布局render樹 -> 繪制render樹:
其實這個步驟可以并列在步驟8中,在瀏覽器顯示HTML時,它會注意到需要獲取其他地址內(nèi)容的標(biāo)簽。這時,瀏覽器會發(fā)送一個獲取請求來重新獲得這些文件。比如我要獲取外圖片,CSS,JS文件等,類似于下面的鏈接:
圖片:http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif
CSS式樣表:http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css
JavaScript 文件:http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js
這些地址都要經(jīng)歷一個和HTML讀取類似的過程。所以瀏覽器會在DNS中查找這些域名,發(fā)送請求,重定向等等...
不像動態(tài)頁面,靜態(tài)文件會允許瀏覽器對其進(jìn)行緩存。有的文件可能會不需要與服務(wù)器通訊,而從緩存中直接讀取,或者可以放到CDN中
一般情況下,一旦web服務(wù)器向瀏覽器發(fā)送了請求數(shù)據(jù)后,它就要關(guān)閉TCP連接,然后如果瀏覽器或者服務(wù)器在其頭信息加入這行代碼:
connection:keep-alive
這樣TCP連接將依然保持打開狀態(tài),瀏覽器可以繼續(xù)通過相同的連接發(fā)送請求,保持連接,節(jié)省了為每個請求建立新連接所需要的的事件,同時節(jié)省了寬帶
實際上,在HTTP 1.1 版本的新特性中有一點是:默認(rèn)持久連接節(jié)省通信量,只要客戶端、服務(wù)端任意一端沒有明確斷開TCP連接,可以發(fā)送多次HTTP請求。
版權(quán)說明:摘錄到部分網(wǎng)絡(luò)資源,如存在版權(quán)問題,請私信聯(lián)系處理,謝謝!
關(guān)注頭條號“編程家園”,后續(xù)陸續(xù)會有更多技術(shù)領(lǐng)域(包括并不限于Android進(jìn)階、Java進(jìn)階、Kotlin、網(wǎng)絡(luò)、Flutter、Python等),以及架構(gòu)、職業(yè)規(guī)劃、職業(yè)思考等方面資料的免費(fèi)分享,期待您的關(guān)注!
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。