2016-11-09 103 views
1

我向我的應用程序添加了一個自定義緩存行爲,類似於Thierry提出的in this article。對於每一個CSS,JS和HTML文件服務器在我的靜態內容我加入這兩個以下標題:我應該手動爲Restlet中的緩存請求(ETag)返回304響應嗎?

// Added by me 
ETag: "0c635aa7113262fac7606da2432e00f5" // md5(last_mod_date_of_file) 
Cache-Control: max-age=31536000 // one year 

// Automatically added by Restlet (probably Directory class?) 
Date: Wed, 09 Nov 2016 11:50:53 GMT 
Expires: Wed, 09 Nov 2016 12:00:53 GMT 
Last-Modified: Wed, 09 Nov 2016 17:30:56 GMT 

這工作得很好,但我注意到,在測試服務器上部署代碼和擊球F5在Chrome瀏覽器後,我再次獲取整個響應(HTTP 200返回)。

我注意到,這些請求都使用適當的標題太:

Cache-Control:max-age=0 
If-Modified-Since: Wed, 09 Nov 2016 17:30:56 GMT 
If-None-Match: "0c635aa7113262fac7606da2432e00f5" 

我的問題是,我應該做If-None-Match頭的任何手動驗證在我的服務器過濾器並返回然後 304迴應?還是由Restlet處理?

注意:這個問題有點奇怪,它似乎在我的本地開發環境中正常工作。我也有點困惑,爲什麼Expires由Restlet設置爲日期之前Last-Modified。我會嘗試調試,如果這是邪惡的根源,但它不會使我關於手動設置304狀態和檢查服務器上的ETags的問題失效。

+0

一個典型的場景是在瀏覽器和Java應用程序之間建立緩存逆向代理。在這種情況下,304由它處理,你不需要在應用程序內部打擾。請注意,因爲邊緣服務器可能會解釋不同於瀏覽器或HTTP標準定義的標頭。例如。 NGINX非常(錯過)可配置。 – cruftex

+1

從上面的標題中,Last-Expires是當前時間10分鐘後。其實最後修改的時間接錯了。也許在構建和生產上有不同的時間或區域? – cruftex

回答

2

好的,所以我已經能夠弄清楚這一點,我在下面發佈答案。

我應該在我的服務器過濾器中對If-None-Match標題做任何手動驗證並返回304響應嗎?

不,您不必親自手動操作。這由Restlet自動處理(DirectoryServerResource負責)。

那麼問題是什麼?

問題確實是Last-Modified標題被設置爲未來日期。發生這種情況是因爲我的生產服務器在UTC-8時區,而我正在開發UTC+1

我是如何解決它的?

它需要熟悉Restlet API,但解決方案並不重要。我確信,當我的應用程序啓動時,它會從操作系統讀取我的應用程序目錄的File Last Modified屬性,因爲這是我想在Last-Modified標頭中使用的值。 現在,您不能僅在responseFilter中設置此標頭,因爲HTTP緩存標頭的自動處理髮生在提及的DirectoryServerResource類之前。因此,解決辦法是:

創建延伸類DSR(給你所有的自動緩存處理免費),以便Last-Modified頭之前,這個邏輯踢設置並修改其handle()方法:

public class WebAssetsResource extends DirectoryServerResource { 
    @Override 
    public Representation handle() { 
     Date desiredDate = ...; // I read this from File System 
     getInfo().setModificationDate(desiredDate); 
     return super.handle(); // Automatic logic will use desired date 
    } 
} 

現在,請確保您新創建的資源由自定義Directory類使用。

public class CachedWebAssetsDirectory extends Directory { 
    public CachedWebAssetsDirectory(Context context, Reference rootLocalReference) { 
     super(context, rootLocalReference); 
     setTargetClass(WebAssetsResource.class); // Needed so that Restlet will use our implementation of a ServerResource to serve static files 
    } 
} 

後,您可以使用CachedWebAssetsDirectory如你所願,建立在此基礎之上的任何自定義過濾器。

相關問題