通过HTTP头控制浏览器的缓存

浏览器缓存是提高用户体验和提升程序性能的一个很重要的途径,通过浏览器的缓存控制,可以对实时性要求不高的数据进行缓存,可以减少甚至不需要再次对服务器的请求就可以显示数据。

本文将介绍如果通过HTTP协议中的header来控制浏览器的缓存行为,建议大家在看的时候写代码试验下,这样对这些header的理解会更深一点。

HTTP协议定义了四个可以用来控制浏览器缓存的HTTP头,它们是:

Last-Modified
Expires
Pragma: no-cache
Cache-Control

下面分别介绍HTTP/1.0和HTTP/1.1协议下的缓存解决方法。

HTTP/1.0

在HTTP/1.0协议中,Last-Modified是控制缓存的一个非常重要的HTTP头。如果需要控制浏览器的缓存,服务器首先必须发送一 个以UTC时间为值的Last-Modifeid头,当第二次访问这个页面时,浏览器会发送一个If-Modified-Since头给服务器,让服务器 判断是否有必要更新内容,这个If-Modified-Since头的值就是上次访问页面时,浏览器发送的Last-Modifeid头的值。

Expires是HTTP/1.0中另外一个很重要的HTTP头,它表示缓存的存在时间,告诉客户端浏览器在这个时间之前不对服务器发送请求,而直接使用浏览器的缓存。

在HTTP/1.0中,可以使用Pragma: no-cache头来告诉浏览器不要缓存内容,它相当于HTTP/1.1中的Cache-Control:no-cache。

如果要使用HTTP/1.0协议来告诉客户端(包括任何中介代理)是否要缓存数据,可以使用以下代码,如果设置liftTime参数则告诉客户端数据缓存的生命期为lifeTime的值:

Php代码
  1. function http_10_cache_headers($lifeTime = null){  
  2.     $gmtime = time();  
  3.     if ($lifeTime){  
  4.         $gmtime += $lifeTime;  
  5.     }else {  
  6.         header("Pragma: no-cache");  
  7.     }  
  8.     $gmtime = gmdate('D, d M Y H:i:s',$gmtime).' GMT';  
  9.     header("Last-Modified: $gmtime");  
  10.     header("Expires: $gmtime");  
  11. }  
function http_10_cache_headers($lifeTime = null){
	$gmtime = time();
	if ($lifeTime){
		$gmtime += $lifeTime;
	}else {
		header("Pragma: no-cache");
	}
	$gmtime = gmdate('D, d M Y H:i:s',$gmtime).' GMT';
	header("Last-Modified: $gmtime");
	header("Expires: $gmtime");
}


HTTP/1.0协议的这种实现方式的缺点是,服务器和客户端的时间有可能是不同步的,这样会造成缓存的实现达不到预期效果。HTTP/1.1协议用Cache-Control头解决了这个问题。

HTTP/1.1

Cache-Control响应头的语法为:
Cache-Control = “Cache-Control” “:”; #缓存响应指令

缓存响应指令为一下几个中的任意一个:

   1. public
   2. private
   3. no-cache
   4. no-store
   5. no-transform
   6. must-revalidate
   7. proxy-revalidate
   8. max-age=时间
   9. s-maxage=时间

详细介绍一下这几个指令的具体含义:

   1. public 指示响应数据可以被任何客户端缓存
   2. private 指示响应数据可以被非共享缓存所缓存。这表明响应的数据可以被发送请求的浏览器缓存,而不能被中介所缓存
   3. no-cache 指示响应数据不能被任何接受响应的客户端所缓存
   4. no-store 指示所传送的响应数据除了不能被缓存,也不能存入磁盘。一般用于敏感数据,以免数据被复制。
   5. must-revalidate 指示所有的缓存都必须重新验证,在这个过程中,浏览器会发送一个If-Modified-Since头。如果服务器程序验证得出当前的响应数据为最新的数 据,那么服务器应当返回一个304 Not Modified响应给客户端,否则响应数据将再次被发送到客户端。
   6. proxy-revalidate 与must-revalidate相似,不同的是用来指示共享缓存。
   7. max-age 数据经过max-age设置的秒数后就会失效,相当于HTTP/1.0中的Expires头。如果在一次响应中同时设置了max-age和 Expires,那么max-age将具有较高的优先级。
   8. s-maxage 与max-age相似,不同的是用来指示共享缓存。

了解这些指令后就可以根据不同的需求来发送不同的HTTP头。

根据响应的内容是否更改来确定是否发送新的响应数据:
Php代码
  1. function validate_cache_headers($my_modtime)  
  2. {  
  3.     $pretty_modtime = gmdate('D, d M Y H:i:s', $my_modtime) . ' GMT';  
  4.     if($_SERVER['IF_MODIFIED_SINCE'] == $gmt_mtime) {  
  5.         header("HTTP/1.1 304 Not Modified");  
  6.         exit;  
  7.     }  
  8.     else {  
  9.         header("Cache-Control: must-revalidate");  
  10.         header("Last-Modified: $pretty_modtime");  
  11.     }  
  12. }  
function validate_cache_headers($my_modtime)
{
    $pretty_modtime = gmdate('D, d M Y H:i:s', $my_modtime) . ' GMT';
    if($_SERVER['IF_MODIFIED_SINCE'] == $gmt_mtime) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }
    else {
        header("Cache-Control: must-revalidate");
        header("Last-Modified: $pretty_modtime");
    }
}


这个函数接受一个页面最后修改的时间作为参数,将它与浏览器发送的If-Modified-Since的时间比较,如果两者相同,说明缓存的数据 版本是最新的,就可以发送一个304状态码给浏览器,让它使用缓存的数据;否则,发送新的Last-Modified头和设置必须验证缓存的数据版本的 Cache-Control头。

如果想要让响应数据被代理缓存一分钟,可以这么做:

Php代码
  1. function cache_novalidate($interval = 60)  
  2. {  
  3.     $now = time();  
  4.     $pretty_lmtime = gmdate('D, d M Y H:i:s', $now) . ' GMT';  
  5.     $pretty_extime = gmdate('D, d M Y H:i:s', $now + $interval) . 'GMT';  
  6.     // 向后兼容HTTP/1.0  
  7.     header("Last Modified: $pretty_lmtime");  
  8.     header("Expires: $pretty_extime");  
  9.     // 支持HTTP/1.1  
  10.     header("Cache-Control: public,max-age=$interval");  
  11. }  
function cache_novalidate($interval = 60)
{
    $now = time();
    $pretty_lmtime = gmdate('D, d M Y H:i:s', $now) . ' GMT';
    $pretty_extime = gmdate('D, d M Y H:i:s', $now + $interval) . 'GMT';
    // 向后兼容HTTP/1.0
    header("Last Modified: $pretty_lmtime");
    header("Expires: $pretty_extime");
    // 支持HTTP/1.1
    header("Cache-Control: public,max-age=$interval");
}


如果只想让浏览器缓存响应数据,可以这么做:

Php代码
  1. function cache_browser($interval = 60)  
  2. {  
  3.     $now = time();  
  4.     $pretty_lmtime = gmdate('D, d M Y H:i:s', $now) . ' GMT';  
  5.     $pretty_extime = gmdate('D, d M Y H:i:s', $now + $interval) . ' GMT';  
  6.     // 向后兼容HTTP/1.0  
  7.     header("Last Modified: $pretty_lmtime");  
  8.     header("Expires: $pretty_extime");  
  9.     // 支持HTTP/1.1  
  10.     header("Cache-Control: private,max-age=$interval,s-maxage=0");  
  11. }  
function cache_browser($interval = 60)
{
    $now = time();
    $pretty_lmtime = gmdate('D, d M Y H:i:s', $now) . ' GMT';
    $pretty_extime = gmdate('D, d M Y H:i:s', $now + $interval) . ' GMT';
    // 向后兼容HTTP/1.0
    header("Last Modified: $pretty_lmtime");
    header("Expires: $pretty_extime");
    // 支持HTTP/1.1
    header("Cache-Control: private,max-age=$interval,s-maxage=0");
}


如果要让数据不被任何客户端缓存:

Php代码
  1. function cache_none($interval = 60)  
  2. {  
  3.   // 向后兼容HTTP/1.0  
  4.   header("Expires: 0");  
  5.   header("Pragma: no-cache");  
  6.   // 支持HTTP/1.1  
  7.   header("Cache-Control: no-cache,no-store,max-age=0,s-maxage=0,must-revalidate");  
  8. }  
function cache_none($interval = 60)
{
  // 向后兼容HTTP/1.0
  header("Expires: 0");
  header("Pragma: no-cache");
  // 支持HTTP/1.1
  header("Cache-Control: no-cache,no-store,max-age=0,s-maxage=0,must-revalidate");
}


当调用session_start()时,PHP会自动发送一个no-cache类的头来阻止缓存数据,

要注意的是:
通过POST方法发送的请求不能以如上所述的方式缓存。

转自:  http://lizhihui.javaeye.com/blog/585336
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卷边书_王诣

您的鼓励,是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值