2016-11-09 112 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如你所愿,建立在此基础之上的任何自定义过滤器。

相关问题