我在我的应用程序中添加了一个自定义缓存行为,类似于Thierry提出的in this article。对于我的静态内容中的每个CSS,JS和HTML文件服务器,我添加了以下两个标题:
// 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
这很好用,但是我注意到在测试服务器上部署代码并在Chrome中点击F5
后,我再次获取整个响应(返回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状态和检查服务器上的ETag的问题无效。
答案 0 :(得分:2)
好的,所以我已经能够解决这个问题,我在下面发布答案。
我应该在服务器过滤器中对If-None-Match标头进行任何手动验证,然后返回304响应吗?
不,您不必亲自手动执行此操作。这是由Restlet自动处理的(DirectoryServerResource
负责处理)。
那是什么问题?
问题确实是将Last-Modified
标头设置为将来的日期。发生这种情况是因为我的生产服务器位于UTC-8
时区,而我正在UTC+1
开发。
我是如何修复的?
它需要熟悉Restlet API,但解决方案是微不足道的。我确保在我的应用程序启动时,它从操作系统读取我的应用程序目录的File Last Modified
属性,因为这是我想在Last-Modified
标头中使用的值。
现在,您不能只在response
中的Filter
上设置此标头,因为HTTP缓存标头的自动处理发生在前面提到的DirectoryServerResource
类中。所以解决方案如下:
创建一个扩展DSR的类(免费提供所有自动缓存处理)并修改其handle()
方法,以便在此逻辑开始之前设置Last-Modified
标头:
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
,在此基础上构建任何自定义过滤器。