首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

HTTP 請求標頭 If-Modified-Since 完整解析與快取優化實戰

     編輯:關於ASP.NET

If-Modified-Since (IMS) 是 HTTP/1.1 標準請求標頭,配合回應標頭 Last-Modified 實現條件式請求:瀏覽器將快取資源的最後修改時間送回伺服器,伺服器比對後決定回傳 304 Not Modified(不含實體)或 200 OK(含新內容),大幅節省頻寬與延遲。

運作流程

  1. 首次請求:無 IMS 標頭 → 伺服器回傳 200 OK + 內容 + Last-Modified: GMT時間
  2. 瀏覽器快取內容與 Last-Modified 時間
  3. 後續請求:自動加上 If-Modified-Since: GMT時間
  4. 伺服器比對:
    • 資源未變 → 304 Not Modified(無 Response Body)
    • 資源已更新 → 200 OK + 新內容 + 新 Last-Modified
  5. 瀏覽器收到 304 直接讀取本地快取

Fiddler 實測示範

第一次請求:

  • Request 無 If-Modified-Since
  • Response: HTTP/1.1 200 OK, Last-Modified: Wed, 04 Jan 2017 02:45:10 GMT

Fiddler 捕獲首次請求回應

第二次請求:

  • Request: If-Modified-Since: Wed, 04 Jan 2017 02:45:10 GMT
  • Response: HTTP/1.1 304 Not Modified(無內容,極小封包)

ASP.NET 實作支援 IMS

public class StaticFileHandler : IHttpHandler {
    public void ProcessRequest(HttpContext context) {
        string filePath = context.Request.MapPath(context.Request.Path);
        if (!File.Exists(filePath)) {
            context.Response.StatusCode = 404;
            return;
        }
        
        FileInfo fi = new FileInfo(filePath);
        DateTime lastModified = fi.LastWriteTimeUtc;
        
        // 設定 Last-Modified 回應標頭
        context.Response.Cache.SetLastModified(lastModified);
        
        // 檢查 If-Modified-Since
        string imsHeader = context.Request.Headers["If-Modified-Since"];
        if (!string.IsNullOrEmpty(imsHeader)) {
            if (DateTime.TryParse(imsHeader, out DateTime clientTime)) {
                // 比較精度到秒(HTTP 日期格式無毫秒)
                if (clientTime >= lastModified.AddSeconds(-1)) {
                    context.Response.StatusCode = 304;
                    context.Response.StatusDescription = "Not Modified";
                    context.Response.SuppressContent = true; // 不輸出 Body
                    return;
                }
            }
        }
        
        // 未修改或無 IMS → 輸出檔案
        context.Response.ContentType = GetMimeType(fi.Extension);
        context.Response.WriteFile(filePath);
    }
    
    public bool IsReusable => true;
}

IIS 靜態檔案自動支援

IIS 7+ 整合模式下,靜態檔案(.html, .css, .js, .jpg 等)由 StaticFileModule 自動處理 IMS/Last-Modified/ETag,無需撰寫代碼。確保 web.config 未移除該模組:

<system.webServer>
  <modules>
    <remove name="StaticFileModule" /> <!-- 勿移除 -->
  </modules>
</system.webServer>

ETag vs Last-Modified

特性Last-ModifiedETag
精度秒級內容雜湊/版本號,更精確
適用場景靜態檔案、資料庫更新時間動態內容、分散式系統
請求標頭If-Modified-SinceIf-None-Match
共存可同時啟用,伺服器任一匹配即回 304

ASP.NET MVC 輸出快取整合

[OutputCache(Duration = 3600, VaryByParam = "none", Location = OutputCacheLocation.ServerAndClient)]
public ActionResult Article(int id) {
    var article = repo.Get(id);
    // 手動設定 Last-Modified 為文章更新時間
    Response.Cache.SetLastModified(article.UpdatedAt);
    return View(article);
}

常見問題排查

  • 304 不生效:檢查伺服器時間與客戶端時間一致性、確認 Last-Modified 格式為 RFC 1123 GMT
  • 動態頁面每次都是 200:未設定 Last-Modified 或 ETag,或程式碼每次產生新物件導致 ETag 異
  • CDN 快取未更新:確認 Origin 回應正確 304/200,CDN 設定遵循標準快取控制標頭
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved