Expires,Cache-Control,Last-Modified和ETag是RFC 2616(HTTP/1.1)协议中与Web缓存相关的几个字段。前两个用于控制缓存过期日期,后两个用于验证网页的有效性。应该注意的是,HTTP/1.0具有较弱的缓存控制机制:Pragma,它使用HTTP/1.0缓存来忽略Expires和Cache-Control头。我们以Apache2.0服务器为例。我们只讨论HTTP/1.1协议。
过期
Expires字段声明浏览器不再缓存网页或URL地址的时间。超过此时间后,浏览器应联系原始服务器。 RFC告诉我们:“因为推断的到期时间可能会降低语义透明度,所以应谨慎使用,我们鼓励原始服务器提供准确的到期时间。”
对于一般的纯静态页面,例如html,gif,jpg,css,js,默认安装的Apache服务器不会在响应头中添加此字段。在Firefox浏览器收到响应后,如果发现没有Expires字段,浏览器会根据文件类型和“Last-Modified”字段推断出合适的到期时间,并将其存储在客户端上。估计时间通常是在收到响应时间后约三天。
Apache的expires_module模块可以自动将Expires字段添加到Http响应头。在Apache httpd.conf文件中执行以下操作:
#启用expires_module模块
LoadModule expires_module modules/mod_expires.so
#启用有效性控制
ExpiresActive On
#GIF有效期为1个月
ExpiresByType image/gif A2592000
#HTML文档在上次修改时间后的一周内有效
ExpiresByType text/html M604800
#以下的意思是类似的
ExpiresByType text/css“now plus 2 month”
ExpiresByType text/js“now plus 2 day”
ExpiresByType image/jpeg“access plus 2 month”
ExpiresByType image/bmp“access plus 2 month”
ExpiresByType image/x-icon“访问加2个月”
ExpiresByType image/png“access plus 2 month”
对于动态页面,如果在页面内没有强制Expires的功能,例如标题(“Expires:”.gmdate(“D,d MYH: i: s”)。“GMT”),Apache服务器将放置Wed ,1984年1月11日05: 00: 00 GMT
返回到浏览器作为Expires字段的内容。也就是说,动态页面始终无效。浏览器仍将保存已过期的动态页面。
可以发现Firefox浏览器始终缓存所有页面,无论失效,无失败或没有过期时间。即使在缓存中声明的网页的生效日期是1970-01-01 08: 00: 00,浏览器仍将在缓存中发送文件的Last-Modified和ETag字段。如果服务器端验证通过并返回到304状态,则浏览器仍将使用此缓存。
缓存控制
可以在Cache-Control字段中声明更多元素,例如no-cache,must-revalidate,max-age=0等。这些元素用于指示页面缓存的时间长度,缓存方式,如何将其转换为不同的介质以及如何将其存储在持久性介质中。但是,任何Cache-Control指令都不保证隐私或数据安全。 “私有”和“无存储”指令可以为隐私和安全提供一些保护,但它们不能用于替换身份验证和加密。
Apache的mod_cern_meta模块允许控制文件级Http响应头,它还可以配置Cache-Control头(或任何其他头)。响应头文件是放在原始目录的子目录中的文件,以原始文件名命名。有关具体用法,请参阅Apache的官方网站。
其中Cache-Control: max-age表示到期日期。如果未启动mod_cern_meta模块,Apache服务器会将Expires字段中的日期转换为以秒为单位的delta值,并将其分配给max-age。如果启动了mod_cern_meta模块并配置了max-age值,Apache将覆盖Expires字段。与此同时,max-age意味着Canche-Control:公开。这样,浏览器接受的Cache-Control: max-age和Expires值是相同的。
如果到期日期Cache-Control: max-ag=0或为负数,浏览器将在相应的缓存中将Expires设置为1970-01-01 08: 00: 00。
最后修改
Last-Modified和ETag是与条件请求相关的两个字段。如果缓存收到页面请求,它会发送一个验证请求,询问服务器页面是否已更改,并在HTTP标头中使用“ETag”和“If Modify Since”标头。服务器基于该信息确定是否存在更新信息。如果不是,则返回HTTP 304(Not Modify);如果有更新,则返回HTTP 200和更新的页面内容,并带有新的“ETag”和“Last-Modified”。
使用此机制,您可以避免重复向浏览器发送文件,但仍会生成HTTP请求。
通常,纯静态页面将具有Last-Modified信息。 Apache服务器将读取页面文件中的Last-Modified信息并将其添加到http响应头。
对于动态页面,如果没有强制Last-Modified在页面内的功能,例如标题(“Last-Modified:”.gmdate(“D,d MYH: i: s”)。“GMT”),Apache server将当前时间作为Last-Modified返回给浏览器。
无论是纯静态页面还是动态页面,Firefox浏览器都会在从服务器接收响应时巧妙地设置缓存页面的Last-Modified,而不是遵循http响应头中的Last-Modified字段。
ETag的
由于有Last-Modified,为什么要使用ETag字段?因为如果在不到一秒的时间内对文件进行两次更改,则Last-Modified将不正确。因此,HTTP/1.1使用Entity Tag标头提供更严格的身份验证。
默认情况下,Apache服务器将ETag字段添加到所有静态和动态文件的响应标头中。
可以通过FileETag指令在Apache httpd.conf文件中配置此选项。当文档基于文件时,FileETag指令配置用于创建Etag(实体标签)响应头的文件的属性。在Apache 1.3.22及更早版本中,ETag的值是通过散列文件的索引部分(INode),大小(大小)和最后修改时间(MTime)获得的。如果目录的配置包含’FileETag INode MTime Size’并且其子目录之一包含’FileETag -INode’,则此子目录的设置(并将由其下的任何子目录继承)将等效于’FileETag MTime Size’ 。
在多个负载平衡的服务器环境中,同一文件将具有不同的etag或文件修改日期,浏览器将每次重新下载。设置’FileETag None’将导致响应头不再包含ETag字段。