HTTP 304狀態碼的詳細講解
HTTP 304狀態碼的詳細講解
304狀態碼或許不應該認為是一種錯誤,而是對客戶端有緩存情況下服務端的一種響應。
整個請求響應過程如下:
客戶端在請求一個檔案的時候,發現自己緩存的檔案有 Last Modified ,那麼在請求中會包含 If Modified Since ,這個時間就是緩存檔案的 Last Modified 。因此,如果請求中包含 If Modified Since,就說明已經有緩存在客戶端。服務端只要判斷這個時間和當前請求的檔案的修改時間就可以確定是返回 304 還是 200 。對於靜態檔案,例如:CSS、圖片,服務器會自動完成 Last Modified 和 If Modified Since
第一次訪問 200按F5重新整理(第二次訪問) 304按Ctrl+F5強制重新整理 200
下面用Fiddler來檢視上面的訪問請求過程
第一次(首次)訪問 200
第二次F5重新整理訪問 304
請求的頭資訊裡多了 “If-Modified-Since","If-None-Match"
第三次按Ctrl+F5強制重新整理 200同第一次,不貼圖了
為什麼要使用條件請求當用戶訪問一個網頁時,條件請求可以加速網頁的開啟時間(因為可以省去傳輸整個響應體的時間),
在超過服務器指定的過期時間之後如果用戶執行了重新整理操作的話在上節給出的圖片中,請求頭中包含了一個Pragma: no-cache.這是由於使用者使用F5重新整理了網頁.如果用戶按下了CTRL-F5 (有時稱之為“強刷-hard refresh”),你會發現瀏覽器省略了If-Modified-Since和If-None-Match請求頭,也就是無條件的請求頁面中的每個資源.避免條件請求通常來說,快取是個好東西.如果你想提高自己網站的訪問速度,快取是必須要考慮的.可是在除錯的時候,有時候需要阻止緩存,這樣才能確保你所訪問到的資源是最新的.你也許會有個疑問:“如果不改變網站內容,我怎麼才能讓Fiddler不返回304而返回一個包含響應體的HTTP/200響應呢?”你可以在Fiddler中的網絡會話(Web Sessions)列表中選擇一條響應為HTTP/304的會話,然後按下U鍵.Fiddler將會無條件重發(Unconditionally reissue)這個請求.然後使用命compare命令對比一下兩個請求有什麼不同,對比結果如下,從中可以得知,Fiddler是通過省略條件請求頭來實現無緩存請求的:Screenshot of Windiff of conditional and unconditional requests如果你想全域性阻止HTTP/304響應,可以這麼做:首先清除瀏覽器的緩存,可以使用Fiddler工具欄上的Clear Cache按鈕(僅能清除Internet Explorer快取),或者在瀏覽器上按CTRL+SHIFT+DELETE(所有瀏覽器都支援).在清除瀏覽器的緩存之後,回到Fiddler中,在菜單中選擇Rules > Performance > Disable Caching選項,然後Fiddler就會:刪除所有請求中的條件請求相同的請求頭以及所有響應中的緩存時間相關的響應頭.此外,還會在每個請求中新增Pragma: no-cache請求頭,在每個響應中新增Cache-Control: no-cache響應頭,阻止瀏覽器緩存這些資源.
動態網頁如何設定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情況下的操作略
- //設定快取選項
- response.Clear();
- response.ClearContent();
- response.Headers["Last-Modified"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- response.Headers["ETag"] = id;//這裡假設的是根據不同的id
- response.CacheControl = "private";
- response.ExpiresAbsolute = DateTime.Now.AddMonths(6);
ETag是什麼意思?HTTP 協議規格說明定義ETag為“被請求變量的實體值” 。另一種說法是,ETag是一個可以與Web資源關聯的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSON或XML文件。服務器單獨負責判斷記號是什麼及其含義,並在HTTP響應頭中將其傳送到客戶端
asp.net web api的實現代碼如下:
- // 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;
- }
常見狀態碼:
一些常見的狀態碼為:
- 200 – 服務器成功返回網頁
- 404 – 請求的網頁不存在
- 503 – 服務器超時
下面提供 HTTP 狀態碼的完整列表。點選連結可瞭解詳情。您也可以訪問。
1xx(臨時響應)表示臨時響應並需要請求者繼續執行操作的狀態碼。
100(繼續) |
請求者應當繼續提出請求。伺服器返回此程式碼表示已收到請求的第一部分,正在等待其餘部分。 |
101(切換協議) |
請求者已要求伺服器切換協議,伺服器已確認並準備切換。 |
2xx (成功)
表示成功處理了請求的狀態碼。
200(成功) |
服務器已成功處理了請求。通常,這表示服務器提供了請求的網頁。如果是對您的 robots.txt 檔案顯示此狀態碼,則表示 Googlebot 已成功檢索到該檔案。 |
201(已創建) |
請求成功並且伺服器建立了新的資源。 |
202(已接受) |
服務器已接受請求,但尚未處理。 |
203(非授權資訊) |
服務器已成功處理了請求,但返回的資訊可能來自另一來源。 |
204(無內容) |
服務器成功處理了請求,但沒有返回任何內容。 |
205(重置內容) |
服務器成功處理了請求,但沒有返回任何內容。與 204 響應不同,此響應要求請求者重置文件檢視(例如,清除表單內容以輸入新內容)。 |
206(部分內容) |
服務器成功處理了部分 GET 請求。 |
3xx (重定向)要完成請求,需要進一步操作。通常,這些狀態碼用來重定向。Google 建議您在每次請求中使用重定向不要超過 5 次。您可以使用網站管理員工具檢視一下 Googlebot 在抓取重定向網頁時是否遇到問題。診斷下的網路抓取頁列出了由於重定向錯誤導致 Googlebot 無法抓取的網址。
300(多種選擇) |
針對請求,伺服器可執行多種操作。伺服器可根據請求者 (user agent) 選擇一項操作,或提供操作列表供請求者選擇。 |
301(永久移動) |
請求的網頁已永久移動到新位置。伺服器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。您應使用此代碼告訴 Googlebot 某個網頁或網站已永久移動到新位置。 |
302(臨時移動) |
服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來響應以後的請求。此代碼與響應 GET 和 HEAD 請求的 301 代碼類似,會自動將請求者轉到不同的位置,但您不應使用此代碼來告訴 Googlebot 某個網頁或網站已經移動,因為 Googlebot 會繼續抓取原有位置並編制索引。 |
303(查看其他位置) |
請求者應當對不同的位置使用單獨的 GET 請求來檢索響應時,伺服器返回此程式碼。對於除 HEAD 之外的所有請求,服務器會自動轉到其他位置。 |
304(未修改) |
自從上次請求後,請求的網頁未修改過。伺服器返回此響應時,不會返回網頁內容。 如果網頁自請求者上次請求後再也沒有更改過,您應將伺服器配置為返回此響應(稱為 If-Modified-Since HTTP 標頭)。伺服器可以告訴 Googlebot 自從上次抓取後網頁沒有變更,進而節省頻寬和開銷。 |
305(使用代理) |
請求者只能使用代理訪問請求的網頁。如果服務器返回此響應,還表示請求者應使用代理。 |
307(臨時重定向) |
服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來響應以後的請求。此代碼與響應 GET 和 HEAD 請求的 <a href=answer.py?answer=>301</a> 代碼類似,會自動將請求者轉到不同的位置,但您不應使用此代碼來告訴 Googlebot 某個頁面或網站已經移動,因為 Googlebot 會繼續抓取原有位置並編制索引。 |
4xx(請求錯誤)這些狀態碼錶示請求可能出錯,妨礙了伺服器的處理。
400(錯誤請求) |
服務器不理解請求的語法。 |
401(未授權) |
請求要求身份驗證。對於登入後請求的網頁,伺服器可能返回此響應。 |
403(禁止) |
服務器拒絕請求。如果您在 Googlebot 嘗試抓取您網站上的有效網頁時看到此狀態碼(您可以在 Google 網站管理員工具診斷下的網絡抓取頁面上看到此資訊),可能是您的服務器或主機拒絕了 Googlebot 訪問。 |
404(未找到) |
伺服器找不到請求的網頁。例如,對於伺服器上不存在的網頁經常會返回此程式碼。 如果您的網站上沒有 robots.txt 檔案,而您在 Google 網站管理員工具上看到此狀態碼,則這是正確的狀態碼。但是,如果您有 robots.txt 檔案而又看到此狀態碼,則說明您的 robots.txt 檔案可能命名錯誤或位於錯誤的位置(該檔案應當位於頂級域,名為 robots.txt)。 如果對於 Googlebot 抓取的網址看到此狀態碼(在”診斷”標籤的上),則表示 Googlebot 跟隨的可能是另一個頁面的無效連結(是舊連結或輸入有誤的連結)。 |
405(方法禁用) |
禁用請求中指定的方法。 |
406(不接受) |
無法使用請求的內容特性響應請求的網頁。 |
407(需要代理授權) |
此狀態碼與 <a href=answer.py?answer=35128>401(未授權)</a>類似,但指定請求者應當授權使用代理。如果伺服器返回此響應,還表示請求者應當使用代理。 |
40 |