mod_rewrite FAQ; Fehlerquellen/-meldungen (HTTP 403/404/500)
Titel wie mod_rewrite hilfe oder mod_rewrite problem etc. sind kontraproduktiv und sagen nichts über den Inhalt aus. Das es in einem Hilfe-Forum um Probleme geht, sollte selbstverständlich sein.
Versuch: FAQ, mögliche Fehlerquellen und Fehlermeldungen beim Gebrauch von mod_rewrite
-> 1.-3. behandelt die Frage, ob mod_rewrite überhaupt auf dem Server läuft,
-> 4.-5. einzelne Problemstellungen
1. Modul geladen?
2. Jede Regel wird ignoriert - es passiret rein gar nichts
3. Fehler 403 Forbidden
4. Fehler 500 Internel Server Error
5. Einzelne Regeln laufen nicht oder nicht richtig (auch Bilder werden nicht geladen, 404 Not Found)
7. FAQ: Q & A (questions and answers)
8. Frage wurde in der FAQ nicht beantwortet
(wird fortgesetzt)
1. Ist das Modul mod_rewrite überhaupt geladen?
- :idea: Die primäre Voraussetzung, um mod_rewrite zu nutzen, ist, dass das Modul im Apache-Webserver überhaupt geladen ist.
Beschreibung: Sofern PHP als Modul (nicht CGI) auf dem Server genutzt wird: Gucke im Output von phpinfo() unter "apache" und dann Loaded Modules, ob das Modul mod_rewrite dort auftaucht.
Lösung: Falls Du Zugriff auf die Serverkonfigurationsdatei „httpd.conf“ hast, suche den Abschnitt, in der die Module über die LoadModule-Direktive geladen werden. Dort sollte ein Eintrag stehen, der wie folgt oder ähnlich lautet:
Code: Alles auswählen
LoadModule rewrite_module modules/mod_rewrite.so
Falls du keinen Zugriff auf die Serverkonfigurationsdatei hast, wende dich an deinen Webhosting-Anbieter.
2. Du hast in der .htaccess folgende Anweisung stehen, es passiert aber nichts. Sämtliche Regeln laufen auch nicht. Auch in den Log-Dateien steht nichts.
- Füge in eine .htaccess im document root (also /.htaccess) folgenden Code ein ("google-Test"):
Code: Alles auswählen
RewriteEngine On
RewriteRule ^ http://www.google.de [R,L]
Rufe dann im Browser z.B. /abc/ auf. Du solltest dann immer auf Google.de weitergeleitet werden. Ist das der Fall: Dann solltest du mod_rewrite problemlos nutzen können. Sollte der Test jedoch nicht funktionieren:
Ursache: Die Direktive AllowOverride in der httpd.conf für deinen <Directory>-Abschnitt steht auf none oder erlaubt nicht FileInfo zu überschreiben.
In AllowOverride wird quasi angegeben, was in .htaccess-Dateien alles genutzt werden kann (bzw. welche Einstellungen aus der httpd.conf überschrieben werden können). Für den Gebrauch von mod_rewrite muss FileInfo überschrieben werden dürfen.
Lösung: Ohne Zugriff auf die Serverkonfigurationsdatei kann man da nichts machen, siehe 6.; Minimal-Config im <Directory /www/user1/htdocs/> also:
Code: Alles auswählen
AllowOverride FileInfo
3. Bei der unter 2. aufgeführten .htaccess-Datei kommt beim Webseitenaufruf der Fehler 403 Forbidden.
- In der Apache-Errorlog steht dazu:
- in der .htaccess oben folgende Zeile einfügen
Code: Alles auswählen
Options +FollowSymlinks
Das funktioniert aber nur, wenn du in der .htaccess die Direktive Options überschreiben darfst (vgl. Problem AllowOverride unter 2.). Wenn das Überschreiben von Optionen in .htaccess-Dateien nicht freigegeben ist, kommt beim Webseitenaufruf ein „500 Internal Server Error“-Fehler. Dann wurde das Überschreiben eben nicht freigegeben und du kannst nicht Options +FollowSymlinks einfügen. In der Apache-Errorlog steht dazuOhne Zugriff auf die Serverkonfigurationsdatei httpd.conf kann man hier nichts machen, siehe 6.; es müssten FollowSymlinks oder SymLinksIfOwnerMatch in der Serverkonfiguration freigeschaltet werden (s. nächster Schritt)Code: Alles auswählen
[alert] [client ...] /www/user1/htdocs/.htaccess: Options not allowed here
- Wenn du Zugriff auf die Serverkonfigurationsdatei hast, in dem <Directory>-Abschnitt für deine htdocs, also bspw. <Directory /var/www> (jedoch nicht <Directory />), füge Folgendes ein bzw. ergänze die vorhandene Optionen durch Folgendes:
Code: Alles auswählen
Options +FollowSymlinks
Noch einmal-- Achtung: Es gibt mehrere <Directory>-Abschnitte in der httpd.conf! zu erst <Directory />. Dieser Abschnitt ist restriktiv konfiguriert und vererbt (sofern nicht überschrieben) auf darunter liegende <Directory>-Abschnitte. Dort sollten keine Änderungen vorgenommen werden! FollowSymLinks daher in dem für die htdocs vorgesehenen Abschnitt <Directory /var/www> einfügen.
Code: Alles auswählen
[error] [client …] Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden: /www/user1/htdocs/
Ursache: Das Nutzen von mod_rewrite in .htaccess-Dateien ist zwar erlaubt (vgl. 2., also AllowOverride ist korrekt gesetzt), jedoch ist bei der Direktive Options die Option FollowSymLinks oder SymLinksIfOwnerMatch abgeschaltet.
FollowSymLinks bedeutet, dass der Server symbolischen Links folgt. SymLinksIfOwnerMatch bedeutet, dass der Server nur symbolischen Links folgt, bei der die Benuzerkennung des Links mit der Benutzerkennung des Zielverzeichnis/-datei übereinstimmt. Letzteres sollte wenn möglich vermieden werden (Performance).
Lösung: (mehrere Möglichkeiten)
4. Bei deiner eigenen RewriteRule kommt 500 - Internal Server Error
- :idea: Ursache: In 90 % der Fälle ein Syntaxfehler in den RewriteRule(s) bzw. fehlerhafte .htaccess-Dateien (Endlosschleife, unzulässiges Überschreiben von Direktiven). Es könnte jedoch auch das Modul nicht geladen sein, vgl. 1. oben)
- Überprüfe deine Regel/Bedingungen auf eventuelle Syntaxfehler, unter anderem Zeichen, die nicht escaped wurden (s. 5a, 2. Punkt). In der error.log steht dazu
Code: Alles auswählen
--> bei einem Syntaxfehler in einer RewriteCondition
[alert] [client ...] LOCAL_PATH_TO/.htaccess: RewriteCond: bad flag delimiters
--> oder bei einem Syntaxfehler in einer RewriteRule
[alert] [client ...] LOCAL_PATH_TO/.htaccess: RewriteRule: bad flag delimiters - .htaccess-Datei: Stelle sicher, dass die Datei in dem Zeichensatz ANSI gespeichert wurde und im ASCII-Modus auf den Server geladen wurde.
- In der .htaccess werden Direktiven überschrieben (wie z.B. die Options-Direktive, Options +FollowSymLinks etc.), das Überschreiben dieser Direktiven wurde aber in der Serverkonfigurations (AllowOverride) unterbunden. In der Apache-Errorlog steht dazu
Code: Alles auswählen
[alert] [client ...] /www/user1/htdocs/.htaccess: Options not allowed here
- Endlosschleife / das Umleitungslimit wurde überschritten: Stelle sicher, dass die umgeschriebene Datei nicht wieder auf eine RewriteRule zutrifft. Beispiel für eine Regel, die zu einer Endlosschleife führt:In der Apache-Errorlog steht dazu
Code: Alles auswählen
RewriteRule .* /index.php
Abhilfe schafft das Ausschließen der Datei durchCode: Alles auswählen
[error] [client ...] mod_rewrite: maximum number of internal redirects reached. Assuming configuration error. Use 'RewriteOptions MaxRedirects' to increase the limit if neccessary.
über der jeweiligen (Problem verursachenden) RewriteRule. Im Endeffekt also:Code: Alles auswählen
RewriteRule !index\.php - [C]
Code: Alles auswählen
RewriteEngine On
RewriteRule !index\.php - [C]
RewriteRule ^ /index.php
Übersetzt bedeutet das soviel wie "RewriteEngine aktivieren; wenn nicht die index.php angefordert wurde - mache nichts und verkette mit der nachfolgenden Regel". Also nur, wenn die index.php nicht angefordert wurde, wird die darunter stehende Regel ausgeführt.
Eine weitere Möglichkeit ist das Abändern der RewriteRule:Hier also ohne führenden Slash bei der index.php, wenn sich die Datei mit der .htaccess-Datei in einem Verzeichnis befindet. In der rewrite_log steht dannCode: Alles auswählen
RewriteRule ^ index.php
Code: Alles auswählen
initial URL equal rewritten URL: /www/user1/htdocs/index.php[IGNORING REWRITE]
ACHTUNG: Das kann jedoch bei der Verwendung des N-Flags beim Behandeln von Unterverzeichnissen zu Fehlern führen. Der Apache kollabiert dann mit dem Rechner in der Form, dass der gesamte Virtuelle Speicher regelrecht "aufgefressen" wird.
Lösung:
5. Einzelne Regeln laufen nicht oder nicht richtig
- Sachen werden nicht gefunden - HTTP 404 Not Found kommt
- Bilder/Stylesheets/JavaScripts werden nicht mehr geladen/gefunden
Bilderverzeichnisse etc. müssen ggf. analog wie die index.php von den Rewrite-Regeln ausgenommen werden siehe 4a.. Alle Angaben zu Bildern etc. müssen ggf. absolut referenziert werden, insbesondere wenn virtuelle Verzeichnisse verwendet werden, die Seite also virtuell unter /aa/bb/cc/index.html zu finden ist.- :idea: Ursache: Relative URLs werden immer von der aktuellen URL ausgehend zu absoluten aufgelöst. Die Pfadangabe bilder/hallo.gif würden in /aa/bb/cc/index.html geschrieben zu /aa/bb/cc/bilder/hallo.gif aufgelöst.
- Dokumente werden nicht gefunden: Einige besondere Zeichen wurden u.U. nicht escaped.
Bestimmte Zeichen sind eine Art Steuerzeichen. Wenn sie verwendet werden sollen, müssen sie durch Voranstellen von einem Backslash (\) escaped werden. Folgende Zeichen müssen escaped werden, sofern sie als String-Ausdruck in dem Pattern(/Searchstring)-Teil von RewriteRule oder RewriteCond Verwendung finden sollenCode: Alles auswählen
. - der Punkt: bspw. RewriteRule ^index\.php$ /index.html
+ - das Pluszeichen: \+
* - der Stern: etc.
^ - ...
$ - Dollarzeichen
[Leerzeichen] bspw. hallo\ welt
? - Fragezeichen
\ - Backslash
| - ...
( - sämtliche Klammern
)
[
{
Lösung: Verwende wenn möglich absolute Quellenangaben, also entweder nur absolute Pfadangaben (/bilder/hallo.gif) oder gleich absolute URLs (http://example.com/bilder/hallo.gif). Eine andere Möglichkeit besteht bei HTML, eine Basis-URL für ein Dokument festzulegen, von der aus dann die relativen URLs aufgelöst werden, beispielsweise:Code: Alles auswählen
<base href="http://example.com">
- Dokumente werden nicht gefunden: Einige besondere Zeichen wurden u.U. nicht escaped.
- Es passiert nichts, die RewriteRule "matched" nicht oder funktioniert fehlerhaft; die Regel unter 2. funktioniert aber
- Eventuell ist die Regel fehlerhaft. Achte auf die Notation des Slashsist in einer.htaccess-Datei falsch. Die Zeichenkette des Search-Strings in der RewriteRule (index.php) beginnt (^) in .htaccess-Dateien NICHT mit einem Slash. Der Slash muss nur in der Serverkonfiguration, also in einem <Directory>- oder <VirtualHost>-Abschnitt mit angegeben werden. Richtig muss die Regel also lauten:
Code: Alles auswählen
RewriteRule ^/index\.php$ /index.html [L]
Code: Alles auswählen
RewriteRule ^index\.php$ /index.html [L]
- Die Variablen werden bei folgender RewriteRule falsch übergeben, die SESSIONID geht verloren
-> bei /werkstatt/hammer/?PHPSESSID=a3a634ss467w soll aufgerufen werden
-> index.php?ort=werkstatt&zeug=hammer&PHPSESSID=a3a634ss467w.Die Session-ID verschwindet aber, warum?Code: Alles auswählen
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?ort=$1&zeug=$2 [L]
Weil der Query String (so nennt sich der teil hinter dem Fragezeichen in der URL) durch einen anderen ersetzt wird (ort=$1&zeug=$2). Um aber den Query String nur zu ergänzen, muss das QSA-Flag notiert werden (Query String Append, alsoCode: Alles auswählen
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?ort=$1&zeug=$2 [QSA,L]
- Eventuell ist die Regel fehlerhaft. Achte auf die Notation des Slashs
- Bilder/Stylesheets/JavaScripts werden nicht mehr geladen/gefunden
6. Frage deinen Provider, ob er die hinter dem Verweis auf diesen Unterpunkt stehende Anweisung in der Serverkonfiguration für dein Directory ändern kann.
7. FAQ: Q & A (questions and answers)
- :?: Wie kann ich auf Variablen der aufgerufenen Seite zugreifen (QueryString)? Es wird die URI http://www.example.com/fileinfo.php?fil ... rdner=data aufgerufen und vom Browser angefordert. Sie soll per externer Weiterleitung (redirect) zu http://www.example.com/datei/data/datei1.txt werden. Wie kann ich dabei auf die per GET übergebenen Variablen file und ordner im QueryString zugreifen?
per folgendem Code in deiner .htaccess-DateiCode: Alles auswählen
RewriteEngine On
RewriteCond %{QUERY_STRING} ^file=([^&]+)&ordner=([^&]+)$
RewriteRule ^fileinfo\.php$ /datei/%2/%1? [R=301,L]
Per %n kann auf die 'Variablen'/Platzhalter der letzten RewriteCondition über der RewriteRule zugegriffen werden. Um den QueryString aus einer URL bei einem forced external Redirect zu entfernen, muss ein ? bei der Substitution angefügt werden (wie oben %1?)
Auf den QueryString kann nicht direkt über eine RewriteRule zugegriffen werden, wie in folgendem Beispiel:Code: Alles auswählen
#falsch!
RewriteRule ^fileinfo\.php\?file=([^&]+)&ordner([^&]+) /datei/$2/$1 [R=301,L]
Weitere Beispiele:
alteDatei.php?id=33 --> neueDatei.php?user_id=33. Es soll also auf die id zugrgriffen werden. Die Variable id wird umbenannt in user_id und an neueDatei.php weitergeleitet.Code: Alles auswählen
RewriteEngine On
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
# In der Variable %1 steht folglich der Wert des Klammerausdrucks, bei id=33 also der Wert 33
RewriteRule ^alteDatei\.php$ /neueDatei.php?user_id=%1 [L]
# NICHT
RewriteRule ^alteDatei\.php\?id=([0-9]+) /neueDatei.php?user_id=$1 [L]
dateiname.php?var=wert --> nach index.php?file=dateiname&var=wert (praktisch soll auf index.php umgelenkt werden und an den alten QueryString soll der Dateiname angehangen werden)Code: Alles auswählen
RewriteEngine On
RewriteRule !^index\.php$ - [C]
RewriteRule ^([^.]+)\.php$ /index.php?file=$1 [QSA,L] - :?: Wie kann ich, wenn meine Website mit http:// aufgerufen wurde, automatisch auf https:// umleiten?
Das geht per folgendem Code in deiner .htaccess-DateiCode: Alles auswählen
RewriteEngine On
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
Für einen Eintrag in der httpd.conf, nutzeWenn der verwendete Serverport nicht 443 ist (das ist standardmäßig der SSL-Port), werden alle Anfragen auf das https-Protokoll umgeleitet. R=301 bewirkt dabei, dass der Status moved permanently (301) gesendet wird. Suchmaschinen werden entsprechend die Seiten im Index auf das https-Protokoll ändern ändern.Code: Alles auswählen
RewriteEngine On
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^/(.*)$ https://www.example.com/$1 [R=301,L] - :?: Wie kann ich unterschiedliche Startseiten für mehere Domains (sog. C-NAMES) anzeigen?, also
domain1.com --> domain.com/index1.html
domain2.com --> domain.com/index2.html
Alle Domains zeigen auf das gleiche Verzeichnis.
Die Differenzierung kann über den HTTP_HOST vorgenommen werden. Dazu musst du in deiner .htaccess-Dateieinfügen.Code: Alles auswählen
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.com
RewriteRule ^$ index1.html
RewriteCond %{HTTP_HOST} ^(www\.)?domain2\.com
RewriteRule ^$ index2.html
Bei Zugriff auf die httpd.conf bietet sich das Einrichten von VirtualHosts an. - :?: Wie kann ich in meinem Dateinamen für alle ankommenden Requests (z.B. durch Suchmaschinen, Forenlinks) alle Unterstriche in dem Dateinamen durch Bindestriche ersetzen?
/meine_html_datei.html soll folglich per redirect an
/meine-html-datei.html umgeleitet werden. Alle HTML-Links im Quelltext der einzelnen Seiten innerhalb des <a href="">-Elements habe ich bereits manuell "auf Bindestriche" umgestellt.
Jetzt soll erreicht werden, dass wenn Suchmaschinen meine alten Links mit Unterstrichen besuchen, sie automatisch zu den neuen mit Bindestrichen umgeleitet werden.
Wie bereits vor einiger Zeit hier im Forum beschrieben, geht das über folgenden Code:Code: Alles auswählen
RewriteEngine On
RewriteRule ^([^/_]+)_([^/.]+)\.html$ $1-$2.html [N]
RewriteCond %{THE_REQUEST} ^GET\ /([^_]+)_([^\ ]+)\ HTTP
RewriteRule ^([^/-]+)-([^/.]+)\.html$ /$1-$2.html [R=301,L]
Zuerst wird eine Schleife durchlaufen, die alle Unterstriche zwischen anderen Zeichen durch einen Bindestrich ersetzt. Das N-Flag bewirkt dabei, dass die Regeln erneut von Anfang an durchlaufen werden. Werden keine Unterstriche mehr gefunden, greift die zweite Regel, sofern ein Bildestrich in dem Pattern überhaupt vorhanden ist. Dann wird der Redirect auf die URL mit Bindestrichen mit dem Statuscode 301 (moved permanently) gesendet. - :?: Variablen aus Path in QueryString umwandeln
Ein Aufruf von /index,get1_val1,get2_val2,get3_val3.html ---soll--in--> /index.php?get1=val1&get2=val2&get3=val3 umgewandelt werden:Code: Alles auswählen
RewriteEngine on
RewriteRule ^([^/,.]+),([^/_]+)_([^/,.]+)([^/.]*)(\.html)?$ $1$4?$2=$3 [QSA,N]
RewriteRule ^([^/.]+)$ /$1.php [L]
Ein Aufruf von /index-start-index-return-links.html --wird--in---> /index.php?start=index&return=links umgewandelt.Code: Alles auswählen
RewriteEngine On
RewriteRule ^(index)-([^/-]+)-([^/.-]+)([^/.]*)(\.html)?$ $1$4?$2=$3 [QSA,N]
RewriteRule ^index$ /index.php [L] - :?: Es wird nur eine weiße Seite angezeigt
Es wird auf eine PHP-Datei intern umgeschrieben, z.B. von /index.html --> index.php?page?index viaCode: Alles auswählen
RewriteEngine on
RewriteRule ^([a-z]+)\.html$ /index.php?page=$1 [L]
Der Apache gibt jedoch nur eine leere, weiße Seite zurück. Ein external redirect funktioniert jedoch wie gewünscht:Code: Alles auswählen
RewriteEngine on
RewriteRule ^([a-z]+)\.html$ http://www.example.com/index.php?page=$1 [R,L]
Es liegt ein PHP-Problem vor. PHP muss neu installiert werden. Siehe http://www.modrewrite.de/foren/ftopic1452.html
8. Deine Frage wurde hier nicht oder nicht ausreichend beantwortet, dann eröffne einen neuen Thread. Gebe doch bitte auch Rückmeldung, wenn eine gepostete Lösung funktioniert hat. Dadurch wissen Andere mit einem ähnlichen Problem beim durchstöbern gleich, dass es eigentlich funktionieren müsste.
Überarbeitet am 2008-01-18 (Gumbo)
Bitte nicht in meinen Beiträgen ohne namentliche Kennzeichnung der Änderungen pfuschen. Danke.