mod_rewrite FAQ; Fehlerquellen/-meldungen (HTTP 403/404/500)

URLs umschreiben, umleiten, blocken oder sperren - all das und noch viel mehr kann mit mod_rewrite erreicht werden. Mit regulären Ausdrücken, Conditions und Rules stehst Du auf Kriegsfuss? mod_rewrite macht nicht das was Du willst, oder funktioniert gar nicht? hier bist Du richtig!

Moderatoren: Bob, Super-Mod

mod_rewrite FAQ; Fehlerquellen/-meldungen (HTTP 403/404/500)

Beitragvon Bob » 24.10.2004 20:08

Bei Eröffnung eines neuen Topics bitte immer aussagekräftige Betreffs wählen - dass es hier in 99% der Fälle um mod_rewrite geht, ist wohl jedem klar. Danke.
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
    Ist dieser auskommentiert (#…), entferne das Kommentarzeichen und starte Apache neu.
    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:

    :idea: 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
. Wichtig dabei ist das Setzen von AllowOverride im richtigen <Directory>-Container. Davon gibt es in der httpd.conf mehere. Suche den heraus, der dein DocumentRoot enthält, also bspw. <Directory /www/user1/htdocs>, jedoch nicht in <Directory />.

3. Bei der unter 2. aufgeführten .htaccess-Datei kommt beim Webseitenaufruf der Fehler 403 Forbidden.
    In der Apache-Errorlog steht dazu:
    Code: Alles auswählen
    [error] [client …] Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden: /www/user1/htdocs/

    :idea: 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)
    1. 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 dazu
      Code: Alles auswählen
      [alert] [client ...] /www/user1/htdocs/.htaccess: Options not allowed here
      Ohne 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)
    2. 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.

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)
    :!: Lösung:
    1. Ü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


    2. .htaccess-Datei: Stelle sicher, dass die Datei in dem Zeichensatz ANSI gespeichert wurde und im ASCII-Modus auf den Server geladen wurde.
    3. 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

    4. 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:
      Code: Alles auswählen
      RewriteRule .* /index.php
      In der Apache-Errorlog steht dazu
      Code: 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.
      Abhilfe schafft das Ausschließen der Datei durch
      Code: Alles auswählen
      RewriteRule !index\.php - [C]
      über der jeweiligen (Problem verursachenden) RewriteRule. Im Endeffekt also:
      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:
      Code: Alles auswählen
      RewriteRule ^  index.php
      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 dann
      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.

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.
        :!: 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.
        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 sollen
        Code: 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
        )
        [
        {
    • 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 Slashs
        Code: Alles auswählen
        RewriteRule ^/index\.php$ /index.html [L]
        ist 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]
      • 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.
        Code: Alles auswählen
        RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?ort=$1&zeug=$2 [L]
        Die Session-ID verschwindet aber, warum?
        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, also
        Code: Alles auswählen
        RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?ort=$1&zeug=$2 [QSA,L]

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)
  1. :?: 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-Datei
    Code: 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]

  2. :?: Wie kann ich, wenn meine Website mit http:// aufgerufen wurde, automatisch auf https:// umleiten?
    :!: Das geht per folgendem Code in deiner .htaccess-Datei
    Code: 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, nutze
    Code: Alles auswählen
    RewriteEngine On
    RewriteCond %{SERVER_PORT} !=443
    RewriteRule ^/(.*)$ https://www.example.com/$1 [R=301,L]
    Wenn 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.
  3. :?: 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-Datei
    Code: Alles auswählen
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.com
    RewriteRule ^$ index1.html
    RewriteCond %{HTTP_HOST} ^(www\.)?domain2\.com
    RewriteRule ^$ index2.html
    einfügen.
    Bei Zugriff auf die httpd.conf bietet sich das Einrichten von VirtualHosts an.
  4. :?: 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.
  5. :?: 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]

  6. :?: 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 via
    Code: 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.
Bob
Moderator
Moderator
 
Beiträge: 5044
Registriert: 01.10.2004 13:10

Zurück zu mod_rewrite

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste

cron