Skip to content

Instantly share code, notes, and snippets.

@nikcorg
Created October 5, 2012 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikcorg/3840326 to your computer and use it in GitHub Desktop.
Save nikcorg/3840326 to your computer and use it in GitHub Desktop.
Cheapo caching for PHP
<?php
// Set elsewhere before including:
//
// $template = contains file to be read when fresh content is served
// CACHE_TTL_SECONDS = how long the cache should live, defaults to 10 mins
//
// Note: this does not necessarily save your server from receiving the GET request,
// you simply don't serve any content over the wire if the caching headers match,
// and you might save some disk I/O.
if (! isset($template)) {
header("HTTP/1.1 500 Internal Server Error", true, 500);
header("Content-Length: 0", true);
exit();
}
if (! defined("CACHE_TTL_SECONDS")) {
define("CACHE_TTL_SECONDS", 600);
}
define("DATE_RFC2616", "D, d M Y H:i:s T");
$lastModifiedOut = $_SERVER["REQUEST_TIME"];
$etagOut = md5($_GET["ts"]);
$etagIn = isset($_SERVER["HTTP_IF_NONE_MATCH"]) ? trim($_SERVER["HTTP_IF_NONE_MATCH"], "\"") : "";
$lastModifiedIn = isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) ? strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]) : 0;
$cacheExpires = $_SERVER["REQUEST_TIME"] + CACHE_TTL_SECONDS;
// Save the intertubes if the previous request was fresh enough.
// Unfortunately, we can't rely on only either of If-None-Match or
// If-Modified-Since. Thus it'snot fully conforming to the spec.
// But it's pretty close and certainly better than nothing.
if (
$etagIn === $etagOut &&
$lastModifiedIn > $_SERVER["REQUEST_TIME"] - CACHE_TTL_SECONDS
) {
header("HTTP/1.1 304 Not Modified", true, 304);
header("ETag: \"" . $etagOut . "\"");
header("Expires: " . gmdate(DATE_RFC2616, $lastModifiedIn));
header("Cache-Control: max-age=" . CACHE_TTL_SECONDS . ", must-revalidate, public");
header("Content-Length: 0");
exit(0);
}
// Attempt to detect the file's encoding from a sample of it's contents
$charset = "UTF-8";
if (function_exists("mb_detect_encoding")) {
$sample = file_get_contents($template, false, null, 0, 200);
$charset = mb_detect_encoding($sample, "UTF-8,ISO-8859-1,ASCII");
}
// Attempt to detect the file's content type
$ctype = "text/html";
if (function_exists("finfo_open") && defined("FILEINFO_MIME_TYPE")) {
$fi = finfo_open();
$ctype = finfo_file($fi, $template, FILEINFO_MIME_TYPE);
finfo_close($fi);
}
// Serve fresh HTML
header("HTTP/1.1 200 Found", true, 200);
header("Content-Type: " . $ctype . "; charset=" . $charset);
header("ETag: \"" . $etagOut . "\"");
header("Last-Modified: " . gmdate(DATE_RFC2616, $lastModifiedOut), true);
header("Age: 0");
header("Expires: " . gmdate(DATE_RFC2616, $cacheExpires), true);
header("Cache-Control: max-age=" . CACHE_TTL_SECONDS . ", must-revalidate, public");
readfile($template);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment