我正在尝试使浏览器和/或代理缓存适合我的Web应用程序(可能是python / flask,但我认为这不是特别重要)。在我阅读的有关ETag的所有内容中,通常将它们讨论为(可能是静态的)资源的哈希。
就我而言,我的数据库中有一类不可编辑的对象。可以为这些对象中的每一个生成几个不同的视图。生成视图(至少其中一些视图)需要在服务器上进行一些工作,但是通常,结果输出是轻量级的。因此,进行生成整个页面然后进行哈希处理的工作效率很低,我也可能只在该时间发送响应。
我的想法是,因为每个视图都是基于一个不变的数据库对象构建的,所以该对象的键(加上请求的URL)足以知道客户端的缓存是否良好。但这意味着对许多不同的资源使用相同的ETag。据我所知,这似乎应该可行,但是
我的应用程序具有以下形式的URL:
example.com/view/<name>/<version>/<view>/<additional view args>
DB在<name>
和<version>
的组合上具有唯一索引。但是对于版本,有一个特殊的关键字latest
,它使服务器使用<name>
查找最新的条目。无论请求什么视图,它都由按名称和版本找到的对象完全定义。因此,如果客户端发送带有If-none-match: <key>
的请求标头,则无论请求的视图如何,我总是会返回304,除非(a)他们请求了latest
版本,并且(b)DB中最新版本的主键没有与If-none-match
标头匹配。
我建议阅读RFC 7232,这很简单,将使您对条件验证有很好的理解。
您希望在知道是否存在ETag匹配之前避免计算响应的成本既明智又允许。正如标准明确指出的那样,由您决定不透明值。哈希只是其中的一种特殊情况。 (实际上,它们需要特别提及,因为理论上可能发生冲突。)它们specifically给出了使用版本号的示例:
例如,具有实现特定版本的资源应用于所有更改的内容可能使用内部修订号,也许结合差异标识符进行内容协商,以准确区分表示形式。
您还询问每个资源的ETag是否需要不同。 answer是否:
有在不同的表示形式之间没有唯一性的含义资源(即,同一强验证器可能用于同时表示多个资源表示这些表示形式是等效的。
有些人会担心向客户端公开数据库ID。我对此没有强烈的感觉,但是当然可以通过对ID进行散列或其他方式很容易避免。
不过,看看您的特定设计,似乎只需对ETag使用version
就足够了。实际上,对于latest
以外的所有资源,似乎只有一种可能的表示形式。如果是这样,则应将这些条目设置为永久缓存,并且ETag是什么并不重要。然后对于latest
,请使用较短的缓存时间,并为ETag使用version
(或主键,如果需要)。