Change file extensions in URLs

Apache web server configuration for changing or hiding visible file extensions in the URL by URL rewriting.

Üblicherweise kann man in der URL bereits erkennen, mit welcher Skriptsprache die Webseiten programmiert sind. PHP-Seiten tragen demnach ein „.php“ in den Dateinamen, ASP.NET-Seiten ein „.aspx“ und statische HTML-Dateien erkannt man oft am bekannten „.html“. Dadurch beschreiben URLs aber nicht nur Identifikatoren für die eigentlichen Inhalte, wie es eigentlich gedacht ist, sondern sind auch von der verwendeten Technik abhängig. Was zu dem Problem führt, dass sich die URLs ändern, wenn man die Skriptsprache wechselt. Und so zahlreich, wie die heute sind, kann das schonmal vorkommen.

Daher habe ich diese Konfiguration entwickelt, mit der URLs ohne Dateiendung oder mit einer Ersatz-Dateiendung auf vorhandene Skriptdateien mit anderem Namen umgeleitet werden, ohne dass der Besucher etwas davon mitbekommt. Das ganze funktioniert sogar so, dass einzelne Seiten mit verschiedener Dateiendung vorliegen und jeweils die existierende ausgewählt wird.

Die folgenden Konfigurationsabschnitte müssen in der Konfigurationsdatei des Apache-Webservers eingetragen werden. Während das auch in der zentralen Serverkonfiguration geschehen kann, ist es für die meisten Webhosting-Benutzer praktikabler, die Anweisungen in einer .htaccess-Datei im Hauptverzeichnis des Webspace oder der jeweiligen Domain abzulegen.

Zuerst muss die URL-Umschreibung aktiviert werden:

RewriteEngine On

Der folgende Abschnitt enthält Konfigurationsanweisungen, die als .html-Datei angeforderte Seiten intern auf die gleichnamige .php-Seite umleitet, sofern die .html-Datei nicht bereits existiert und eine .php-Datei gefunden wurde. Das ermöglicht es, alle einzelnen Seiten in der URL mit der Dateiendung „.html“ zu referenzieren, obwohl tatsächlich PHP-Dateien gespeichert sind und vom Webserver ganz normal wie solche verarbeitet werden. Tatsächlich vorhandene HTML-Dateien bleiben davon unberührt und werden wie gewohnt ausgeliefert.

Benennt man später aus irgendeinem Grund die Dateien um, z. B. von *.php nach *.py, braucht man nur die zu suchende Dateiendung in dieser Konfiguration ändern (oder eine zusätzliche hinzufügen) – alle URLs funktionieren nach wie vor, es sind keine Änderungen an der Links nötig und Links von anderen Webseiten oder Suchmaschinen bleiben gültig.

# Replace ".php" by ".html"
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} ^(.*)\.html$
RewriteCond %1\.php -f
RewriteCond %{REQUEST_URI} ^(.*)\.html$
RewriteRule ^(.*)$ %1.php [L]

Der nächste Abschnitt enthält Konfigurationsanweisungen ähnlich dem ersten Abschnitt, nur dass statt einer Ersatz-Dateiendung wie „.html“ gar keine Dateiendung verwendet wird. Die Datei „/inhalt/kontakt.php“ kann somit über die URL „/inhalt/kontakt“ aufgerufen werden. Da hier nicht erst die Ersatzendung herausgeschnitten werden muss, ist diese Konfiguration einfacher und deshalb kürzer.

# Replace ".php" by ""
#
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

Die beiden vorgenannten Abschnitte suchen jeweils für eine URL den tatsächlichen Dateinamen mit der angegebenen Dateiendung, in diesem Beispiel „.php“. Um nach mehreren Dateiendungen zu suchen, wenn z. B. PHP- oder Python-Implementierungen für unterschiedliche Seiten vorliegen, lässt sich der jeweilige Abschnitt beliebig oft für weitere Dateiendungen wiederholen. Falls ein Dateiname mit mehreren unterstützten Endungen gefunden würde, entscheidet die Reihenfolge der Abschnitte in der Konfigurationsdatei; allerdings empfehle ich nicht, sowas zu tun.

Beim Setzen der Links innerhalb der Website muss man dann natürlich auch die öffentlich sichtbaren URLs verwenden statt der internen Dateinamen. Generell ist es ratsam, URLs und Dateinamen voneinander entkoppelt zu betrachten. So wie man gut zwischen Plaintext und HTML-Code unterscheiden muss, sind auch URLs und Pfadnamen unterschiedlich zu behandeln. Beachtet man solche Unterschiede durchgängig, vermeidet man typische Verwirrungsprobleme, die sich symptomatisch nur sehr unzuverlässig lösen lassen. Entsprechend sieht der HTML-Code nicht mehr so aus:

<p>
Weitere Informationen auf der <a href="download.php">Download-Seite</a>.
</p>

Sondern so, ohne die Dateierweiterung:

<p>
Weitere Informationen auf der <a href="download">Download-Seite</a>.
</p>

Das vollständige Verbergen der Dateiendung wie im zweiten Abschnitt beschrieben führt bei Dateien zu URLs, die denen von Verzeichnissen sehr ähnlich sehen. Gibt man die URL eines Verzeichnisses ohne den abschließenden Schrägstrich („/“) ein, leitet der Webserver den Browser automatisch auf die richtige Adresse um und der Schrägstrich wird hinzugefügt. Andersherum sollte der Schrägstrich aber auch entfernt werden, wenn die URL kein vorhandenes Verzeichnis beschreibt, aber ohne den Schrägstrich existieren würde. Diese Aufgabe übernimmt schließlich der letzte Abschnitt.

# External redirect for files requested as a directory (remove trailing slash)
#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.*)/$
RewriteCond %1 -U
RewriteRule ^(.*)$ %1 [L,R]

Ich habe diese Angaben mit Apache 2.2 auf Windows und Apache 2.0 und 2.2 auf Linux getestet, in verschiedenen Unterverzeichnissen und teilweise mit Query-Strings, hat überall funktioniert. Das RewriteLog (Level 9) gibt auch keinen Anlass zu Bedenken. Schaut also ganz gut aus, denk ich. :)

Statistic data

  • Created on 2007-08-04, updated on 2014-03-08.