.htaccess Redirects von RealURL mit SQL erzeugen

Redirects mit RealURL 2.x

Beginnend mit RealURL 2.x werden Redirects von RealURL laut einer Ankündigung nicht mehr unterstützt. Neu eingepflegte Redirects in der Tabelle tx_realurl_redirects führen nicht mehr zu einer Weiterleitung, sondern zu einem Fehler. Nach einem Update ist besonders wichtig, dass man bei einem DB-Compare im Install Tool diese Tabelle nicht einfach löscht, denn sonst ist neben der Funktion auch noch die Information über bestehende Redirects dauerhaft verloren.

Außerdem steht das Backend-Modul Web->Info->Realurl-Management unter TYPO3 CMS 6.2 nicht mehr zur Verfügung. Dies ist laut dem Autor von RealURL kein Bug.

Warum funktionieren alte Redirects trotz Feature-Entfernung weiterhin?

Etwas verwirrend ist die Tatsache, dass in Version 1.x eingepflegte Redirects im Labortest auch unter Version 2.0.10 weiterhin zu 302-Weiterleitungen führten (ohne Browser-Caching getestet mit wget). Hierbei handelt es sich jedoch um Überbleibsel im RealURL-Cache (Tabelle tx_realurl_pathcache) der sich unter TYPO3 CMS 6.2 mangels Backend-Modul vorerst nicht mit Bordmitteln zurücksetzen lässt und potentiell für Überraschungen in der Zukunft sorgt, wenn dann doch mal der Cache geleert wird (z. B. mittels Scheduler Task für ein Zurücksetzen der RealURL-Caches). Die Cache-Leichen mit unzuordenbarer Herkunft kommuniziert RealURL in der Response mit dem Hinweis expired, also zum Beispiel

302 TYPO3 RealURL redirect for expired page path

Neue Redirects lassen sich über die unbenutzte Tabelle tx_realurl_redirects nicht mehr anlegen und führen auch nicht zu neuen Cache-Einträgen in der Tabelle tx_realurl_pathcache.

Wie könnte ein Migrationskonzept bezüglich Redirects aussehen?

Man hat im Grunde vier Möglichkeiten, wenn man die bereits eingepflegten Redirects nicht verzichten möchte (oder kann):

  • RealURL 2.x nicht installieren und stattdessen bei RealURL 1.x bleiben. Version 1.x erhält allerdings vermutlich keine Sicherheitsupdates mehr, sodass man spätestens im Falle einer Sicherheitslücke in Version 1.x auf Version 2.x umsteigen müsste und dann auf die Schnelle ein gutes Alternativkonzept bezüglich Redirects bräuchte.
  • Ggf. auf eine separate Extension für Redirects warten, die der Autor von RealURL bereits vage in Aussicht gestellt hat.
  • Redirects aus tx_realurl_redirects mittels .htaccess-Datei abbilden.
  • Dafür sorgen, dass Einträge in tx_realurl_pathcache niemals gelöscht werden. Dies ist jedoch gefährlich, denn Caches sollten eigentlich jederzeit rücksetzbar sein und werden potentiell durch ein Update oder eine Benutzeraktion gelöscht.

Werden Redirects in RealURL 2.x noch nachgerüstet?

Die Möglichkeit, einen Bugfix beizusteuern bzw. die beiden fehlenden Features nachzurüsten, scheidet aus, da sich der Autor offensichtlich bereits gegen Redirects mittels RealURL entschieden hat und dies im Wesentlichen damit begründet, dass Redirects statisch sind und aus Performancegründen nicht den kompletten Typo3-Stack durchlaufen sollten. Die Auslagerung der Redirects in die Apache-Konfiguration oder die .htaccess-Datei dürfte hierbei durchaus Performancevorteile haben, wobei man sich angesichts des Redirect-immanenten Charakters eines Fallbacks über die Sinnhaftigkeit dieser Zielsetzung durchaus streiten könnte. Erwartbares Unverständnis auf Anwenderseite wurde obendrein geflissentlich in Kauf genommen.

Zu bemängeln wäre hierbei insbesondere ein (noch) nicht existentes Nachfolgekonzept mit TYPO3-Bordmitteln, denn nicht jeder Anwender darf oder will seine .htaccess-Datei ändern. Gewissermaßen handelt es sich bei Redirects zudem um Content, den ein CMS ja eigentlich gerade managen sollte, und ein Enterprise-CMS sollte hierfür eine Management-Oberfläche für Redakteure anbieten anstatt auf manuelles Anpassen einer .htaccess-Datei durch den Webmaster oder Webhoster zurückzufallen.

Statt einer Entfernung dieses wichtigen Features wäre es stattdessen wünschenswert gewesen, dass RealURL Titel-Änderungen feststellt und entsprechende Redirects bezüglich der alten URL für den alten Titel automatisch setzt. Dies wäre die Enterprise-Spielart gewesen. Um negative Kritik zu relativieren, bleibt zu bemerken, dass die Neuentwicklung von RealURL 2.x sicherlich viel Entwicklungsaufwand verschlungen hat, der ggf. nur teilweise durch Spenden gedeckt war. Es bleibt abzuwarten, ob die bereits angesprochene separate Redirect-Extension derartige Features nachrüsten wird. Und nicht zuletzt bleibt zu hoffen, dass genügend Benutzer zu einer Spende oder Mitarbeit bereit sind.

Sinn und Unsinn von Redirects

Der Autor von RealURL bemängelt auch nicht Redirects an sich, sondern lediglich die bisherige Implementierung in RealURL. Redirects sind an und für sich nicht böse oder schlechter Stil, ganz im Gegenteil: Redirects sind standardkonform und erlauben Änderungen der URL, ohne dass Links anderer Webseiten auf die alte URL zu einem Fehler führen.

Insbesondere Suchmaschinenbetreiber legen größten Wert darauf, dass Weiterleitungen eingepflegt werden, z. B. Google mittels Search Console (aka Webmaster Tools). In Sachen User Experience und SEO sind Redirects unverzichtbar. Zudem erlauben Redirects verlinkenden Webseitenbetreibern und Suchmaschinen, automatisiert Kenntnis über die neue URL zu erlangen und eine dauerhafte Umstellung auf neue URLs vorzunehmen. Nur dauerhaft für die Benutzung vorgesehene Redirects, insbesondere mehrfache Redirects für einen Request, sollte man aus Performance-Gründen vermeiden.

Idealerweise kann man Redirects später wieder entfernen, wenn Suchmaschinen und verlinkende Webseiten von den entsprechenden Betreibern umgestellt wurden. De facto muss man unbenutzte bzw. selten benutzte Redirects nicht unbedingt löschen, denn wenn sie ohnehin nicht benutzt werden, beeinträchtigen Redirects auch die Performance von Requests nicht wesentlich, nur der datenbankinterne Index-Scan auf einen Hash-Wert dauert minimal länger, und dies bei separater Tabelle auch nur für den Fallback-Charakter von Redirects. Nicht zuletzt erlauben Redirects auch noch die Vermeidung von duplicate content, so dass man im Idealfall auf die Behelfslösung von Canonical URLs verzichten könnte.

Redirects für .htaccess aus RealURL-Redirects erzeugen

Entscheidet man sich für die Variante von Redirects mittels .htaccess-Datei, dann kann man die entsprechenden Einträge, wie im Folgenden beschrieben, aus der RealURL-Tabelle tx_realurl_redirects erzeugen:

Die Auslagerung der Redirects von RealURL in eine .htaccess-Datei nimmt man an Besten vor dem Update von RealURL 1.x auf RealURL 2.x vor. Hat man bereits auf RealURL 2.x aktualisiert, dann sollte man die Tabelle tx_realurl_redirects tunlichst nicht mittels DB-Compare löschen, bevor der Umzug in die .htaccess-Datei erfolgt ist. Auch danach kann man sich überlegen, dass eine neue, separate Redirect-Extension diese Tabelle möglicherweise für ein Migrationskonzept nutzen wird. Wenn man darauf spekuliert, dann sollte man diese Tabelle ebenfalls nicht löschen (und ggf. gar nicht erst auf RealURL 2.x updaten!).

Permanente Redirects mittels http-status 301 sehen in der .htaccess-Datei wie folgt aus:

// Redirect für eine Ressource (Datei)
Redirect permanent /path/to/old.html /path/to/new.html
//Redirect für einen Pfad-Prefix (Verzeichnis)
RedirectMatch permanent /olddir(.*) /newdir/$1

Sofern die Tabelle tx_realurl_redirects von RealURL 1.x noch vorhanden ist, kann man die Redirect-Einträge für die .htaccess-Datei aus der bestehenden RealURL-Tabelle erzeugen, wobei die entsprechenden Einträge, wie folgt, in SQL erzeugt werden können:

SELECT CONCAT(
    'Redirect permanent ',
    IF(LEFT(url, 1) = '/', url, CONCAT('/', url)), ' ',
    IF(LEFT(destination, 1) = '/', destination, CONCAT('/', destination))
)
FROM tx_realurl_redirects
ORDER BY url DESC;

Mittels MySQL-Konsole lässt sich eine Ausgabe ohne Formatierung erreichen mit:

mysql -N -B -u user_name -p typo3_db -e "SELECT CONCAT('Redirect permanent ', IF(LEFT(url, 1) = '/', url, CONCAT('/', url)), ' ', IF(LEFT(destination, 1) = '/', destination, CONCAT('/', destination))) FROM tx_realurl_redirects ORDER BY url DESC;"

Die Daten lassen sich auch direkt in eine Datei (hier: /tmp/redirects.txt) wegschreiben, deren Inhalt man am Anfang der .htaccess-Datei einfügen kann:

mysql -N -B -u user_name -p typo3_db -e "SELECT CONCAT('Redirect permanent ', IF(LEFT(url, 1) = '/', url, CONCAT('/', url)), ' ', IF(LEFT(destination, 1) = '/', destination, CONCAT('/', destination))) FROM tx_realurl_redirects ORDER BY url DESC;" > /tmp/redirects.txt

Die Ausgabe sieht dann z. B. so aus:

Redirect permanent /firma/impressum/ /ueber-uns/impressum/
Redirect permanent /firma/kontakt/ /ueber-uns/kontakt/
Redirect permanent /anfahrt/ /anfahrtplan/

Sofern ganze Verzeichnisse verschoben wurden, muss man die darin enthaltenen Dateien nicht einzeln umleiten, sondern kann diese (manuell) zusammenfassen. Entsprechend lässt sich das obige Beispiel teilweise zusammenfassen:

//Redirect für einen Pfad-Prefix (Verzeichnis)
RedirectMatch permanent /firma/(.*) /ueber-uns/$1

Prüfung der .htaccess-Redirects und Bereinigung der RealURL-Caches

Zunächst sollte man prüfen, ob die Redirects tatsächlich durch den Webserver mittels .htaccess-Datei abgewickelt werden. Hierzu einen der Redirects mit wget testen:

wget "http://www.example.com/firma/impressum/"

Hierbei ist einerseits zu prüfen, ob die 301-Weiterleitung tatsächlich erfolgt, und andererseits darf die Weiterleitung nicht mehr von RealURL kommen. Verwaiste Cache-Einträge identifiziert RealURL als expired, und diese dürften nach einem Abruf der Redirects nicht mehr auftreten:

302 TYPO3 RealURL redirect for expired page path

Stattdessen sollte man nun eine Weiterleitung vom Apache-Webserver erhalten, die folgendermaßen aussieht:

301 Moved Permanently

Ist dies der Fall, dann greifen die Weiterleitungen bereits auf Ebene des Apache-Webservers und RealURL kommt gar nicht erst zum Zuge. Entsprechend kann man sich daher an die Bereinigung der Real-URL Caches machen, denn die verwaisten Einträge werden nun nicht mehr benötigt.

Vor dem Leeren der RealURL-Caches sollte man eine Sicherung der entsprechenden Tabellen anfertigen:

mysqldump -u user_name -p typo3_db --tables tx_realurl_urlcache tx_realurl_pathcache > /tmp/realurl_caches.sql

Wenn durch das nachfolgend beschriebene Leeren der RealURL-Caches etwas schief gehen sollte, kann man die entsprechenden Tabellen wiederherstellen mit

mysql -u user_name -p typo3_db < /tmp/realurl_caches.sql

Die RealURL-Caches lassen sich in SQL leeren mit

TRUNCATE tx_realurl_urlcache;
TRUNCATE tx_realurl_pathcache;

Oder alternativ direkt in einem Shell-Befehl:

mysql -u user_name -p typo3_db -e "TRUNCATE tx_realurl_urlcache;TRUNCATE tx_realurl_pathcache;"

Danach muss man die TYPO3-eigenen caches leeren (frontend caches und general caches). Danach sollte sich der RealURL-Cache wieder füllen. Im Anschluss sollte man sich unbedingt vergewissern, dass neben den Redirects auch normale sprechende URLs weiterhin funktionieren.

Die Neubefüllung der Caches lässt sich in SQL prüfen mit

    SELECT 'urlcache' AS cache, COUNT(*) AS entries
    FROM tx_realurl_urlcache
UNION
    SELECT 'pathcache', COUNT(*)
    FROM tx_realurl_pathcache;

Wurden die Caches befüllt, sollte die Anzahl der Einträge größer als 0 sein, wie in folgendem Anfrageergebnis:

+-----------+---------+
| cache     | entries |
+-----------+---------+
| urlcache  |      20 |
| pathcache |      16 |
+-----------+---------+

Realurlmanagement und RealURL 2.x

Früher gab es noch die Extension realurlmanagement, welche ebenfalls die Pflege von Redirects via RealURL erlaubte. Diese Extension hatte jedoch eine Sicherheitslücke und der Autor der Extension pflegt die Extension laut Ankündigung nicht mehr. Die Extension sollte entsprechend deinstalliert werden, denn sie ist bekanntermaßen unsicher und wird auch nicht mehr gewartet. Die Extension ist auch nicht mehr im TER verfügbar.

Mit RealURL 2.x ist die Pflege von Redirects in den Tabellen von RealURL zudem ohnehin unwirksam, insofern sind alte Versionen von realurlmanagement im Zusammenspiel mit RealURL 2.x obsolet.