Beim Umschreiben von URLs lässt das Apache-Modul Mod_rewrite keine Wünsche offen. Es eignet sich gleichermaßen für einfache Aufgaben und komplexe Szenarien.
Informationen im Internet sind schnellebig: Domainnamen und Pfadangaben ändern sich, alte Meldungen wandern ins Archiv. Kurzlebige Kampagnen-Adressen tun ihr Übriges, um das Chaos zu vergrößern. So verwundert es nicht, dass viele Content-Management-Systeme (CMS) auf ein Apache-Modul namens Mod_rewrite setzen: Es erleichtert die Organisation der Internetadressen erheblich.
Zunächst gilt es, zu klären, ob für Sie das Umschreiben von Adressen überhaupt Sinn ergibt, denn eigentlich ist die Sache ganz einfach: Entweder lässt sich eine Seite unter einer bestimmten URL erreichen und erscheint im Browser, oder es kommt eine Fehlermeldung (404 — Page not found). Bei einfachen Seiten mag diese Strategie ausreichen, doch bei größeren Webprojekten stößt man damit schnell an Grenzen:
- Ein neuer Firmenname ändert auch den Domainnamen. Da die alten Adressen aber noch an vielen Stellen stehen, gilt es sie automatisch umzuschreiben.
- Seiten, die Passwörter abfragen, sollen ausschließlich per SSL-Verschlüsselung erreichbar sein.
- Sie besitzen mehrere Domains und möchten alle auf eine Seite leiten.
- Wegen hoher Last betreiben Sie mehrere Webserver, die eingehenden Anfragen sollen bei Bedarf verteilt werden.
Erfahrene Webmaster weisen zurecht darauf hin, dass für alle genannten Beispiele auch anderweitige Lösungen existieren: Domains schalten Sie im Webserver einfach als Alias auf, gesicherte Angebote bieten sie eben nur im HTTPS-Protokoll an, und um die Lastverteilung kümmern sich Caches oder DNS-Round-Robin-Verfahren. Letztendlich steht in jedem HTML-Buch, dass auch das entsprechende Meta-Tag eine Umleitung realisiert.
Doch dank Mod_rewrite decken Sie all diese Möglichkeiten mit einem einzigen, direkt in den Apache-Webserver integrieren und damit sehr leistungsfähigen Modul ab. Zudem meistern Sie damit auch dynamische Umleitungen, was reines HTML nicht mehr leistet. Zahlreiche CMS setzen daher auf das Apache-Modul, beispielsweise um unschöne Adressen wie ?site=2&cat=5&subsite=3&page=27 in ansehnliche Pfade wie /de/docs/faq.html umzuschreiben – was auch der Indizierung und Platzierung bei Suchmaschinen zugute kommt.
Testumgebung
Unser Testsystem besteht aus der aktuellen LTS-Version von Ubuntu 10.04 “Lucid Lynx”, auf dem wir Apache mittels sudo apt-get install apache2-suexec apache2-mpm-prefork einrichten. Die Software enthält bereits das Modul mod_rewrite. Wir aktivieren es mittels des Kommandozeilenaufrufs sudo a2enmod rewrite und starten anschließend den Webserver mit sudo apache2ctl restart neu.
Konfiguration
Unabhängig davon, ob Sie eine bestehende Installation mit Mod_rewrite ergänzen oder den Webserver frisch aufsetzen – als Erstes gilt es, das Modul über die Direktive RewriteEngine on in der Apache-Konfiguration zu aktivieren. Anstatt das global für den gesamten Webserver zu tun, versehen Sie nur diejenigen Hosts damit, die diese Umleitung auch in Anspruch nehmen.
Dazu öffnen Sie die entsprechende Konfigurationsdatei im Verzeichnis /etc/apache2/sites-enabled und fügen die Direktive ein (Listing 1). Nach jeder Änderung am virtuellen Host gilt es, Apache neu zu starten, damit er die Änderungen übernimmt; bei der Variante mittels .htaccess entfällt dieser Schritt. Die Vor- und Nachteile beider Varianten erklärt der Kasten “.htaccess oder Virtual Host?”.
Listing 1
<VirtualHost *:80> ServerName meinefirma.tld RewriteEngine on </VirtualHost>
oder Virtual Host?
Die Mod_rewrite-Regeln legen Sie auf zwei verschiedene Arten an: Zum einen im entsprechenden Virtual-Host-Abschnitt der Konfigurationsdatei von Apache, zum anderen in den so genannten .htaccess-Dateien. Die letztgenannte Variante bietet den Vorteil, dass sie auch normalen Anwendern ohne Zugriff auf die Apache-Konfiguration zur Verfügung steht. Allerdings arbeitet diese Methode nicht nur langsamer, sondern birgt auch die Gefahr, dass ein Anwender mit einer unbedachten Regel den kompletten Webserver lahm legt. Es empfiehlt sich deswegen, die Regeln direkt in der Virtual-Host-Direktive anzulegen.
Eigene Regeln
Mod_rewrite macht nichts anderes, als Adressen anhand bestimmter Regeln umzuschreiben. Dazu bringt es eine Vielzahl von Direktiven mit, die das Apache-Handbuch komplett dokumentiert [1]. Die wesentlichen Funktionen bildet das Modul mit den Funktionen RewriteRule und RewriteCond ab. Erstere regelt, in welcher Art das Modul die Adressen umschreibt, letztere besagt, wann der Mechanismus greift. Erst wenn die in RewriteCond definierten Regeln erfüllt sind, erfolgt das Umschreiben mittels RewriteRule. Bedingungen legen Sie wahlweise einzeln oder kumulativ fest. Ein Beispiel:
RewriteRule ^/weihnachten2010\.html$ /ostern2011.html
Diese Zeile leitet den Aufruf der Seite /weihnachten2010.html, die hier beispielhaft für die Weihnachtskampagne eines Versandhauses steht, auf die der Jahreszeit angepasste Seite für das Ostergeschäft weiter, /ostern2011.html. Die Zieladresse ist dabei kein absoluter Pfad im Dateisystem sondern die URL, wie Sie sie auch im Browser eingeben würden. Rufen Sie jetzt die weihnachtliche Seite auf, so leitet Apache die Anfrage um – für den Besucher transparent: Er sieht in der Adresszeile nach wie vor die Weihnachts-URL.
Für manche Umleitung mag das wünschenswert sein, doch gerade wenn Sie Adressen dauerhaft ändern, weisen Sie den Anwender und insbesondere Suchmaschinen besser darauf hin. Fügen Sie dazu den Parameter R=permanent in eckigen Klammern hinzu, der dann den Status-Code 301 auslöst:
RewriteRule ^/weihnachten2010\.html$ ostern2011.html [R=permanent]
Wollen Sie nicht auf ein internes Angebot, sondern auf die Seite eines Dritten weiterleiten, so geben Sie die komplette URL an – in diesem Fall sieht der Besucher die Umleitung aber in jedem Fall:
RewriteRule ^/weihnachten2010\.html$ http://meineandereseite.tld/ostern2011.html [R=permanent]
Beachten Sie die Schreibweise von Quelle und Ziel. Die bisherigen Beispiele geben als Zieladresse stets eine normale absolute oder relative URL an – die Quelle jedoch als sogenannten regulären Ausdruck. Diesen umschließen die Zeichen ^ (Hochkomma) und $ (Dollar). Als weitere Besonderheit gilt es, in der Adresse vorkommende Punkte mit einem \ (Backslash) zu maskieren (auch “escapen” genannt). Das mutet zunächst umständlich an, hat aber einen guten Grund: Reguläre Ausdrücke verwenden auch Platzhalter, die eine Vielzahl von Fällen auf einmal abdecken. Ein Beispiel:
RewriteRule ^/[^/]*2010\.html$ /ostern2011.html [R=permanent]
Mit dieser Regel schreiben Sie sämtliche Adressen um, in denen 2010.html vorkommt und die im Stammverzeichnis der Domain liegen. [^/]* steht als regulärer Ausdruck für eine beliebige Anzahl von Zeichen, jedoch nicht den Backslash. Konkret heißt das, die Regel sowohl /januar2010.html abgedeckt, also auch /januar2010.htm, nicht jedoch /januar2010.htmlx, denn den Ausdruck schließt ein Dollarzeichen ab. Allerdings zählt auch /2010.html als Treffer, denn [^/]* bedeutet auch, dass gar kein Zeichen vorkommt. Um zumindest ein einziges Zeichen zu verlangen, und sowohl html als auch htm als Endung zuzulassen, ersetzen Sie den Stern durch ein Plus, und verwenden .? als Platzhalter, was so viel bedeutet wie “kein oder genau ein Zeichen”:
RewriteRule ^/[^/]+2010\.htm.?$ /ostern2011.html [R=permanent]
Jetzt sehen Sie auch den Grund, warum vor Punkten der Backslash steht: Während Sie mit \. den Punkt als Bestandteil der Domain bezeichnen, steht .? als Platzhalter und nicht für einen Punkt gefolgt von einem Fragezeichen.
Schleierhaftes
Ein Trick ermöglicht es, eine Umleitung vor dem Besucher zu verschleiern – nämlich dann, wenn Mod_rewrite gleichzeitig als Proxy agiert. Da manche Applikationen die Adresse explizit setzen, funktioniert das zwar nicht in allen Fällen, aber oft hilft es weiter. Der Besucher sieht die aufgerufene Adresse, und auch Suchmaschinen indizieren sie anstelle der eigentlichen Zieladresse. Um diese Funktion zu aktivieren, laden Sie über den Kommandozeilenbefehl sudo a2enmod proxy_http das Proxy-Modul und starten Apache anschließend neu. Danach ersetzen Sie den Schalter R=permanent durch proxy:
RewriteRule ^/[^/]+2010\.htm.?$ http://meineandereseite.tld/ostern2011.html [proxy]
Allerdings sollten Sie davon nicht zu regen Gebrauch machen, denn das Proxy-Modul reduziert nicht nur die Geschwindigkeit, sondern hat auch noch andere Nachteile: Die Seite, auf die das Modul weiterleitet, sieht in der Regel lediglich die IP-Adresse des Proxies, nicht jedoch des eigentlichen Besuchers. Das stört nicht nur bei der Besucherzählung, sondern verschleiert unter Umständen auch Angriffe. Deswegen sollten Sie sich vor dem Aktivieren des Proxymoduls eingehend mit dessen Konfiguration befassen [2]. Ein falsch konfigurierter Proxy führt im schlimmsten Fall dazu, dass Ihr Server als offenes Relay für kriminelle Zwecke dient.
Doppelt gemoppelt
Im nächsten Schritt definieren Sie zwei Regeln, die Apache hintereinander abarbeitet: Mit den zwei Zeilen aus Listing 2 schreiben Sie alle Dateien mit dem Namensbestandteil 200*.html(l) auf /archiv.html um. Die erste Zeile hilft beispielsweise dabei, alle Kampagnen des letzten Jahres – gleich ob Weihnachten, Ostern oder Sommerschlussverkauf – auf die aktuelle Sonderseite weiterzuleiten. Die Seiten der Jahre 2004 bis 2009 hingegen leiten Sie direkt ins Archiv.
Listing 2
RewriteRule ^/[^/]+2010\.htm.?$ /ostern2011.html [R=permanent] RewriteRule ^/[^/]+200[4-9]\.htm.?$ /archiv.html [R=permanent]
Bedingungslos
Die bisherigen Weiterleitungen greifen wegen fehlender Bedingungen immer. Um genauer zu bestimmen, wann überhaupt eine Umleitung erfolgt, legen Sie mittels RewriteCond genaue Bedingungen fest. Beachten Sie, dass RewriteCond nur für die jeweils nächste Zeile greift und daher unmittelbar vor der Regel stehen muss.
Mit dem Dreizeiler aus Listing 3 verfeinern Sie beispielsweise die Weiterleitungsvoraussetzung der vergangenen Kampagnen. Für die Seiten aus den Jahren 2004 bis 2009 erfolgt eine Weiterleitung nur dann, wenn die Datei noch im Dateisystem existiert, andernfalls erscheint lediglich eine Fehlerseite. Da die RewriteCond nur über der ersten Regel steht, greift sie nur für diese – Weiterleitungen für die Kampagnen im Jahre 2010 erfolgen entsprechend unabhängig davon, ob die ursprünglichen Dateien existieren.
Listing 3
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/[^/]+200[4-9]\.htm.?$ /archiv.html [R=permanent]
RewriteRule ^/[^/]+2010\.htm.?$ /ostern2011.html [R=permanent]
Ein weiteres Praxisbeispiel zeigt Bedingungen für das Nutzen mehrerer Domains. Angenommen, Sie verwalten linuxuser.de, www.linuxuser.de, linux-user.de und www.linux-user.de, die Sie als Server-Alias in einem virtuellen Host verwenden. Als Schreibweise möchten Sie nur die Schreibweise www.linux-user.de benutzen und andere Anfragen entsprechend weiterleiten. Das richten sie mit den beiden Zeilen aus Listing 4 ein.
Listing 4
RewriteCond %{HTTP_HOST} !^www\.linux-user\.de$ [nocase]
RewriteRule ^(.*)$ http://www.linux-user.de$1 [R=permanent]
Alle Ergebnisse aus Suchmustern, die in Klammern stehen, bilden Variablen ab. Die erste Klammer referenzieren Sie als $1, die zweite Klammer als $2 und so weiter. Das Beispiel aus Listing 4 führt also dazu, dass alles ab dem Domainnamen in dieser Variable landet. Ruft nun jemand http://linuxuser.de/ausgabe/index.html auf, leiten Sie ihn damit automatisch zu http://www.linux-user.de/ausgabe/index.html weiter.
Ähnliches gilt auch für Domains mit verschiedenen Endungen. Am Beispiel sehen Sie auch, dass RewriteCond auch Parameter akzeptiert. nocase bedeutet beispielsweise, dass das Modul die Groß- und Kleinschreibung von Adressen und Pfaden nicht berücksichtigt.
Aus Alt mach Neu
Ebenso praktisch sind Bedingungen, wenn Sie den Inhalt einer alten Seite in eine neue integrieren. Liegen die Inhalte der alten Seite im Pfad /alt, leiten Sie Besucher der alten Adresse einfach mit drei Zeilen darauf um, sodass die gewohnten Links auch weiterhin funktionieren (Listing 5, oben). Dank eines regulären Ausdrucks verkürzen Sie die Schreibweise wahlweise auch auf nur zwei Zeilen (Listing 5, unten).
Listing 5
Ausführliche Schreibweise:
RewriteCond %{HTTP_HOST} ^alteseite\.tld$ [OR]
RewriteCond %{HTTP_HOST} ^www\.alteseite\.tld$
RewriteRule ^(.*)$ http://www.neueseite.tld/alt$1 [R=permanent]
Verkürzte Schreibweise mit RegEx:
RewriteCond %{HTTP_HOST} ^(www\.)?alteseite\.tld$
RewriteRule ^(.*)$ http://www.neueseite.tld/alt$1 [R=permanent]
Die Zeichen (www\.) dienen als Platzhalter, die in der URL vorkommen können, aber nicht müssen, was im Beispiel den Hostnamen mit und ohne www anspricht. Ebenso sehen Sie, wie der OR-Parameter zwei Bedingungen verbindet. Lassen Sie ihn weg, so nimmt mod_rewrite automatisch AND an und verwendet die beiden Bedingungen kumulativ statt alternativ. Das Beispiel aus Listing 6 schreibt die Domain um, aber nur jene ohne SSL-Verschlüsselung – ideal also, um Weiterleitungen zu vermeiden, bei denen der Zertifikatsname nicht stimmen würde.
Listing 6
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.meine-domain\.tld$
RewriteRule ^(.*)$ http://www.meinedomain.tld$1
Eingedickt
Das Rewrite-Modul ermöglicht durch die Unterstützung regulärer Ausdrücke sehr kompakte Schreibweisen. Sollen zum Beispiel sowohl die Subdomain site1 als auch site2 auf die Hauptseite verweisen, so drücken Sie dies wie in Listing 7 aus.
Listing 7
RewriteCond %{HTTP_HOST} ^(site1|site2)\.seite\.tld$
RewriteRule ^(.*)$ http://www.seite.tld$1 [R=permanent]
Zum Abschluss noch ein Tipp für Webmaster, die FTP-Downloads anbieten: Viele Browser erkennen eine solche Adresse automatisch und schalten das Protokoll um – allerdings klappt das nicht immer. Mit den zwei Zeilen aus Listing 8 leiten Sie die FTP-Subdomain direkt um.
Listing 8
RewriteCond %{HTTP_HOST} ^ftp\.ihrefirma\.tld$
RewriteRule ^(.*)$ ftp://ftp.ihrefirma.tld$1 [R=permanent]
Fazit
Mod_rewrite ist extrem mächtig und kann noch weitaus mehr, als dieser Artikel beschreibt. So werten Sie damit auch die IP-Adresse des Zugreifenden, den verwendeten Browser, den Referer und die aktuelle Tageszeit aus, oder speichern umfangreiche Regelwerke in einem externen Map-File [3].
Infos
[1] Dokumentation zu Mod_rewrite: http://httpd.apache.org/docs/current/mod/mod_rewrite.html
[2] Wichtige Hinweise zu Mod_proxy: http://httpd.apache.org/docs/current/mod/mod_proxy.html
[3] Benutzung von Rewrite-Maps: http://httpd.apache.org/docs/current/rewrite/rewritemap.html






Hallo Herr Effenberger, vielen Dank erst einmal für den tollen Artikel! Das Prinzip mit dem Umschreiben habe ich verstanden, und in der Praxis funktioniert das auch so weit. Jedoch habe ich einen Fall, der mit nicht ganz einleuchtet. Folgende RewriteRule wird bei WordPress verwendet und funktioniert auch: RewriteRule . /index.php [L] Hier wird quasi alles nach index.php umgeschrieben und trotzdem schafft es das PHP Skript, den richtigen Artikel anzuzeigen – ohne dass zumindest offensichtlich Query-Parameter oder andere Informationen an index.php übergeben werden. Ein Test mit einer RewriteRule, die auf eine externe URL umschreibt, auf der mit netcat ein simpler TCP-Server… Mehr »
Hallo Marc, soweit ich das im Netz recherchieren konnte, verhindert das [L] einen Loop, also eine Endlosschleife, bei der index.php immer wieder auf sich selbst verweist. Im Netz gibt es zu der Frage, wie das bei WordPress funktioniert, die Antwort auf folgender Seite:
http://stackoverflow.com/questions/5061880/this-is-the-htaccess-code-in-wordpress-can-someone-explain-how-it-works
Demzufolge gehören noch zwei weitere Anweisungen zu dem Block.
Beste Grüße
Andreas