So, da ich aktuell ein wenig am Weblog meiner Freundin arbeite hatte ich in diesem Zuge auch einmal Gelegenheit deren Seite als meine kleine Sandbox zu missbrauchen, was ihr letztendlich nur zu gute kommt.
Nur vorab, über die Seite an sich werde ich wohl gesondert nochmal berichten wenn wirklich alles “perfekt” steht, die aufmerksamen Leser unter euch kennen die Seite aber wohl eh schon.
Nun will ich den ganzen Keywords im Titel aber auch gerecht werden.
Also, ich wollte eigentlich einfach mal ein bisschen mit der Twitter-API spielen. Ziel sollte es sein das die letzten 10 Updates von Danis Twitter-Account öffentlich auf der Seite dargestellt werden können, obwohl ihr Account aber für die Öffentlichkeit gesperrt ist. Hauptgrund dafür war eigentlich nur die wilde Indexierung durch Google.
Nun unterstützt Twitter von Haus aus das abholen der Updates im JSON-Format und rein zufällig kann auch jQuery von Haus aus mit JSON wunderbar umgehen, selbst wenn die Dateien auf einer fremden Domain liegen.
Nun wäre es natürlich sehr einfach eine kleine Anwendung zu schreiben (bei Ralph wird alles gut beschrieben) in der sich der Browser bei jedem Seitenaufruf direkt die .json-Datei von Twitter bezieht und diese optisch auf der Seite darstellt. Nun gibt es jedoch ein paar Gründe die aus meiner Sicht dagegen sprechen fremde API-Dateien direkt in seinem JavaScript zu benutzen.
Nachteile die da wären:
- Der Twitter-Server könnte überlastet sein.
- Manchmal will man die Herkunft der Daten verschleiern.
- Wir müssen das Ergebnis erstmal unbearbeitbar hinnehmen.
- Viele APIs machen bei zuviel Traffic irgendwann dicht.
- Der DNS-Resolve auf eine Fremddomain dauert doch meist.
- … und die meisten API-Server sind auch nicht die schnellsten.
Aus diesem Grund habe ich mich für etwas entschieden das ich hier mal einen PHP-CURL-CACHE-Proxy nennen möchte. Im Prinzip ist der Sinn hinter diesem Script ein ganz simpler, denn wir haben eigentlich nur Vorteile davon den Server die meiste Arbeit machen zu lassen.
Vorteile die wir ausnutzen sollten:
- Antwortet der API-Server nicht, oder gibt einen Fehler zurück behalten wir das letzte valide Ergebnis erstmal im Cache, wir verhindern also Fehlermeldungen.
- Niemand kann direkt sehen wo unsere Quelle für die Daten liegt.
- Wir können das Ergebnis vor der Ausgabe beliebig Manipulieren, z.B. URLs löschen oder Namen ausschwärzen etc. pp.
- Nur unser Server greift auf die API zu, und das in einem bestimmten Zeitintervall, z.b. alle 180 Sekunden, auch wenn sich in dieser Zeit 600 Benutzer auf der Seite tummeln.
- Ajax/jQuery sieht lokale XML, JSON und TXT-Dateien als vertrauenswürdiger an und lässt z.b. auf externe Dateien keine Timeout-Option zu.
Es geht hierbei also nicht um die Struktur des JavaScript, das hat (wie schon gesagt) der Ralph ganz gut beschrieben, sondern nur um die Adresse von der wir unser Resultat beziehen.
Ok, und so wird (laienhaft) gemacht:
Zuerst brauchen wir 2 Dateien zum Cachen der Daten. In die erste Datei wird der Timestamp der letzten aktualisierung geschrieben, in die andere Datei packen wir das Resultat was wir vom API-Server bekommen haben. Warum wir das nicht in eine Datei packen? Gute Frage, prinzipiell wäre das wohl auch irgendwie möglich, ich fand es aufgrund der unterschiedlichen Encodings jedoch als leichter beide Werte getrennt zu behandeln. Um vernünftig mit der API arbeiten zu können sollte auf eurem Server die cURL-Extension vorhanden sein, welche es uns auf einfachste Art ermöglicht, fremde Seiten und Dateien abzugreifen.
Hier nun auf die schnelle mein Kleines PHP-Script:
//Erstmal kontrollieren wir ob der Referer
//auch unserer Domain entspricht und ob die
//Anfrage ein XMLHttpRequest ist.
if($HTTP_SERVER_VARS['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' && strpos($HTTP_SERVER_VARS['HTTP_REFERER'], $_SERVER['SERVER_NAME']) == false){
exit();
}
//Pfad zur Timestamp-Datei
$cache['keys'] = 'cache/keys.txt';
//Pfad zum Cache-Content
$cache['twitter'] = 'cache/twitter.txt';
//Zeit die das Resultat im Cache gehalten werden soll (180 Sekunden)
$cache['time'] = time()-180;
//Wir schauen wann der Cache das letzte mal aktualisiert wurde...
$twit = file($cache['keys']);
//Und setzen gleich mal den richtigen Header
header('application/x-javascript');
//Sollte der Cache älter als 180 Sekunden sein, wird er erneuert...
if($twit[0] <= $cachetime){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://twitter.com/statuses/user_timeline.json?count=10');
//Wir müssen uns am Server autorisieren
curl_setopt($ch, CURLOPT_USERPWD, 'twittername:twitterpasswort');
//Antwortet der Server nach 4 Sekunden nicht wird abgebrochen
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$buffer = curl_exec($ch);
//Ist das Ergebnis über 1000 Byte lang und
//beinhalteten den typischen Abschnitt "profile_image_url"
//schreiben wir es in den Cache, wenn nicht lassen wir
//die alten Daten im Cache.
if(strlen($buffer) > 1000 && strpos($buffer,'profile_image_url')){
$fp = fopen ($cache['keys'], "w");
fwrite ($fp , time());
fclose ($fp);
$fp = fopen ($cache['twitter'], "w");
fwrite ($fp , $buffer);
fclose ($fp);
} else {
$buffer = file_get_contents($cache['twitter']);
}
} else {
$buffer = file_get_contents($cache['twitter']);
}
echo $buffer;
Nun brauchen wir nur noch die Cache-Dateien erstellen, diese für unser Script schreibbar machen und unser JavaScript auf die lokale Datei umlenken. Ihr habt zudem natürlich den Vorteil alle Daten, z.B. mit preg_replace frei zu modifizieren.
Kommentare zum Thema JSON, jQuery, cURL ,Twitter und der Cache:
klingt gut, merci
mh ich muss was falsches gemacht haben es klappt bei mir nicht
hallo, finde ich sehr interessant, ich werde dein blog verlinken. ciao
mh ich muss was falsches gemacht haben es klappt bei mir nicht
Du darfst das ja auch nicht einfach so kopieren ;) Der Christian hat da auch ja (aus Versehen?) einen kleinen Fehler in den Code gebastelt
//Sollte der Cache älter als 180 Sekunden sein, wird er erneuert…
if($twit\[0\] <= $cachetime){
müsste richtig heißen:
//Sollte der Cache älter als 180 Sekunden sein, wird er erneuert…
if($twit\[0\] <= $cache[‘time’]){
müsste Zeile 18 sein. Die “\” in “$twit\[0\]” müssen natürlich raus, sollen die Textile-Formatierung umgehen. Die Idee finde ich aber ziemlich elegant, muss ich sagen!
wie ist den die url zum blog der freundin?
Kommentar-Feed für diesen Artikel
Google-Cache der aktuellen Seite schnell einsehen Die DebugBar für den Internet Explorer

Danke fuer den Tipp, werd ich bei Gelegenheit mal ausprobieren.
Greetings