Rolfi: mod_rewrite

Ola alle miteinander!
Ich habe zwei Probleme die ich euch erläutern möchte. Ich hoffe ihr findet meine Fehler, die ich nicht sehe. Fangen wir an, das ist mein aktuelles Gerüst:

RewriteCond %{REQUEST_URI} !-f  
RewriteCond %{HTTP_HOST} ^domainname\.(.*) [NC]  
RewriteRule ^$ index.php?d=%1&k=index [QSA]  
  
RewriteCond %{REQUEST_URI} !-f  
RewriteCond %{HTTP_HOST} ^domainname\.(.*) [NC]  
RewriteRule ^([-\w]+)\.html$ index.php?d=%1&k=$1 [QSA]

In der Selfhtml Dokumentation habe ich gelesen, dass sich %1 auf die >letzte< RewriteCond bezieht. Baue ich mir allerdings soetwas zusammen:

  
RewriteCond %{REQUEST_URI} !-f  
RewriteCond %{HTTP_HOST} ^domainname\.(.*) [NC]  
RewriteRule ^([-\w]+)\.html$ index.php?d=%1&k=$1 [QSA]  
RewriteRule ^$ index.php?d=%1&k=index [QSA]

Funktioniert die zweite RewriteRule nicht mehr (Unabhängig davon in welcher Reihenfolge ich die RewriteRule setze). Wieso, was ist plötzlich falsch? Da sich %1 laut der Dokumentation auf die RewriteCond bezieht, müsste das doch eigentlich problemlos funktionieren?? Naja, da das anscheinend für mich nicht gilt, musste ich es in zwei Blöcke aufteilen...

Nächstes Problem!
-f prüft doch, ob die Datei existiert oder nicht. Ein Ausrufezeichen davor bedeutet, "wenn die Datei nicht existiert" mache das und jenes. Ich wollte aber gerade meine Seite bei google manuell indizieren lassen, dabei muss man eine html file auf seinen webspace schieben. Gefordert getan, nur aufrufen kann ichs nicht (etwa: http://domainname.de/google-ka8zefsh8ef.html). Der geht mir nämlich trotzdem in die index.php und gibt mir, weil er dann den Datensatz in der Datenbank nicht zuordnen kann, ein liebes 404 Not Found aus, das ich selbst erstellt habe. Die Datei liegt wie die index.php im gleichen Verzeichnis. Aber laut !-f darf die Datei ja nicht existieren, damit er rein geht?
Hoste bei Strato.

Für eine Hilfe die meine Verwirrung aufdeckt, bin ich zutiefst verbunden!

Mfg,
Rolfi

  1. Tach!

    RewriteCond %{REQUEST_URI} !-f
    RewriteCond %{HTTP_HOST} ^domainname.(.*) [NC]
    RewriteRule ^([-\w]+).html$ index.php?d=%1&k=$1 [QSA]
    RewriteRule ^$ index.php?d=%1&k=index [QSA]

    
    >   
    > Funktioniert die zweite RewriteRule nicht mehr (Unabhängig davon in welcher Reihenfolge ich die RewriteRule setze). Wieso, was ist plötzlich falsch? Da sich %1 laut der Dokumentation auf die RewriteCond bezieht, müsste das doch eigentlich problemlos funktionieren?  
      
      
    RewriteConds gelten nur für die unmittelbar danach stehende RewriteRule. Deine zweite RewriteRule hat keine RewriteConds.  
      
    
    > -f prüft doch, ob die Datei existiert oder nicht. Ein Ausrufezeichen davor bedeutet, "wenn die Datei nicht existiert" mache das und jenes.  
      
    "Machen" macht eine RewriteCond gar nichts. Sie passt oder passt nicht und schränkt die RewriteRule weiter ein, die vorher schon gepasst haben muss.  
      
    
    > Ich wollte aber gerade meine Seite bei google manuell indizieren lassen, dabei muss man eine html file auf seinen webspace schieben. Gefordert getan, nur aufrufen kann ichs nicht (etwa: http://domainname.de/google-ka8zefsh8ef.html). Der geht mir nämlich trotzdem in die index.php und gibt mir, weil er dann den Datensatz in der Datenbank nicht zuordnen kann, ein liebes 404 Not Found aus, das ich selbst erstellt habe. Die Datei liegt wie die index.php im gleichen Verzeichnis. Aber laut !-f darf die Datei ja nicht existieren, damit er rein geht?  
      
    Für welche Regeln genau gilt jetzt dieses Problem? Ich kann dir nur soviel sagen, dass ^$ nur bei leerem Pfad zieht (ab der Stelle im Pfad, in der die Regeln wirken). -f mit oder ohne ! hat keine Auswirkungen mehr, weil die Regel ja nicht matcht, wenn ein Dateiname angegeben ist.  
      
      
    dedlfix.
    
    1. Ola dedlfix,

      Für welche Regeln genau gilt jetzt dieses Problem? Ich kann dir nur soviel sagen, dass ^$ nur bei leerem Pfad zieht (ab der Stelle im Pfad, in der die Regeln wirken). -f mit oder ohne ! hat keine Auswirkungen mehr, weil die Regel ja nicht matcht, wenn ein Dateiname angegeben ist.

      Also ich habe eine Datei von google, die heißt in etwa google-kasgdkuaskd7q72dhd.html (bliblablubb...). Die möchte ich ja aufrufen und die Datei existiert auch - alle anderen html Dateien die ich aufrufe existieren nicht. Aber du sagst, wenn ich es richtig verstehe, dass aufgrund des -f das nur prüft ob eine valide Datei z.b. test.html angefordert wurde (die nicht unbedingt bestehen muss), und er deshalb trotzdem in die RewriteRule geht, sodass ich die echte HTML Seite nicht aufrufen kann. Wie kann ich das dann umgehen?

      Grüße,
      Rolfi

      1. Tach!

        Also ich habe eine Datei von google, die heißt in etwa google-kasgdkuaskd7q72dhd.html (bliblablubb...). Die möchte ich ja aufrufen und die Datei existiert auch - alle anderen html Dateien die ich aufrufe existieren nicht. Aber du sagst, wenn ich es richtig verstehe, dass aufgrund des -f das nur prüft ob eine valide Datei z.b. test.html angefordert wurde (die nicht unbedingt bestehen muss), und er deshalb trotzdem in die RewriteRule geht, sodass ich die echte HTML Seite nicht aufrufen kann. Wie kann ich das dann umgehen?

        Nein. Zuerst wird eine passende RewriteRule gesucht. Wobei ^$ nur auf "leere" Requests passt, .* hingegen auf alle. Dann werden die vor dieser RewriteRule stehenden RewriteCond ausgewertet. Wenn die alle passen, dann wird der Request zum in der Rule angegebenen Ziel umgeschrieben, ansonsten wird die RewriteRule doch noch ignoriert.

        Wenn du nun eine RewriteRule hast, die auch auf diese (und andere vorhandene Dateien) passt, dann kannst du mit einer !-f RewriteCond die Ausführung des Rewrites verhindern.

        dedlfix.

        1. Ola dedlfix,

          Nein. Zuerst wird eine passende RewriteRule gesucht. Wobei ^$ nur auf "leere" Requests passt, .* hingegen auf alle. Dann werden die vor dieser RewriteRule stehenden RewriteCond ausgewertet. Wenn die alle passen, dann wird der Request zum in der Rule angegebenen Ziel umgeschrieben, ansonsten wird die RewriteRule doch noch ignoriert.

          Das ist wirklich sehr gut zu wissen, wie das funktioniert!! Dachte das geht immer andersrum.

          Wenn du nun eine RewriteRule hast, die auch auf diese (und andere vorhandene Dateien) passt, dann kannst du mit einer !-f RewriteCond die Ausführung des Rewrites verhindern.

          Das dachte ich ja "auch", dass ich es so verhindern kann. Aber anscheinend habe ich einen Fehler gemacht, den ich nicht finden kann.

          Ich analysiere das mal. Ich habe eine echte existente Datei namens "google-kasgdkuaskd7q72dhd.html"

          RewriteCond %{REQUEST_URI} !-f  
          RewriteCond %{HTTP_HOST} ^domainname\.(.*) [NC]  
          RewriteRule ^$ index.php?d=%1&k=index [QSA]
          

          Wie du richtig feststellst, erwartet ^$ einen leeren Request. Es steht also nichts hinter der Domain. Also wird nur was getan, wenn man direkt die Seite mit domainname.de oder welcher TLD auch immer, aufruft. Es wird hier nicht automatisch in vorhandene Dateien gegangen wie einer index.html oder index.php, da es vorher abgefangen wird. !-f trifft auch zu, da ein leerer Request keine Datei sein kann. Als Schlussfolgerung ziehe ich, dass "google-kasgdkuaskd7q72dhd.html" in diese RewriteRule nicht reinfällt.

          Nun der nächste Baustein, wenn denn eine Seite aufgerufen wird.

          RewriteCond %{REQUEST_URI} !-f  
          RewriteCond %{HTTP_HOST} ^domainname\.(.*) [NC]  
          RewriteRule ^([-\w]+)\.html$ index.php?d=%1&k=$1 [QSA]
          

          Es wird ein Request gesucht, der unbedingt mit einem Dateinamen anfängt der dabei den Bindestrich und Buchstaben/Zahlen enthalten kann. Er muss mit der Dateiendung .html enden. Nun geht er in die RewriteCond %{HTTP_HOST} und prüft ob er auf der Domain "domainname" ist und nimmt dann entsprechend die TLD am Ende weg um sie der RewriteRule anzufügen. Nun geht er in die letzte RewriteCond. Da die Datei "google-kasgdkuaskd7q72dhd.html" jedoch existiert, trifft diese RewriteCond nicht mehr zu, denn !-f steht ja dafür, dass "wenn die Datei nicht existiert", so wie du es auch sagst. Ab hier kommt es zu meinem Verständnisproblem, warum die Datei "google-kasgdkuaskd7q72dhd.html" dennoch in die RewriteRule fällt, obwohl sie existiert.

          mfg,
          Rolfi

          1. Tach!

            Ich habe eine echte existente Datei namens "google-kasgdkuaskd7q72dhd.html"

            RewriteCond %{REQUEST_URI} !-f

            RewriteCond %{HTTP_HOST} ^domainname.(.*) [NC]
            RewriteRule ^$ index.php?d=%1&k=index [QSA]

            
            >   
            > Wie du richtig feststellst, erwartet ^$ einen leeren Request. Es steht also nichts hinter der Domain. Also wird nur was getan, wenn man direkt die Seite mit domainname.de oder welcher TLD auch immer, aufruft. Es wird hier nicht automatisch in vorhandene Dateien gegangen wie einer index.html oder index.php, da es vorher abgefangen wird. !-f trifft auch zu, da ein leerer Request keine Datei sein kann. Als Schlussfolgerung ziehe ich, dass "google-kasgdkuaskd7q72dhd.html" in diese RewriteRule nicht reinfällt.  
              
            Die RewriteConds kommen gar nicht zur Auswertung, weil die Rule nicht matcht. Es ist in dem Fall also egal, was für Conds da stehen. Und die erste RewriteCond ist in jedem Fall überflüssig (selbst mit der Korrektur - siehe nachfolgend).  
              
            
            > Nun der nächste Baustein, wenn denn eine Seite aufgerufen wird.  
            > ~~~apache
            
            RewriteCond %{REQUEST_URI} !-f  
            
            > RewriteCond %{HTTP_HOST} ^domainname\.(.*) [NC]  
            > RewriteRule ^([-\w]+)\.html$ index.php?d=%1&k=$1 [QSA]
            
            

            Es wird ein Request gesucht, der unbedingt mit einem Dateinamen anfängt der dabei den Bindestrich und Buchstaben/Zahlen enthalten kann. Er muss mit der Dateiendung .html enden. Nun geht er in die RewriteCond %{HTTP_HOST} und prüft ob er auf der Domain "domainname" ist und nimmt dann entsprechend die TLD am Ende weg um sie der RewriteRule anzufügen. Nun geht er in die letzte RewriteCond.

            Es gibt ein RewriteLog, das zeigt genau, wann was in welcher Reihenfolge passiert oder nicht. Da muss man nicht raten. Allerdings kann diese Direktive nur im Server/VHost-Kontext gesetzt werden.

            Da die Datei "google-kasgdkuaskd7q72dhd.html" jedoch existiert, trifft diese RewriteCond nicht mehr zu, denn !-f steht ja dafür, dass "wenn die Datei nicht existiert", so wie du es auch sagst. Ab hier kommt es zu meinem Verständnisproblem, warum die Datei "google-kasgdkuaskd7q72dhd.html" dennoch in die RewriteRule fällt, obwohl sie existiert.

            Weil du nicht %{REQUEST_FILENAME} sondern %{REQUEST_URI} untersuchst. Teste mal nacheinander

            RewriteCond %{REQUEST_URI} (.*)
            RewriteRule ^([-\w]+).html$ test.php?x=%1 [QSA]

            RewriteCond %{REQUEST_FILENAME} (.*)
            RewriteRule ^([-\w]+).html$ test.php?x=%1 [QSA]

            Und in der test.php ein <pre><?php print_r($_GET);

            %{REQUEST_URI} ergibt keinen im System vorhandenen Dateinamen.

            dedlfix.

            1. Ola dedlfix,

              Weil du nicht %{REQUEST_FILENAME} sondern %{REQUEST_URI} untersuchst. Teste mal nacheinander

              Das wars. Wenn ich dir sowas wie einen goldenen Apfel als Aufkleber schenken könnte, würde ich es hier jetzt tun. Aber ich hoffe du nimmst stattdessen meinen herzlichsten Dank entgegen. Vielen, vielen Dank! :-)