我应该在Restlet中为缓存请求(ETag)手动返回304响应吗?

时间:2016-11-09 12:29:16

标签: java caching restlet etag restlet-2.3.1

我在我的应用程序中添加了一个自定义缓存行为,类似于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的问题无效。

1 个答案:

答案 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,在此基础上构建任何自定义过滤器。