主要涉及到 Header 里面三个属性
lastModified:设定一个最后修改时间,浏览器下次访问的时候,发送一个”If-Modified-Sinc”的头信息,如果内容在这个时间之后没有更新,服务器直接返回一个304 Not Modified而不传输详细内容,可以节省带宽。
Etag:设定一个标记,浏览器下次访问时,发送一个”If-None-Match”的头信息,如果服务器内容还是这个标记没变,也直接返回一个304 Not Modified而不传输详细内容,同样可以节省带宽。
Expires:设定一个过期时间,如果当前请求在这个过期时间之类,则不发送HTTP请求,不仅可以节约服务器带宽,还可以减少服务器HTTP请求数。
Cache-control: max-age=seconds 缓存相对时间 seconds 是缓存的秒数 即第一次访问后 多少秒之内再访问直接访问的时候浏览器本地缓存 不会访问服务器
过程如下:
1.客户端请求一个页面(A)。
2.服务器返回页面A,并在给A加上一个Last-Modified/ETag。
3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
5.服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。
相关函数
//http header 状态码 和 对应描述
$statusTexts = array(
'100' => 'Continue',
'101' => 'Switching Protocols',
'200' => 'OK',
'201' => 'Created',
'202' => 'Accepted',
'203' => 'Non-Authoritative Information',
'204' => 'No Content',
'205' => 'Reset Content',
'206' => 'Partial Content',
'300' => 'Multiple Choices',
'301' => 'Moved Permanently',
'302' => 'Found',
'303' => 'See Other',
'304' => 'Not Modified',
'305' => 'Use Proxy',
'306' => '(Unused)',
'307' => 'Temporary Redirect',
'400' => 'Bad Request',
'401' => 'Unauthorized',
'402' => 'Payment Required',
'403' => 'Forbidden',
'404' => 'Not Found',
'405' => 'Method Not Allowed',
'406' => 'Not Acceptable',
'407' => 'Proxy Authentication Required',
'408' => 'Request Timeout',
'409' => 'Conflict',
'410' => 'Gone',
'411' => 'Length Required',
'412' => 'Precondition Failed',
'413' => 'Request Entity Too Large',
'414' => 'Request-URI Too Long',
'415' => 'Unsupported Media Type',
'416' => 'Requested Range Not Satisfiable',
'417' => 'Expectation Failed',
'500' => 'Internal Server Error',
'501' => 'Not Implemented',
'502' => 'Bad Gateway',
'503' => 'Service Unavailable',
'504' => 'Gateway Timeout',
'505' => 'HTTP Version Not Supported',
);
//设置缓存过期时间
function expires($seconds = 1800)
{
$time = date('D, d M Y H:i:s', time() + $seconds) . ' GMT';
header("Expires: $time");
}
//返回指定header状态信息
function statusCode($code, $text = null)
{
global $statusTexts;//http header 状态
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
$text = (null === $text) ? $statusTexts[$code] : $text;
$status = "$protocol $code $text";
header($status);
}
//lastModified
function lastModified($modifiedTime, $notModifiedExit = true)
{
$modifiedTime = date('D, d M Y H:i:s \G\M\T', $modifiedTime);
if ($notModifiedExit && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $modifiedTime == $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
statusCode('304');
exit();
}
header("Last-Modified: $modifiedTime");
}
//设置页面charest
function charset($enc = 'UTF-8', $type = 'text/html')
{
header("Content-Type:$type;charset=$enc");
}
//禁止浏览器缓存页面
function disableBrowserCache()
{
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
}
//etag 设置内容标记 etag 多用 md5(要输出的内容)
function etag($etag, $notModifiedExit = true)
{
if ($notModifiedExit && isset($_SERVER['HTTP_IF_NONE_MATCH']) && $etag == $_SERVER['HTTP_IF_NONE_MATCH']) {
statusCode('304');
exit();
}
header("Etag: $etag");
}