my/creativity

30 september 2012

Je website versnellen met HTTP Cache-Control-headers

Naast het cachen van objecten in het geheugen van de server cache ik ook de pagina’s zelf. Dat scheelt mijn Raspberry Pi een hoop werk, en de bezoeker wachttijd.

De klasse hieronder regelt die HTTP-caching. Hij heeft één statische functie, Init, met twee parameters: een timestamp van het moment waarop de pagina (of welk bestand de browser ook opvraagt) voor het laatst is gewijzigd, en de maximale leeftijd in seconden die de browser hem in de cache mag houden.

class HttpCache 
{
    public static function Init($lastModifiedTimestamp, $maxAge)
    {
        if (self::IsModifiedSince($lastModifiedTimestamp))
        {
            self::SetLastModifiedHeader($lastModifiedTimestamp, $maxAge);
        }
        else 
        {
            self::SetNotModifiedHeader($maxAge);
        }
    }
    
    private static function IsModifiedSince($lastModifiedTimestamp)
    {
        $allHeaders = getallheaders();
        
        if (array_key_exists("If-Modified-Since", $allHeaders))
        {
            $gmtSinceDate = $allHeaders["If-Modified-Since"];
            $sinceTimestamp = strtotime($gmtSinceDate);
            
            // Can the browser get it from the cache?
            if ($sinceTimestamp != false && $lastModifiedTimestamp <= $sinceTimestamp)
            {
                return false;
            }
        }
        
        return true;
    }
    
    private static function SetNotModifiedHeader($maxAge)
    {
        // Set headers
        header("HTTP/1.1 304 Not Modified", true);
        header("Cache-Control: public, max-age=$maxAge", true);
        die();
    }
    
    private static function SetLastModifiedHeader($lastModifiedTimestamp, $maxAge)
    {
        // Fetching the last modified time of the XML file
        $date = gmdate("D, j M Y H:i:s", $lastModifiedTimestamp)." GMT";
        
        // Set headers
        header("HTTP/1.1 200 OK", true);
        header("Cache-Control: public, max-age=$maxAge", true);
        header("Last-Modified: $date", true);
    }
}