Caching von AJAX-Requests verhindern

Bei meiner Ajax Klasse hatte ich ein kleines Problem, dass der Internet-Explorer gewisse Ajax-Requests zwischengespeichert wurden. Dies ist ja oft nicht was man will, den schliesslich soll immer das neuste Resultat zurückgeliefert werden.
Zum einen kann man bei der Serverseitigen Datei, die mit dem Request aufgerufen wird mit den Headers eine Cache-Control bewirken. Leider hat das bei mir nicht immer geholfen. Funktionieren würde es bei PHP so:
<?
header
("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
?>


Die Lösung die bei mir funktioniert hatte war die folgende: Wenn bei der Url die angefragt wird zusätzlich noch ein Parameter mit einer zufälligen Zahl angehängt wird meint der Browser, dass er die Adresse zum ersten mal aufruft und nimmt so keine Daten aus dem Cache. Das sieht dann so aus:
ajax=new XMLHttp;
var url="rpc.php?param=test&rand="+Math.random();
ajax.start(url,"elem");

Gravatare mit PHP cachen

In meinem Blog verwende ich schon lange den Dienst Gravatar. Dadurch wird zu den Kommentaren ein Bild (Avatar) vom Kommentator angezeigt. Vorausgesetzt, eine Mailadresse wird angegeben und ein Avatar ist bei Gravatar auf diese Adresse registriert. Beim Aufruf meiner Seite wir dieser Avatar von der Gravatarseite geholt und angezeigt.

Für den Benutzer hat das den Vorteil, dass er sich nur an einem Ort registrieren muss und dann auf allen Seiten die Gravatar unterstützen einen Avatar hat. Die Mailadresse bleibt dabei immer geschützt, da sie vor der Übertragung in einen MD5 String umgewandelt wird.

Auch für den Webseitenbetreiber hat Gravatar einige Vorteile. So muss man kein eigenes Avatarsystem zusammenbauen und kann einfach Gravatar nutzen. Das ganze ist sehr einfach zu realisieren. Für Wordpress gibt es ja auch Plugins.

Der Nachteil ist allerdings, dass Gravatar halt auf einer anderen Seite läuft. Sollte diese Seite mal Trafficprobleme haben, oder gar ganz down sein, so wir die eigene Seite auch langsam, da die Bilder nicht geladen werden können. Dieses Problem kann man umgehen, indem man die Bilder in einem Cache abspeichert. Ich habe ein PHP Script geschrieben, welches diese Bilder in einen Cache speichert.

Der Ablauf sieht so aus. Zuerst überprüft das Script, ob sich das Bild schon im Cache befindet. Zur Identifizierung wird die Mailadresse als MD5 String verwendet. Ist das Bild schon im Cache und nicht älter als zwei Tage wird das Bild ausgegeben.
Anders sieht es aus, wenn das Bild noch nicht im Cache, oder schon älter als zwei Tage ist. Dann wir eine Verbindung zum Gravatarserver hergestellt, das Bild heruntergeladen und im Cache gespeichert. Dann wird es auch ausgegeben.

Mir ist klar, dass es (noch) keine perfekte Lösung ist, aber es funktioniert. Natürlich kann man so auch andere Bilder (nicht von Gravatar) cachen. Man muss halt einige Angaben anpassen.

Nun müssen sich nur noch mehr Leute bei Gravatar anmelden.

Hier der Code des Scripts:
<?

// Konfiguration
define("CACHE_FOLDER","cache/");                // cache ordner
define("CACHE_DURATION",48);                    // wie lange die bilder im cache bleiben sollen (tage)
define("GRAVATAR_OPTIONS","size=64&amp;");      // optionen (bild groesse, rating usw)

// ueberprufen ob die mailadresse (als md5 string) gesetzt ist
if(!isSet($_GET['address']))
{
    die(
"no address is set");
}

// cache dauer in sekunden umrechnen
$duration_secs=CACHE_DURATION*60*60;

// adresse ueberpruefen
$address=$_GET['address'];
if(!
preg_match("/[a-z0-9]*/i",$address))
{
    die(
"wrong address");
}

define("GRAVATAR_HOST","www.gravatar.com");
define("GRAVATAR_PATH","/avatar.php?".GRAVATAR_OPTIONS."gravatar_id=".$address);
$filename=CACHE_FOLDER.$address.".jpg";

// ueberprufen, ob die datei heruntergeladen werden muss
$download=TRUE;
if(
file_exists($filename))
{
    if(
fileMTime($filename)>(time()-$duration_secs))
    {
        
$download=FALSE;
    }
}

// wenn ja
if($download)
{
    
// zum host verbinden
    
$source=@fSockOpen(GRAVATAR_HOST,80,$errno,$errstr,30);

    
// wen verbindung hergestellt
    
if($source!=FALSE)
    {
        
// zu sendende headers zusammenstellen
        
$req ="GET ".GRAVATAR_PATH." HTTP/1.0\r\n";
        
$req.="Host: ".GRAVATAR_HOST."\r\n";
        
$req.="Connection: Close\r\n\r\n";

        
// headers senden
        
fWrite($source,$req);
        
        
// headers der antwort auslesen
        
while(!fEof($source))
        {
            
$header=trim(fGets($source,1024));
            if(
$header=="")
            {
                break;
            }
        }

        
// zieldatei oeffnen
        
$dest=fOpen($filename,"w+");

        
// daten auslesen und direkt in die zieldatei schreiben
        
while(!fEof($source))
        {
            
$data=fGets($source,1024);
            
fWrite($dest,$data);
        }

        
// verbindung trennen
        
fClose($source);
        
fClose($dest);
    }
    else
    {
        
// wenn gravatar down und kein bild im cache
        // standardbild verwenden
        
$filename="gravatar.jpg";
    }
}

// Bild ausgeben.
header("Content-type: image/jpeg");
echo 
file_get_contents($filename);
?>