【问题标题】:Should I manually return 304 response for cached requests (ETag) in Restlet?我应该在 Restlet 中手动为缓存请求(ETag)返回 304 响应吗?
【发布时间】:2017-03-23 06:27:09
【问题描述】:

我向我的应用程序添加了自定义缓存行为,类似于 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 设置为 before Last-Modified 的日期,我也有点困惑。如果这是邪恶的根源,我会尝试调试,但这不会使我关于手动设置 304 状态和检查服务器上的 ETag 的问题无效。

【问题讨论】:

  • 一个典型的场景是在浏览器和 Java 应用程序之间有一个缓存反向代理。在这种情况下,304 由它处理,您无需在应用程序内部打扰。请小心,因为边缘服务器可能会解释与浏览器或 HTTP 标准定义不同的标头。例如。 NGINX 是高度可配置的。
  • 从上面的标题中,Last-Expires 是当前时间之后的 10 分钟。实际上最后修改的时间接缝是错误的。也许构建和生产的时间或区域不同?

标签: java caching restlet etag restlet-2.3.1


【解决方案1】:

好的,所以我已经能够解决这个问题,我将在下面发布答案。

我是否应该在我的服务器过滤器中手动验证 If-None-Match 标头并返回 304 响应?

不,您不必自己手动执行此操作。这由 Restlet 自动处理(DirectoryServerResource 负责处理)。

当时有什么问题?

问题确实在于Last-Modified 标头设置为未来日期。发生这种情况是因为我的生产服务器位于 UTC-8 时区,而我正在开发 UTC+1

我是如何解决的?

它需要熟悉 Restlet API,但当时的解决方案是微不足道的。我确保当我的应用程序启动时,它会从操作系统读取我的应用程序目录的File Last Modified 属性,因为这是我想在Last-Modified 标头中使用的值。 现在,您不能只在Filter 中的response 上设置此标头,因为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,在此基础上构建任何自定义过滤器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-02
    • 2013-12-24
    • 2017-04-04
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 2017-03-22
    • 2011-02-11
    相关资源
    最近更新 更多