Automatische Weiterleitung

Wenn sich die Adresse einer Ressource ändert, sollte diese weiterhin unter dem alten URI erreichbar sein. Dies erreichen Sie mittels einer Weiterleitung. Dieser Artikel diskutiert mehrere Möglichkeiten mit dem Schwerpunkt serverseitige Weiterleitung.

Warum weiterleiten?

Die Entwicklung einer Website beginnt mit dem Entwurf der Informationsarchitektur und Datenorganisation. Sie stellen Material zusammen, unterteilen es in Informationseinheiten und überlegen sich, wie Sie diese auf der Website präsentieren sollen:

  • Welche Technologien stehen zur Verfügung und welchen Einschränkungen unterliegen sie?
  • Welche Verzeichnisse und Unterverzeichnisse benötigen Sie, welche Ressourcen beinhalten diese?
  • Wie werden Ressourcen ausgeliefert und über welche URIs sind sie adressierbar?

Sobald Sie die Planung einer Website abgeschlossen und das Konzept ausreichend geprüft haben, können Sie mit der Realisierung der Website beginnen, diese wiederum mehreren Evaluationsdurchläufen durchziehen, Crawler einsetzen, welche die Konsistenz der Website überprüfen, und die fertige Site schließlich publizieren. Nun gibt es rein theoretisch keinen Grund mehr, den Aufbau der Website zu verändern und Ressourcen zu verschieben oder zu löschen – in der Praxis gibt es leider einige davon:

  • Dokumente sind veraltet und sollen gelöscht oder in ein Archiv verschoben werden.
  • Es wird eine andere Technologie eingesetzt, beispielsweise ein anderes Content-Management-System, wodurch die Informationsarchitektur sich ändert und der URI oder Teile davon anders aussehen.
  • Im Rahmen eines Relaunchs der Website werden die Inhalte komplett umstrukturiert, beispielsweise an eine veränderte Unternehmensstruktur angepasst.
  • Ein Anbieter muss seine gesamte Website vom Netz nehmen, zum Beispiel Inhalte der Website einer Firma, die Pleite gegangen ist oder aufgekauft wurde.

Alle diese Maßnahmen führen dazu, dass Ressourcen überhaupt nicht mehr oder nicht unter der ursprünglichen Adresse erreichbar sind, unter die sie in Trefferlisten von Suchmaschinen, Lesezeichen oder auf anderen Websites verlinkt sind. Das Ergebnis sind Fehler der Art 404 (Not Found) und frustrierte Besucher, welche die gesuchte Information nicht sofort erhalten, sondern sie erst suchen müssen – wenn sie sich überhaupt darum bemühen und nicht verärgert für immer von dannen ziehen. Gelangen Besucher über eine Suchmaschine auf eine Website, werden sie kaum den Aufwand betreiben, die Site nach der gewünschten Ressource zu durchforsten, sondern wählen stattdessen einfach den nächsten Eintrag in der Trefferliste.

Wenn sich der URI einer Ressource ändert, aus welchen Gründen auch immer, sollte diese weiterhin unter dem alten URI erreichbar sein. Dies erreichen Sie über eine Weiterleitung.

Serverseitige Weiterleitung

Serverseitige Weiterleitung bietet Ihnen zwei Vorteile:

  1. Der Server leitet nicht nur weiter, sondern sendet auch einen entsprechenden Statuscode. Dadurch wird der Client, der die Ressource angefordert hat, über die Änderung informiert. Suchmaschinen aktualisieren ihren Index entsprechend und zeigen in der Folge den neuen URI an.
  2. Der Besucher bekommt von der Weiterleitung nichts mit, sondern ihm wird unmittelbar die angeforderte Ressource unter der neuen Adresse angezeigt.

Die Redirect-Direktive des Apache Webservers

Der Webserver Apache ermöglicht serverseitige Weiterleitungen durch die Direktive Redirect. Andere Webserver bieten ähnliche Möglichkeiten. Die Redirect-Direktive bildet einen alten URI auf einen neuen ab. Der neue URI wird an den Client zurückgeliefert, der daraufhin versuchen wird, das Dokument unter der neuen Adresse abzurufen. Redirect-Direktiven notieren Sie in der Konfigurationsdatei httpd.conf oder in Zugriffskontrolldateien (htaccess-Dateien). Die Syntax ist wie folgt:

Redirect [<Status>] <Pfad> <URI>

Das Statusargument ist optional und wird im weiteren Verlauf dieses Abschnitts erklärt. Der Pfad ist der Teil des alten URI nach dem Server-Namen. Lautete der alte URI http://www.example.com/foo/bar, müssen Sie als Pfad /foo/bar notieren. Alle Anfragen für Ressourcen, die mit diesem Pfad beginnen, werden mit einem entsprechenden Umleitungsstatus auf den neuen URI verwiesen. Folgende Weiterleitung leitet alle Anfragen an /foo/ an http://www.example.com/bar/ weiter.

Redirect /foo/ http://www.example.com/bar/

Wird kein Statusargument übergeben, wird eine temporäre Umleitung angenommen (Status 302, Found). Dadurch wird dem Client mitgeteilt, dass die Ressource lediglich vorübergehend unter der neuen Adresse erreichbar ist. Sie können folgende Statusargumente angeben:

permanent
Der Server sendet Status 301 (Moved Permanently), um anzuzeigen, dass die Ressource für immer unter dem neuen URI erreichbar ist.
temp
Der Server gibt den Status 302 (Found) zurück. Dies ist die Standardeinstellung und entspricht dem Verhalten, wenn Sie kein Statusargument angeben.
seeother
Der Server gibt den Status 303 (See Other) zurück. Dadurch können Sie deutlich machen, dass die ursprüngliche Ressource ersetzt wurde.
gone
Der Server sendet den Status 410 (Gone). Die angeforderte Ressource ist auf dem Server nicht mehr erreichbar und es ist auch kein neuer URI bekannt. Suchmaschinen, die den Statuscode 410 zurückerhalten, sollten die Ressource aus ihrem Index entfernen.

Darüber hinaus können Sie beliebige andere Statuscodes zurückgeben, indem Sie ihren numerischen Wert als Statusargument angeben. Alle Statuscodes finden Sie in der HTTP-Spezifikation in Abschnitt 10. Wenn der Statuscode im Bereich 300 bis 399 liegt, müssen Sie eine Weiterleitungsadresse angeben. Außerdem muss das Statusargument einem dem Apache bekannten Code entsprechen.

Neben der Direktive Redirect gibt es die Direktiven RedirectPermanent und RedirectTemp, die lediglich andere Schreibweisen für die Redirect-Direktive mit dem entsprechenden Statusargument darstellen, und die Direktive RedirectMatch, bei der Sie mit regulären Ausdrücken arbeiten können. Das folgende Beispiel ersetzt /foo/ in allen Anfragen durch /bar/. Würde ein Benutzer beispielsweise http://www.example.com/foo/document anfragen, würde der Webserver nach http://www.example.com/bar/document weiterleiten.

RedirectMatch permanent /foo/([^.]+) /bar/$1

Das Apache-Modul mod_rewrite

Ein weiteres, sehr mächtiges Werkzeug, das Sie unter anderem zur Weiterleitung von einem URI zu einem anderen nutzen können, bietet mod_rewrite. Dabei handelt es sich um ein Apache-Modul für die URI-Manipulation. Mit der RewriteEngine des Apache-Webservers ist es möglich, den angeforderten URI anhand von Regeln umzuschreiben und somit virtuelle URIs zu erzeugen, die auf tatsächlich vorhandene verweisen. Basierend auf einem Parser für reguläre Ausdrücke kann der angeforderte URI manipuliert werden. mod_rewrite ist sehr komplex und bietet derart viele Möglichkeiten, dass man ein ganzes Buch darüber schreiben könnte. Um Brian Behlendorf, ein Mitglied der Apache Group, zu zitieren:

»The great thing about mod_rewrite is it gives you all the configurability and flexibility of Sendmail. The downside to mod_rewrite is that it gives you all the configurability and flexibility of Sendmail.«

Ich beschränke mich im Rahmen dieses Artikels nur auf eine kleine Einführung und zwei Anwendungsbeispiele. Weitere Informationen erhalten Sie in den Apache-Manuals.

Um mod_rewrite zu nutzen, müssen Sie Ihre Zugriffskontrolldatei zunächst um folgende Zeilen erweitern:

RewriteEngine on
RewriteBase /
Options +FollowSymlinks

Die erste der drei Zeilen startet das Modul. RewriteBase gibt den Basis-URI an, in diesem Fall das Root-Verzeichnis der jeweiligen Domain. FollowSymlinks bewirkt, dass bei Weiterleitungen via mod_rewrite den symbolischen Links auf dem Webserver auch gefolgt werden kann. Anschließend folgen die Suchmuster. Dazu verwenden Sie die Direktive RewriteRule. Sie hat folgende Syntax:

RewriteRule <Muster> <Ersatz>

Als Beispiel ein recht simples Suchmuster: Ein Nutzer wird bei Aufruf der Ressource /foo an die Ressource /bar weitergeleitet, ohne dass er davon etwas merkt; der URI, der in der Adresszeile des Browsers angezeigt wird, bleibt unverändert.

RewriteRule ^foo$ /bar

Die Zeichen ^ und $ stellen Anker dar, die Anfang und Ende des Musters ausgehend vom Basis-URI markieren.

Zugegeben, das Beispiel ist nicht sonderlich aufregend. Spannender wird es, wenn Sie mit regulären Ausdrücken arbeiten. Dazu ein Beispiel aus der Praxis: Ich habe meine deutsche Übersetzung Bert Bos’ lesenswerten Essays »What is a good standard?« scheinbar in mehrere Dokumente unterteilt, um die Ladezeiten gering zu halten. Zusätzlich wird es in einem Dokument komplett angeboten. Die Einteilung in mehrere Dokumente findet allerdings nur virtuell statt. Es handelt sich in Wirklichkeit um eine einzige PHP-Datei mit diversen if-Abfragen folgender Art:

<?php
if( isset($_GET["show"]) ) {
  if($_GET["show"] == "wartbarkeit" ||
    $_ GET["show"] == "essay") {
    // Ausgabe
  }
}
?>

Es wird ein Parameter show nach seinem Wert abgefragt. Um den Abschnitt »Wartbarkeit« anzuzeigen, muss eigentlich der URI http://jendryschik.de/wsdev/trans/designguide/index.xhtml?show=wartbarkeit aufgerufen werden. Das gleiche gilt entsprechend für alle anderen Abschnitte. URIs mit Parameter sind allerdings nicht sonderlich schön und auch von Suchmaschinen nicht gern gesehen. Besser sind URIs nach folgendem Muster: http://jendryschik.de/wsdev/trans/designguide/wartbarkeit. Mit einer RewriteRule lassen sich die URIs entsprechend umschreiben:

RewriteRule ^/wsdev/trans/designguide/wartbarkeit$
  wsdev/trans/designguide/index.xhtml?show=wartbarkeit

Allerdings gibt es 25 Abschnitte, dazu noch die Möglichkeit, den ganzen Essay anzeigen zu lassen. 26 Suchmuster zu schreiben, wäre zeitaufwändig und würde die htaccess-Datei deutlich aufblähen. Aber es gibt ja reguläre Ausdrücke:

RewriteRule ^wsdev/trans/designguide/([^.]+)$
  /wsdev/trans/designguide/index.xhtml?show=$1

Alle Aufrufe von URIs, die dem Muster entsprechen, werden nun an die tatsächlich existierenden URIs weitergeleitet, wobei der Wert des Parameters ausgelesen und entsprechend anstelle der Variable $1 eingefügt wird.

Ein weiteres Beispiel soll die Möglichkeiten von mod_rewrite veranschaulichen: Die meisten Websites sind mit und ohne Angabe von »www« erreichbar. Dieselbe Ressource lässt sich dann sowohl mit dem URI http://www.example.com/foo als auch mit http://example.com/foo adressieren. Ich verwende mod_rewrite dazu, alle Anfragen an http://www.jendryschik.de/foo an die entsprechende Adresse ohne das überflüssige »www« weiterzuleiten:

RewriteCond %{HTTP_HOST} ^www.jendryschik.de$ [NC]
RewriteRule ^(.*) http://jendryschik.de/$1 [R=301]
RewriteCond %{THE_REQUEST} (.*).xhtml [NC]
RewriteRule (.*).xhtml http://jendryschik.de/$1 [NC,R=301]

Reguläre Ausdrücke machen sehr umfangreiche und mächtige Suchmuster möglich. Eine ausführliche Erläuterung deren Aufbaus ist allerdings nicht Thema dieses Artikels. Mehr Informationen dazu finden Sie in den Apache-Manuals oder einem Tutorial Ihrer Wahl.

Weiterleitung mit PHP

Eine weniger komplexe und trotzdem sehr mächtige Möglichkeit der Weiterleitung bietet PHP. Mit Hilfe der Funktion header() lassen sich Zeilen in den HTTP-Header einfügen, sodass der HTTP-Response direkt beeinflusst werden kann.

<?php
header("Location: http://www.example.com/");
exit();
?>

Die Funktion exit() bewirkt, dass das Parsen des aktuellen Dokuments abgebrochen wird. Dies spart nicht nur Ressourcen des Servers; auch sorgt der Abbruch dafür, dass kein HTTP-Body erzeugt wird. Für spezielle Clients, die der Weiterleitung nicht folgen können oder wollen, kann aber ein solcher Body erzeugt werden:

<?php
header("Location: http://www.example.com/");
echo "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"n";
echo " "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">n";
echo "<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">n";
echo "  <head>n";
echo "    <meta http-equiv="content-type"n";
echo "      content="text/html; charset=utf-8" />n";
echo "    <title>Weiterleitung</title>n";
echo "  </head>n";
echo "  <body>n";
echo "    <p>Die gesuchte Ressource wurde nach";
echo "      <a href="http://www.example.com/">www.example.com</a>";
echo "      verschoben.</p>n";
echo "  </body>n";
echo "</html>";
exit();
?>

Wenn benutzerdefinierte Header gesendet werden sollen, müssen Sie allerdings sicherstellen, dass keine Ausgabe vor dem Senden der Header erfolgt. Die sicherste Methode ist, das PHP-Skript so zu schreiben, dass die header()-Funktion vor jeglicher Ausgabe erfolgt. Bedenken Sie, dass Whitespace außerhalb der Markierungen <?php und ?> ebenfalls eine Ausgabe darstellt!

Standardmäßig wird auch hier der Statuscode 302 versendet. Wollen Sie eine permanente Weiterleitung realisieren, so fügen Sie in obiges Skript noch die folgende Zeile ein:

header("Status: 301");

Zusätzlich müssen Sie beachten, dass HTTP einen absoluten URI erwartet, auch wenn relative URIs in den meisten Fällen ebenfalls zum gewünschten Ergebnis führen. Der folgende Header ist somit unzulässig:

header("Location: bar");

Falls Sie innerhalb des PHP-Skripts nicht wissen, auf welcher Domain das Skript ablaufen wird, oder wenn Sie es auf mehreren Domains einsetzen möchten, können Sie die Server-Variable $_SERVER["HTTP_HOST"] nutzen, um einen zulässigen Header zu erzeugen:

header("Location: http://" . $_SERVER["HTTP_HOST"] . "/");

Clientseitige Weiterleitung

Eine serverseitige Weiterleitung ist nicht für alle Webautoren realisierbar. Bei vielen billigen oder kostenlosen Web-Hostern besteht keine Möglichkeit des Einsatzes von Zugriffskontrolldateien oder serverseitigen Techniken wie PHP. In diesem Fall steht nur die Möglichkeit der clientseitigen Weiterleitung zur Verfügung. Das bleibt zwar nur ein schwacher Ersatz für eine »richtige« Weiterleitung, stellt jedoch – sparsam und mit Bedacht eingesetzt – eine akzeptable Notlösung dar, wenngleich natürlich kein entsprechender Statuscode an den Client gesendet wird.

Weiterleitung per meta-Element

Richtig eingesetzt, können Sie das HTML/XHTML-Element meta dazu verwenden, eine Weiterleitung zu simulieren. In der Praxis funktioniert dies recht zuverlässig, wenngleich Sie damit natürlich keine »echte« Weiterleitung ersetzen können. Folgende Angabe leitet nach 5 Sekunden nach http://www.example.com/ weiter:

<meta http-equiv="refresh" content="5; url=http://www.example.com/">

Mit dem ersten Teil des Wertes des Attributs content bestimmen Sie, wie lange die aktuelle Seite, nachdem sie geladen ist, angezeigt wird, bevor die Weiterleitung zum im zweiten Teil des Wertes angegebenen URI erfolgt. Sie können sowohl absolute als auch relative URIs notieren.

Sie sollten sich nicht darauf verlassen, dass eine solche Weiterleitung bei jedem Client zuverlässig funktioniert. Einige Browser können mit einer Weiterleitung per meta-Element nichts anfangen, in anderen kann man diese Funktionalität abstellen, sogar im Internet Explorer. Zur Sicherheit notieren Sie einen normalen Link zur Weiterleitungsadresse. Das hat zudem den Vorteil, dass Suchmaschinen der Weiterleitung folgen und die Zielressource in den Index aufnehmen können.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="refresh" content="0; url=http://www.example.com/" />
    <title>Weiterleitung</title>
  </head>

  <body>
    <p>Die gesuchte Ressource wurde nach <a href="http://www.example.com/">www.example.com</a> verschoben.</p>
  </body>
</html>

Weiterleitung mit JavaScript

Der Vollständigkeit halber sei erwähnt, dass sich mit clientseitigen Skriptsprachen wie JavaScript ebenfalls Weiterleitungen realisieren lassen, beispielsweise wie folgt:

<script type="text/javascript">
  window.location.href='http://www.example.com/';
</script>

Davon möchte ich jedoch abraten. Weiterleitung mit JavaScript und per meta-Element teilen sich die gleichen Nachteile, wobei die Wahrscheinlichkeit, dass der Nutzer die JavaScript-Unterstützung seines Clients abgeschaltet hat, ungleich größer ist. Ich kann mir nur einen praktischen Anwendungsfall vorstellen, bei dem eine JavaScript-Lösung dem oben vorgestellten meta-Element vorzuziehen ist: Weiterleitung auf einen Teil der Website, der JavaScript erfordert, mit Darstellung von Alternativinhalten im aktuellen Weiterleitungsdokument.

Michael Jendryschik
0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlassen Sie mir einen Kommentar!

Ihre Kommentareingaben werden zwecks Anti-Spam-Prüfung an den Dienst Akismet gesendet. Darüber hinaus nutze ich die eingegebene E-Mail-Adresse zum Bezug von Profilbildern bei dem Dienst Gravatar. Weitere Informationen und Hinweise zum Widerrufsrecht finden sich in der Datenschutzerklärung.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert