HTTP缓存仅仅为安全方法工作(比如GET和HEAD)。要安全意味着当它为某个请求服务时从来不会改变服务器上应用程序的状态。(当然你可以写日志信息,缓存数据等)。这里有两个很合理的后果(consequences):
当你的应用程序回复一个GET或者HEAD请求时,你绝对不会改变你应用程序的状态。即使你不用网关缓存,代理缓存的存在意味着任何GET和HEAD请求可能会或者可能不会真的达到你的服务器。
不要期望PUT,POST或者DELETE方法被缓存。这些方法被使用意味着你应用程序状态的改变。缓存它们将阻止某种请求访问或者改变你的应用程序。
缓存规则和默认设置
HTTP 1.1 默认情况下允许缓存任何事情除非有一个显式的Cache-Control头。实践中,大多数缓存当请求有cookie,一个授权头,使用一个非安全的方法(比如PUT,POST,DELETE)或者当请求有一个重定向代码时,不会进行任何缓存活动。
当开发者没有做任何设置时,Symfony2 会自动按照下面的规则设置一个合理的比较保守的Cache-Control头:
如果没有缓存头被定义(Cache-Control,Expires,ETag 或者Last-Modified),Cache-Control被设置为no-cache,意味着该response将不会被缓存。
如果Cache-Control 为空(但是有另一个缓存头存在),它的值被设置为private,must-revalidate;
如果至少一个Cache-Control指令被设置,并且没有'public'或者‘private'指令被显式的添加,Symfony2 会自动添加一个private指令(除去s-maxage 被设置的情况)。
HTTP过期和校验
HTTP规范定义了两个缓存模型:
过期模型,你只需要通过包含一个Cache-Control和/或者一个Expires头来指定一个Response应该多长时间被考虑“新鲜”问题。缓存理解过期将不再让相同的请求回复,直到缓存的版本达到它过期时间成为“stale"陈旧。
校验模型,当页面时真正的动态页面时(他们的展现经常变化),校验模型就经常需要了。这种模型,缓存存储response,但是要求服务对每个请求是否缓存response依然进行校验。
应用程序使用唯一的response 标示符(ETag 头) 和/或者 时间戳(Last-Modified 头)来检查页面自从被缓存后是否放生了变化。
这两个模型的目标是通过依靠一个缓存存储并返回"新鲜" response,使得应用程序从不生成相同的response两次。
过期:
过期模型是在这两个模型中是更加有效和简单明确的模型,它应该在任何时候都有被使用的可能。当一个response使用一过期方式被缓存,缓存将存储response并为请求直接返回它而不去访问应用程序,直到它过期。
过期模型可以被熟练的使用一两个,几乎相同的,HTTP头:比如 Expires或cache - control。
过期和Expires 头
根据HTTP规范,Expires头字段提供一个日期/时间,过了这个日期或时间后它的response就被认为是陈旧的了。Expires头可以被Response的setExpires()方法设置。它要求一个DateTime实例作为输入参数。
$date = new DateTime(); $date->modify('+600 seconds'); $response->setExpires($date);
生成的HTTP头的结果如下:
Expires: Thu, 01 Mar 2011 16:00:00 GMT
注意,因为规范的需要setExprise()方法会自动把日期转换为GMT时区。
我们注意到在HTTP规范1.1版之前,源服务不需要发送一个Date头。 因此缓存(比如浏览器)可能需要依靠它本地的始终来评估Expires头,造成计算生命周期时时钟偏差。 Expires头的另一个限制是规范规定:"HTTP/1.1服务不应该发送Expires日期未来超过一年。"
过期和Cache-Control 头
因为Expires头的限制,大多时候,你应该采用Cache-Control头来替代它。回想一下,Cache-Control头是用来指定多个不同缓存指令的。对于过期来说,有两个指令,max-age 和 s-maxage。第一个被所有的缓存使用,然而第二个仅仅被用于共享缓存。
// 设置一个秒数,过了这个秒数后response就被认为是陈旧的了。 $response->setMaxAge(600); // 同上,但是只用于共享缓存。 $response->setSharedMaxAge(600); Cache-Control头将使用如下格式(它可能还有其它指令): Cache-Control: max-age=600, s-maxage=600
校验:
一旦底层数据发生变化需要立刻对缓存资源进行更新时,过期模型就显得力不从心了。在过期模型下,应用程序不会被要求返回更新的response直到缓存最后过期变为陈旧内容以后。