Last active
August 29, 2015 14:11
-
-
Save duzun/9d719acea9c582eedd6f to your computer and use it in GitHub Desktop.
Set cache control headers and manage http cache logic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Set cache control headers and manage http cache logic. | |
* | |
* @param (int|bool) $expires: true - use cache, false - no cache, int - expires timeout | |
* @param (time) [$modified]: Last modification time stamp | |
* @param (string) [$etag]: ETag content identifier | |
* @param (int) [$die]: 0 - no die, 1 - die on 304, -1 - no 304 headers | |
* | |
* @return (mixed) status code if cache, false if headers sent, true otherwise | |
* | |
* @author Dumitru Uzun | |
*/ | |
function header_cache($expires=true, $modified=NULL, $etag=NULL, $die=true, $cc=NULL) { | |
if(headers_sent()) return false; | |
defined('DATE_HTTP') or define('DATE_HTTP', 'D, d M Y H:i:s T'); | |
$time = time(); | |
header("Date: ".gmdate(DATE_HTTP, $time)); | |
// Cache-Control: no-cache,max-age=0 | |
// Pragma: no-cache | |
$hcc = get_env('HTTP_CACHE_CONTROL'); | |
$hpg = get_env('HTTP_PRAGMA'); | |
if($hcc || $hpg) { | |
$t = explode(',', $hcc.','.$hpg); | |
$rcc = array(); // request Cache-Control | |
foreach($t as $v) if($v = trim($v)) { | |
$v = explode('=', $v, 2); | |
if(count($v) == 2) { | |
$rcc[$v[0]] = trim($v[1]); | |
} | |
else { | |
$v = reset($v); | |
$rcc[$v] = $v; | |
} | |
} | |
if(!empty($rcc['no-cache'])) { | |
$expires = false; | |
} | |
elseif($expires && @$rcc['max-age'] == '0') { | |
$expires = 0; | |
} | |
unset($t, $v); | |
} | |
if(is_int($expires) || $expires) { | |
isset($cc) or $cc = defined('CACHE_CONTROL') ? CACHE_CONTROL : 'public'; | |
$cc and header("Pragma: $cc"); | |
if(is_int($expires)) { | |
// isset($prot) or $prot = get_env('SERVER_PROTOCOL') or $prot = 'HTTP/1.0'; | |
header('Expires: ' . gmdate(DATE_HTTP, $time+$expires)); // HTTP/1.0 | |
$cc and $cc = ' ' . $cc . ','; | |
header("Cache-Control:$cc max-age=$expires"); // HTTP/1.1 | |
} | |
$fresh = NULL; // NULL - undefined, true - fresh, false - old | |
if( $modified > 0 ) { | |
header('Last-Modified: '.gmdate(DATE_HTTP, $modified)); | |
if($fresh !== false ) { | |
if($ms = get_env('HTTP_IF_MODIFIED_SINCE')) { | |
$fresh = ($modified <= strtotime($ms)); | |
} // else - first visit or not suported | |
} | |
} | |
if( $etag ) { | |
header('ETag: '.$etag); | |
if($ms = get_env('HTTP_IF_NONE_MATCH') or $fresh) { | |
$fresh = ($ms == $etag); | |
} // else - first visit or not suported | |
} | |
if(isset($fresh)) { | |
if($fresh === true) { | |
$code = 304; | |
if($die >= 0) { | |
$msg = 'Not Modified'; | |
if(strncmp(php_sapi_name(), 'cgi', 3) == 0) { | |
header("Status: $code $msg", true, $code); | |
} | |
else { | |
isset($prot) or $prot = get_env('SERVER_PROTOCOL') or $prot = 'HTTP/1.1'; | |
header("$prot $code $msg", true, $code); | |
} | |
if($die) { | |
while(ob_get_level() > 0) ob_end_clean(); | |
flush(); | |
die(); | |
} | |
} | |
return $code; | |
} | |
else { | |
return 200; | |
} | |
} | |
} | |
else { | |
header('Pragma: no-cache'); | |
header('Expires: 0'); | |
header('Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0'); | |
} | |
return true; | |
} | |
// A helper function to get an environment/server variable | |
function get_env($var) { | |
if(func_num_args() > 1) { | |
$t = func_get_args(); | |
return get_env($t); | |
} | |
if(is_array($var)) { | |
foreach($var as $v) { | |
$t = get_env($v); | |
if($t !== false) return $t; | |
} | |
} | |
else { | |
$t = getenv($var); | |
if($t === false && array_key_exists($var, $_SERVER)) { | |
$t = $_SERVER[$var]; | |
} | |
} | |
return $t; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment