If-Modified-Since HTTP 304 和 ETag
HTTP 304狀態(tài)碼的詳細講解
304狀態(tài)碼或許不應(yīng)該認為是一種錯誤,而是對客戶端有緩存情況下服務(wù)端的一種響應(yīng)。
整個請求響應(yīng)過程如下:
客戶端在請求一個文件的時候,發(fā)現(xiàn)自己緩存的文件有 Last Modified ,那么在請求中會包含 If Modified Since ,這個時間就是緩存文件的 Last Modified 。因此,如果請求中包含 If Modified Since,就說明已經(jīng)有緩存在客戶端。服務(wù)端只要判斷這個時間和當前請求的文件的修改時間就可以確定是返回 304 還是 200 。
對于靜態(tài)文件,例如:CSS、圖片,服務(wù)器會自動完成 Last Modified 和 If Modified Since 的比較,完成緩存或者更新。但是對于動態(tài)頁面,就是動態(tài)產(chǎn)生的頁面,往往沒有包含 Last Modified 信息,這樣瀏覽器、網(wǎng)關(guān)等都不會做緩存,也就是在每次請求的時候都完成一個 200 的請求。
因此,對于動態(tài)頁面做緩存加速,首先要在 Response 的 HTTP Header 中增加 Last Modified 定義,其次根據(jù) Request 中的 If Modified Since 和被請求內(nèi)容的更新時間來返回 200 或者 304 。雖然在返回 304 的時候已經(jīng)做了一次數(shù)據(jù)庫查詢,但是可以避免接下來更多的數(shù)據(jù)庫查詢,并且沒有返回頁面內(nèi)容而只是一個 HTTP Header,從而大大的降低帶寬的消耗,對于用戶的感覺也是提高。當這些緩存有效的時候,通過 Fiddler 或HttpWatch 查看一個請求會得到這樣的結(jié)果:
?
第一次訪問 200
按F5刷新(第二次訪問) 304
按Ctrl+F5強制刷新 200
下面用Fiddler來查看上面的訪問請求過程
第一次(首次)訪問 200
?
第二次F5刷新訪問 304
請求的頭信息里多了 “If-Modified-Since","If-None-Match"?
第三次 按Ctrl+F5強制刷新 200
同第一次,不貼圖了
?
為什么要使用條件請求
當用戶訪問一個網(wǎng)頁時,條件請求可以加速網(wǎng)頁的打開時間(因為可以省去傳輸整個響應(yīng)體的時間),但仍然會有網(wǎng)絡(luò)延遲,因為瀏覽器還是得為每個資源生成一條條件請求,并且等到服務(wù)器返回HTTP/304響應(yīng),才能讀取緩存來顯示網(wǎng)頁.更理想的情況是,服務(wù)器在響應(yīng)上指定Cache-Control或Expires指令,這樣客戶端就能知道該資源的可用時間為多長,也就能跳過條件請求的步驟,直接使用緩存中的資源了.可是,即使服務(wù)器提供了這些信息,在下列情況下仍然需要使用條件請求:
在超過服務(wù)器指定的過期時間之后
如果用戶執(zhí)行了刷新操作的話
在上節(jié)給出的圖片中,請求頭中包含了一個Pragma: no-cache.這是由于用戶使用F5刷新了網(wǎng)頁.如果用戶按下了CTRL-F5 (有時稱之為“強刷-hard refresh”),你會發(fā)現(xiàn)瀏覽器省略了If-Modified-Since和If-None-Match請求頭,也就是無條件的請求頁面中的每個資源.
避免條件請求
通常來說,緩存是個好東西.如果你想提高自己網(wǎng)站的訪問速度,緩存是必須要考慮的.可是在調(diào)試的時候,有時候需要阻止緩存,這樣才能確保你所訪問到的資源是最新的.
你也許會有個疑問:“如果不改變網(wǎng)站內(nèi)容,我怎么才能讓Fiddler不返回304而返回一個包含響應(yīng)體的HTTP/200響應(yīng)呢?”
你可以在Fiddler中的網(wǎng)絡(luò)會話(Web Sessions)列表中選擇一條響應(yīng)為HTTP/304的會話,然后按下U鍵.Fiddler將會無條件重發(fā)(Unconditionally reissue)這個請求.然后使用命compare命令對比一下兩個請求有什么不同,對比結(jié)果如下,從中可以得知,Fiddler是通過省略條件請求頭來實現(xiàn)無緩存請求的:
Screenshot of Windiff of conditional and unconditional requests
如果你想全局阻止HTTP/304響應(yīng),可以這么做:首先清除瀏覽器的緩存,可以使用Fiddler工具欄上的Clear Cache按鈕(僅能清除Internet Explorer緩存),或者在瀏覽器上按CTRL+SHIFT+DELETE(所有瀏覽器都支持).在清除瀏覽器的緩存之后,回到Fiddler中,在菜單中選擇Rules > Performance > Disable Caching選項,然后Fiddler就會:刪除所有請求中的條件請求相同的請求頭以及所有響應(yīng)中的緩存時間相關(guān)的響應(yīng)頭.此外,還會在每個請求中添加Pragma: no-cache請求頭,在每個響應(yīng)中添加Cache-Control: no-cache響應(yīng)頭,阻止瀏覽器緩存這些資源.
?
動態(tài)網(wǎng)頁如何設(shè)置304
以aspx頁面為例,代碼如下:
?
var request = context.Request;
var response = context.Response;
if (request.Headers["If-Modified-Since"].NotNullOrEmpty() || request.Headers["If-None-Match"].NotNullOrEmpty())
{
response.StatusCode = 304;
return;
}
//非304情況下的操作 略
//設(shè)置緩存選項
response.Clear();
response.ClearContent();
response.Headers["Last-Modified"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
response.Headers["ETag"] = id;//這里假設(shè)的是根據(jù)不同的id
response.CacheControl = "private";
response.ExpiresAbsolute = DateTime.Now.AddMonths(6);
?
ETag是什么意思?
HTTP 協(xié)議規(guī)格說明定義ETag為“被請求變量的實體值” 。 另一種說法是,ETag是一個可以與Web資源關(guān)聯(lián)的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSON或XML文檔。服務(wù)器單獨負責判斷記號是什么及其含義,并在HTTP響應(yīng)頭中將其傳送到客戶端
?
asp.net web api的實現(xiàn)代碼如下:
?
// GET /images/001.png
[HttpGet]
public HttpResponseMessage Get(string filename)
{
HttpResponseMessage response = new HttpResponseMessage();
.....
string etag = string.Format("\"{0}\"", fileInfo.MD5);
var tag = Request.Headers.IfNoneMatch.FirstOrDefault();
if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag == etag)
{
response.StatusCode = HttpStatusCode.NotModified;
}
else
{
//dealcode ......
responseStream.Position = 0;
response.StatusCode = fullContent ? HttpStatusCode.OK : HttpStatusCode.PartialContent;
response.Content = new StreamContent(responseStream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue(fileInfo.ContentType);
response.Headers.ETag = new EntityTagHeaderValue(etag);
response.Headers.CacheControl = new CacheControlHeaderValue();
response.Headers.CacheControl.Public = true;
response.Headers.CacheControl.MaxAge = TimeSpan.FromHours(480);
response.Content.Headers.Expires = DateTimeOffset.Now.AddDays(20);
response.Content.Headers.LastModified = fileInfo.UploadDate;
}
return response;
}
?
常見狀態(tài)碼:
一些常見的狀態(tài)碼為:
- 200?– 服務(wù)器成功返回網(wǎng)頁
- 404?– 請求的網(wǎng)頁不存在
- 503?– 服務(wù)器超時
下面提供 HTTP 狀態(tài)碼的完整列表。點擊鏈接可了解詳情。您也可以訪問?HTTP 狀態(tài)碼上的 W3C 頁獲取更多信息。
1xx(臨時響應(yīng))
表示臨時響應(yīng)并需要請求者繼續(xù)執(zhí)行操作的狀態(tài)碼。
| 100(繼續(xù)) | 請求者應(yīng)當繼續(xù)提出請求。服務(wù)器返回此代碼表示已收到請求的第一部分,正在等待其余部分。 |
| 101(切換協(xié)議) | 請求者已要求服務(wù)器切換協(xié)議,服務(wù)器已確認并準備切換。 |
2xx?(成功)
表示成功處理了請求的狀態(tài)碼。
| 200(成功) | 服務(wù)器已成功處理了請求。通常,這表示服務(wù)器提供了請求的網(wǎng)頁。如果是對您的 robots.txt 文件顯示此狀態(tài)碼,則表示 Googlebot 已成功檢索到該文件。 |
| 201(已創(chuàng)建) | 請求成功并且服務(wù)器創(chuàng)建了新的資源。 |
| 202(已接受) | 服務(wù)器已接受請求,但尚未處理。 |
| 203(非授權(quán)信息) | 服務(wù)器已成功處理了請求,但返回的信息可能來自另一來源。 |
| 204(無內(nèi)容) | 服務(wù)器成功處理了請求,但沒有返回任何內(nèi)容。 |
| 205(重置內(nèi)容) | 服務(wù)器成功處理了請求,但沒有返回任何內(nèi)容。與 204 響應(yīng)不同,此響應(yīng)要求請求者重置文檔視圖(例如,清除表單內(nèi)容以輸入新內(nèi)容)。 |
| 206(部分內(nèi)容) | 服務(wù)器成功處理了部分 GET 請求。 |
3xx?(重定向)
要完成請求,需要進一步操作。通常,這些狀態(tài)碼用來重定向。Google 建議您在每次請求中使用重定向不要超過 5 次。您可以使用網(wǎng)站管理員工具查看一下 Googlebot 在抓取重定向網(wǎng)頁時是否遇到問題。診斷下的網(wǎng)絡(luò)抓取頁列出了由于重定向錯誤導致 Googlebot 無法抓取的網(wǎng)址。
| 300(多種選擇) | 針對請求,服務(wù)器可執(zhí)行多種操作。服務(wù)器可根據(jù)請求者 (user agent) 選擇一項操作,或提供操作列表供請求者選擇。 |
| 301(永久移動) | 請求的網(wǎng)頁已永久移動到新位置。服務(wù)器返回此響應(yīng)(對 GET 或 HEAD 請求的響應(yīng))時,會自動將請求者轉(zhuǎn)到新位置。您應(yīng)使用此代碼告訴 Googlebot 某個網(wǎng)頁或網(wǎng)站已永久移動到新位置。 |
| 302(臨時移動) | 服務(wù)器目前從不同位置的網(wǎng)頁響應(yīng)請求,但請求者應(yīng)繼續(xù)使用原有位置來響應(yīng)以后的請求。此代碼與響應(yīng) GET 和 HEAD 請求的 301 代碼類似,會自動將請求者轉(zhuǎn)到不同的位置,但您不應(yīng)使用此代碼來告訴 Googlebot 某個網(wǎng)頁或網(wǎng)站已經(jīng)移動,因為 Googlebot 會繼續(xù)抓取原有位置并編制索引。 |
| 303(查看其他位置) | 請求者應(yīng)當對不同的位置使用單獨的 GET 請求來檢索響應(yīng)時,服務(wù)器返回此代碼。對于除 HEAD 之外的所有請求,服務(wù)器會自動轉(zhuǎn)到其他位置。 |
| 304(未修改) | 自從上次請求后,請求的網(wǎng)頁未修改過。服務(wù)器返回此響應(yīng)時,不會返回網(wǎng)頁內(nèi)容。 如果網(wǎng)頁自請求者上次請求后再也沒有更改過,您應(yīng)將服務(wù)器配置為返回此響應(yīng)(稱為 If-Modified-Since HTTP 標頭)。服務(wù)器可以告訴 Googlebot 自從上次抓取后網(wǎng)頁沒有變更,進而節(jié)省帶寬和開銷。 ? |
| 305(使用代理) | 請求者只能使用代理訪問請求的網(wǎng)頁。如果服務(wù)器返回此響應(yīng),還表示請求者應(yīng)使用代理。 |
| 307(臨時重定向) | 服務(wù)器目前從不同位置的網(wǎng)頁響應(yīng)請求,但請求者應(yīng)繼續(xù)使用原有位置來響應(yīng)以后的請求。此代碼與響應(yīng) GET 和 HEAD 請求的 <a href=answer.py?answer=>301</a> 代碼類似,會自動將請求者轉(zhuǎn)到不同的位置,但您不應(yīng)使用此代碼來告訴 Googlebot 某個頁面或網(wǎng)站已經(jīng)移動,因為 Googlebot 會繼續(xù)抓取原有位置并編制索引。 |
4xx(請求錯誤)
這些狀態(tài)碼表示請求可能出錯,妨礙了服務(wù)器的處理。
| 400(錯誤請求) | 服務(wù)器不理解請求的語法。 |
| 401(未授權(quán)) | 請求要求身份驗證。對于登錄后請求的網(wǎng)頁,服務(wù)器可能返回此響應(yīng)。 |
| 403(禁止) | 服務(wù)器拒絕請求。如果您在 Googlebot 嘗試抓取您網(wǎng)站上的有效網(wǎng)頁時看到此狀態(tài)碼(您可以在 Google 網(wǎng)站管理員工具診斷下的網(wǎng)絡(luò)抓取頁面上看到此信息),可能是您的服務(wù)器或主機拒絕了 Googlebot 訪問。 |
| 404(未找到) | 服務(wù)器找不到請求的網(wǎng)頁。例如,對于服務(wù)器上不存在的網(wǎng)頁經(jīng)常會返回此代碼。 如果您的網(wǎng)站上沒有 robots.txt 文件,而您在 Google 網(wǎng)站管理員工具“診斷”標簽的 robots.txt 頁上看到此狀態(tài)碼,則這是正確的狀態(tài)碼。但是,如果您有 robots.txt 文件而又看到此狀態(tài)碼,則說明您的 robots.txt 文件可能命名錯誤或位于錯誤的位置(該文件應(yīng)當位于頂級域,名為 robots.txt)。 如果對于 Googlebot 抓取的網(wǎng)址看到此狀態(tài)碼(在”診斷”標簽的?HTTP 錯誤頁面上),則表示 Googlebot 跟隨的可能是另一個頁面的無效鏈接(是舊鏈接或輸入有誤的鏈接)。 |
| 405(方法禁用) | 禁用請求中指定的方法。 |
| 406(不接受) | 無法使用請求的內(nèi)容特性響應(yīng)請求的網(wǎng)頁。 |
| 407(需要代理授權(quán)) | 此狀態(tài)碼與 <a href=answer.py?answer=35128>401(未授權(quán))</a>類似,但指定請求者應(yīng)當授權(quán)使用代理。如果服務(wù)器返回此響應(yīng),還表示請求者應(yīng)當使用代理。 |
| 408(請求超時) | 服務(wù)器等候請求時發(fā)生超時。 |
| 409(沖突) | 服務(wù)器在完成請求時發(fā)生沖突。服務(wù)器必須在響應(yīng)中包含有關(guān)沖突的信息。服務(wù)器在響應(yīng)與前一個請求相沖突的 PUT 請求時可能會返回此代碼,以及兩個請求的差異列表。 |
| 410(已刪除) | 如果請求的資源已永久刪除,服務(wù)器就會返回此響應(yīng)。該代碼與 404(未找到)代碼類似,但在資源以前存在而現(xiàn)在不存在的情況下,有時會用來替代 404 代碼。如果資源已永久移動,您應(yīng)使用 301 指定資源的新位置。 |
| 411(需要有效長度) | 服務(wù)器不接受不含有效內(nèi)容長度標頭字段的請求。 |
| 412(未滿足前提條件) | 服務(wù)器未滿足請求者在請求中設(shè)置的其中一個前提條件。 |
| 413(請求實體過大) | 服務(wù)器無法處理請求,因為請求實體過大,超出服務(wù)器的處理能力。 |
| 414(請求的 URI 過長) | 請求的 URI(通常為網(wǎng)址)過長,服務(wù)器無法處理。 |
| 415(不支持的媒體類型) | 請求的格式不受請求頁面的支持。 |
| 416(請求范圍不符合要求) | 如果頁面無法提供請求的范圍,則服務(wù)器會返回此狀態(tài)碼。 |
| 417(未滿足期望值) | 服務(wù)器未滿足”期望”請求標頭字段的要求。 |
5xx(服務(wù)器錯誤)
這些狀態(tài)碼表示服務(wù)器在處理請求時發(fā)生內(nèi)部錯誤。這些錯誤可能是服務(wù)器本身的錯誤,而不是請求出錯。
| 500(服務(wù)器內(nèi)部錯誤) | 服務(wù)器遇到錯誤,無法完成請求。 |
| 501(尚未實施) | 服務(wù)器不具備完成請求的功能。例如,服務(wù)器無法識別請求方法時可能會返回此代碼。 |
| 502(錯誤網(wǎng)關(guān)) | 服務(wù)器作為網(wǎng)關(guān)或代理,從上游服務(wù)器收到無效響應(yīng)。 |
| 503(服務(wù)不可用) | 服務(wù)器目前無法使用(由于超載或停機維護)。通常,這只是暫時狀態(tài)。 |
| 504(網(wǎng)關(guān)超時) | 服務(wù)器作為網(wǎng)關(guān)或代理,但是沒有及時從上游服務(wù)器收到請求。 |
| 505(HTTP 版本不受支持) | 服務(wù)器不支持請求中所用的 HTTP 協(xié)議版本。 |
?
?
引用內(nèi)容源址:
http://www.jb51.net/article/43143.htm
http://blog.sina.com.cn/s/blog_4c98b9600100jd4z.html
http://www.cnblogs.com/shanyou/archive/2012/05/01/2477500.html
--- end ---
總結(jié)
以上是生活随笔為你收集整理的If-Modified-Since HTTP 304 和 ETag的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WGCNA 简明指南|2. 模块与性状关
- 下一篇: 明基逐鹿出席2016薪酬福利与激励创新论