Geordneter Umzug (zu Wordpress)

Ende letzten Jahres habe ich mich dazu entschlossen, die Website meines Volleyballvereins mit einem Redaktionssystem zu betreiben. Im Zuge der Neuerungen musste auch die URL-Struktur geändert werden, was naturgemäß zu dem Problem führt, dass Aufrufe über Lesezeichen, Links und Suchmaschinen unerwartet im „Seite nicht gefunden“-Nirwana landen. Um unseren Besuchern (und unserer guter Position in den Suchmaschinen) das zu ersparen habe ich den Umzug geordnet durchgeführt und alle alten Links übersetzt und leite die Besucher zur gewünschten Seite weiter.

Die richtige Antwort

Wenn man eine URL Aufruft, zu der keine passende Ressource gefunden wird, landet man für gewöhnlich auf einer weißen „404 – not found“ Seite, die vom Server automatisch generiert wird. Mit etwas Glück ist diese Seite aber im Design der Website und bietet mögliche Alternativen zum nicht gefundenen Inhalt. In beiden Fällen antwortete der Webserver auf die Anfrage mit dem Statuscode „404“ der besagt: „Es wurde nichts gefunden“.

Ändern sich bei einem Umzug die URLs der Seiten, so landet jeder Aufruf der alten Links in der Sackgasse obwohl die Seite noch existiert. Folgerichtig wäre die korrekte Antwort vom Server: „der gesuchte Inhalt ist jetzt unter einer neuen URL verfügbar“. Der richtige Statuscode für diesen Fall ist „301 – Moved Permanently“.

Einige Seiten sind auch komplett verschwunden. Zum Teil weil sie in andere eingebunden wurden (Kontakt und Impressum können durchaus auf einer Seite unterkommen), andere waren einfach veraltet. Anfragen auf gelöschte Seiten beantwortet man ordnungsgemäß mit dem Statuscode „410 – gone“, der soviel bedeutet wie „Diese Seite ist von uns gegangen“. Somit ist auch gleich dafür gesorgt, dass Google & co. bescheid wissen und ihre Indizes aktualisieren können.

Die Umzugskisten auspacken

Während andernorts noch diskutiert wird, ob Wordpress als CMS taugt, setze ich es ein. Nicht zuletzt weil Anpassungen wie diese kinderleicht zu integrieren sind. Um alte URLs ihren neuen zuzuordnen und gelöschte Seiten zu kennzeichnen, ergänze ich die functions.php des eingesetzten Designs um folgende Funktion:

/** 
* umleiten alter Permalinks auf die neuen
*/
function translate_permalinks() {

	$_301 = array(
		'/startseite.html' => '/'
		'/kontakt.html' => '/kontakt',
		'/mannschaften.html' => '/mannschaften',
		'/news.html' => '/aktuell',
		'/links.html' => '/weblinks',
		'/impressum.html' => '/kontakt#impressum',
	);
	$_410 = array ( 
		'/alt.html',
		'/javascript/altes_script.js',
		'/css/altes_stylesheet.css',
		'/weg.html'
	);
	if ( array_key_exists( $_SERVER['REQUEST_URI'], $_301 ) ) {
		header(
			'Location: '
				. ( $_SERVER['HTTPS'] 
					? 'https'
					: 'http'
				  )
				. '://' . $_SERVER['SERVER_NAME'] 
                  		. $_301[$_SERVER['REQUEST_URI']],
			true,
			301
		);
		exit();
	}

	if ( in_array( $_SERVER[ 'REQUEST_URI' ], $_410 ) ) {
		header(
			  ( $_SERVER[ 'SERVER_PROTOCOL' ] == 'HTTP/1.1' 
				? 'HTTP/1.1'
				:  'HTTP/1.0'
			  )
			. ' 410 Gone'
		);
		header('Content-type: text/html;charset=utf-8');
		echo 
			'<h1>410 - Gone</h1>
			<p>Dieses Dokument existiert nicht mehr bei uns.
			Besuch bitte unsere <em>neue</em> Website:
			<a href="http://domain.tld/">http://domain.tld</a></p>';
		exit();
	}
}

In dem Array $_301 ordne ich die neuen Links den alten in der Form zu:
/link/zur/alten-datei.html => /neue_datei.
Alle nicht mehr vorhandenen URLs werden in dem Array $_410 lose aufgelistet. Die Elemente beider Arrays werden mit der Request-URI verglichen und im Falle einer Übereinstimmung erfolgt die Weiterleitung bzw. die Antwort mit dem entsprechenden Statuscode.

Der Funktionsaufruf erfolgt am Anfang der functions.php. Je nach Umfang der Website ist das etwas mehr Handarbeit die sich aber lohnt.

Nachtrag:

In den Kommentaren hat mich Thomas darauf hingewiesen, dass es schneller geht, die Umleitungen in die .htaccess-Datei zu schreiben, da so nicht jedesmal das ganze System geladen wird. Wer also auf die Performance achtet, oder ein anderes System als Wordpress nimmt, schreibt die Umleitungen und gelöschten Dokumente besser in die .htaccess.

Für diese Zwecke ist die Redirect-Direktive des Moduls „mod_alias“ geeignet. Alle permanenten Umleitungen werden so notiert:

Redirect permanent /alte_seite.html http://domain.tld/neue_seite

Hier muss man darauf achten, dass die URL zur neuen Seite vollständig angegeben werden muss, da Weiterleitungen nicht zwangsläufig auf eine Domain beschränkt sind.

Für gelöschte Dokumente lautet der Eintrag:

<IfModule mod_alias.c>
	Redirect permanent /startseite.html http://domain.tld/
	Redirect permanent /kontakt.html http://domain.tld/kontakt
	Redirect permanent /mannschaften.html http://domain.tld/mannschaften
	Redirect permanent /news.html http://domain.tld/aktuell
	Redirect permanent /links.html http://domain.tld/weblinks
	Redirect permanent /impressum.html http://domain.tld/kontakt#impressum

	Redirect gone /alt.html
	Redirect gone /javascript
	Redirect gone /css
	Redirect gone /weg.html
</IfModule>

Mit der Redirect Direktive kann man nicht nur einzelne Dokumente sondern auch Verzeichnisse handhaben, wie im Fall der Stylesheets und der Skripte zu sehen ist.

Damit Anfragen auf die entfernten Dokumente nicht mit einer lieblosen Standardantwort abgespeist werden, kann man noch ein Error-Dokument in der .htaccess anlegen:

ErrorDocument 410 /entfernt.html

Kommentare

  1. 01) 26.01.2010
    Thomas Scholz

    Beantworte solche Requests immer innerhalb des vom Client verwendeten Protokolls. Einem Request in HTTP 1.0 darfst du keinen Response in HTTP 1.1 entgegnen; du weißt ja nicht, ob der Client das versteht.

    $_SERVER['SERVER_PROTOCOL'] enthält diese Information.

    Viel einfacher geht das natürlich, wenn du dem Server das alles überläßt und die Einträge in die .htaccess packst. Dann muß dafür auch nicht erst das ganze WordPress geladen werden.

  2. 02) 26.01.2010
    David

    Danke für den Hinweis mit dem Protokoll. Ich werd das mit einbeziehen.

    Ich hab anfänglich auch überlegt, ob ich die Regeln in die .htaccess schreibe, habe mich dann aber für diese Methode entschieden, weil ich sie komfortabler finde. Auf diese Weise konnt ich die Arrays schnell im WP-Backend ergänzen, ich hatte nicht alle URLs am Anfang berücksichtigt.

    Insgesamt machen die Requests die dadurch behandelt werden nur einen Bruchteil der Gesamtheit aus. Die 410 bekommen meist nur die Bots zu sehen und die Umleitungen sind permanent, sollten also mit der Zeit auch geringer werden. Performanceprobleme kann ich also noch ausschließen. Aber die Methode über die .htaccess wäre eine gute Ergänzung für den Artikel. Ich setzte mich da mal ran.

Fragen, Ideen oder Kritik? – Hier ist Platz dafür!

Dein Kommentar

Um ein Kommentar abzugeben, reicht der Text im Kommentarfeld. Die Angabe eines Namens wäre nett, ist aber nicht erforderlich.

Du darfst folgenden HTML-Code verwenden, musst aber nicht:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>