Wie du die WordPress Rest-API zum Server-Cache füllen nehmen kannst

Aus meiner „administrativen Sicht“ ist die neue WordPress REST API Fluch und Segen zugleich. Ob dabei der Fluch, oder der Segen überwiegt muss ich für mich erst noch herausfinden.

Wie auf unzähligen Webseiten und Blogs nachzulesen ist, wurde mit WordPress 4.4 der erste Teil der neuen WordPress REST API eingeführt. Mit der WordPress Version 4.5 soll der zweite Teil der REST API, Mitte April 2016 implementiert werden.
So muss man sich, mit Stand heute, noch mit dem WordPress Plugin „WordPress REST API (Version 2)“ behelfen, um die volle Funktionalität der REST API in WordPress 4.4 nachzurüsten.

Aktuell kann man mit dem WordPress REST API Plugin folgende HTTP-Requests benutzen:

  1. POST (Create)
  2. GET (Retrieve)
  3. PUT (Update)
  4. DELETE (Delete)

Mittels dieser HTTP-Requests kann man auf folgende WordPress Ressourcen zugreifen:

  1. Beiträge
  2. Seiten
  3. Medien
  4. Beitrags-Meta
  5. Beitrags-Revisionen
  6. Kommentare
  7. Taxonomien
  8. Begriffe
  9. Benutzer

Schön, aber was hat die WordPress REST API mit dem Füllen von Server-Caches zu tun?
Diese Frage möchte ich im Folgenden beantworten.

1. Nur ein warmer Cache ist ein guter Cache

Der erste Besucher einer Webseite, deren Cache leer (kalt) ist, hat das „Problem“ einer längeren Ladezeit – im Vergleich zu einem Besucher, der dieselbe Seite ein wenig später aufruft. Das möchte man als Beitreiber einer Webseite natürlich möglichst verhindern.
Eine Lösung dafür, ist sicherlich der Einsatz eines der unzähligen WordPress Cache-Plugins.

Da ich auf meinem Server inzwischen auf Nginx mit HTTP/2, HHVM und mod_pagespeed umgestiegen bin, habe ich auf den meisten meiner WordPress-Installationen alle Cache-Plugins entfernt.
Statische Inhalte werden mit mit Nginx gecacht, dynamische Inhalte per se schon in HHVM zwischengespeichert, bzw. die Datenbank-Objekte in einem Redis-Server abgelegt.
Ergo: es ist kein extra WordPress Cache-Plugin vonnöten.

Um diese Kombination von Server-Caches zu füllen (aufzuwärmen), hat man eigentlich nur eine Möglichkeit: den regelmäßigen Aufruf aller Beiträge und Seiten, um deren Inhalte in den jeweiligen Caches vorzuhalten.
Der bisher einfachste Weg das abzubilden war:

  • Parsen der sitemap.xml
  • Links für Beiträge und Seiten in ein Script zu extrahieren
  • Das resultierende Script per Cronjob aufzurufen.

Mit der WordPress REST API öffnet sich nun eine neue Tür, um Server-Caches zu befüllen/anzuwärmen.

2. Caches mittels der WordPress Rest-API und zwei einfachen Skripten anwärmen

Das Ganze ist wirklich trivial:

  • Der Aufruf von http(s)://meinewebseite.de/wp-json/wp/v2/posts?filter[posts_per_page]=-1  ergibt eine Json-Liste aller veröffentlichter Beiträge.
  • Der Aufruf von http(s)://meinewebseite.de/wp-json/wp/v2/pages ergibt eine Json-Liste aller veröffentlichter Seiten.

Der Schritt von der, zum Teil recht großen Json-Ausgabe, über das Extrahieren der einzelnen Links und der CURL-Abfrage zum Webserver, ist mit wenigen Zeilen PHP-Code realisiert:

#!/usr/bin/php

function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// UserAgent mit Cache-Filler erweitern, um die Zugriffe im Logfile zu kennzeichnen
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0 Cache-Filler');
$data = curl_exec($ch);
curl_close($ch);
return $data;
}

// Variable aus Bash-Script aufnehmen
$url = $argv[1];
// Default WordPress REST API Pfad
$wpjsonpath = '/wp-json/wp/v2';
// Ptotokoll (HTTP oder HTTPS)
$protocol = 'https';
// Beitrags- und Seiten-URLs zusammenbauen
$posts_url = $protocol . '://' . $url . $wpjsonpath . '/posts?filter[posts_per_page]=-1';
$pages_url = $protocol . '://' . $url . $wpjsonpath . '/pages';

// Arrays fuer Beitrags- und Seiten-URLs vorbereiten
$data_posts = file_get_contents($posts_url);
$json_posts = json_decode($data_posts);
$data_pages = file_get_contents($pages_url);
$json_pages = json_decode($data_pages);

// Schleife, um die Links aus Beitraegen zu extrahieren und mittels der curl funktion vom Server abzufragen
foreach ($json_posts as $myposts)
{
curl($myposts->link);
sleep(1);
}
// Schleife, um die Links aus Seiten zu extrahieren und mittels der curl funktion vom Server abzufragen
foreach ($json_pages as $mypages)
{
curl($mypages->link);
sleep(1);
}

?>

Wie man sieht, ist PHP-Programmieren vielleicht nicht meine Stärke, aber das Script erfüllt seinen Zweck.

Das Script ist hinreichend kommentiert, so dass ich auf weitere Erklärungen an dieser Stelle verzichte.

Dies PHP-Script rufe ich mit dedizierten Bash-Skripten (per Domain) auf.
Das mag vielleicht umständlich erscheinen, gibt mir aber die Freiheit, domainspezifischen Inhalt dediziert und mit unterschiedlichen Frequenzen aufzurufen. Je nachdem, wie frequentiert eine Webseite ist, kann das Bash-Script in der Crontab mit unterschiedlich oft aufgerufen werden.

#!/bin/bash

RUNDIR="/root/bin/"
php ${RUNDIR}fill-cache.php 365-tage-fotoprojekte.de

Die Laufzeit des Scripts ist, Stand heute, akzeptabel – sicherlich kann man die einzelnen Schleifen in unterschiedliche PHP-Kindprozesse abspalten, um die Abarbeitung zu parallelisieren.
Auf meinem privaten Fotoblog habe ich aktuell an die zweihundert veröffentlichte Beiträge und ein dutzend Seiten: dort läuft das Script circa sechs Minuten.

So, that’s it.

Gerne beantworte ich Fragen, oder nehme auch Verbesserungsvorschläge für das PHP-Script an 🙂