剛剛開始使用Fiddler的用戶經常會對Fiddler的網絡會話(Web Sessions)列表中的HTTP/304響應感到困惑:
如果客戶端發送的是一個條件驗證(Conditional Validation)請求,則web服務器可能會返回HTTP/304響應,這就表明了客戶端中所請求資源的緩存仍然是有效的,也就是說該資源從上次緩存到現在並沒有被修改過.條件請求可以在確保客戶端的資源是最新的同時避免因每次都請求完整資源給服務器帶來的性能問題.
辨別條件請求
當客戶端緩存了目標資源但不確定該緩存資源是否是最新版本的時候,就會發送一個條件請求.在Fiddler中,你可以在Headers Inspector查找相關請求頭,這樣就可以辨別出一個請求是否是條件請求.
在進行條件請求時,客戶端會提供給服務器一個If-Modified-Since請求頭,其值為服務器上次返回的Last-Modified響應頭中的日期值,還會提供一個If-None-Match請求頭,值為服務器上次返回的ETag響應頭的值:
服務器會讀取到這兩個請求頭中的值,判斷出客戶端緩存的資源是否是最新的,如果是的話,服務器就會返回HTTP/304 Not Modified響應,但沒有響應體.客戶端收到304響應后,就會從緩存中讀取對應的資源.
另一種情況是,如果服務器認為客戶端緩存的資源已經過期了,那么服務器就會返回HTTP/200 OK響應,響應體就是該資源當前最新的內容.客戶端收到200響應后,就會用新的響應體覆蓋掉舊的緩存資源.
只有在客戶端緩存了對應資源且該資源的響應頭中包含了Last-Modified或ETag的情況下,才可能發送條件請求.如果這兩個頭都不存在,則必須無條件(unconditionally)請求該資源,服務器也就必須返回完整的資源數據.
為什么要使用條件請求
當用戶訪問一個網頁時,條件請求可以加速網頁的打開時間(因為可以省去傳輸整個響應體的時間),但仍然會有網絡延遲,因為瀏覽器還是得為每個資源生成一條條件請求,並且等到服務器返回HTTP/304響應,才能讀取緩存來顯示網頁.更理想的情況是,服務器在響應上指定Cache-Control或Expires指令,這樣客戶端就能知道該資源的可用時間為多長,也就能跳過條件請求的步驟,直接使用緩存中的資源了.可是,即使服務器提供了這些信息,在下列情況下仍然需要使用條件請求:
- 在超過服務器指定的過期時間之后
- 如果用戶執行了刷新操作的話
在上節給出的圖片中,請求頭中包含了一個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是通過省略條件請求頭來實現無緩存請求的:
如果你想全局阻止HTTP/304響應,可以這么做:首先清除瀏覽器的緩存,可以使用Fiddler工具欄上的Clear Cache按鈕(僅能清除Internet Explorer緩存),或者在瀏覽器上按CTRL+SHIFT+DELETE(所有瀏覽器都支持).在清除瀏覽器的緩存之后,回到Fiddler中,在菜單中選擇Rules > Performance > Disable Caching選項,然后Fiddler就會:刪除所有請求中的條件請求相同的請求頭以及所有響應中的緩存時間相關的響應頭.此外,還會在每個請求中添加Pragma: no-cache請求頭,在每個響應中添加Cache-Control: no-cache響應頭,阻止瀏覽器緩存這些資源.