Mastershrimp: .htaccess: Eigenes 404-Doc nur für nicht-Bilddatei-Anfragen

Moin,

ich arbeite gerade an der 404-Fehler-Verarbeitung meines CMS. Das System generiert für 404-Fehler eine eigene Seite - aus Speed-Gründen soll es das aber nur für "sichtbare" Anfragen machen, sprich, wenn die Anfrage nach Bildern und ähnlichen Objekten fehlschlägt, soll die Seite nicht gesendet werden sondern einfach die Standard-Apache-404-Seite.

Da ich mod_rewrite verwende und das scheinbar vor den ErrorDocument-Direktiven ausgeführt wird, muss ich das ganze auf RewriteCond-Ebene lösen. Hier mein Ansatz:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !.(gif|jpe?g|png|ico|bmp|js|swf)$ [nocase]
RewriteRule ^(.*)$ index.php5?page=$1&%{QUERY_STRING}

Was die RewriteCond's tun sollen:
1. "Sende die Datei falls die Anfrage einer real auf dem Server existierenden Datei galt" (kein Umweg über index.php5 also)
2. Gleiches Spiel mit real existierenden Ordnern
3. Wende die RewriteRule an sofern die Anfrage nicht auf ".gif", ".jpeg", ".png", ... endet. Ist dies der Fall, wertet diese RewriteCond zu "false" aus und die RewriteRule wird nicht angewendet. An diesem Punkt ist auch bereits klar, dass die Bild-Datei nicht existiert (sonst hätte Cond#1 gegriffen)

Das ganze funktioniert auch für Anfragen von Dateien ausm Wurzelverzeichnis (meinedomain.de/gibtsnicht.jpg). Sobald die angefragte Datei in nem Unterordner liegt, klappts nicht mehr (meinedomain.de/ordner/gibtsnicht.jpg). Da kommt dann wieder die 404-Seite meines CMS, die Cond#3 greift also irgendwie nicht.

Habs auch schon mit
RewriteCond %{REQUEST_FILENAME} !^.+.(gif|jpe?g|png|ico|bmp|js|swf)$ [nocase]
versucht, aber ohne Erfolg.

Wo ist mein Fehler? Das Problem tritt sowohl auf meinem Produktiv-System-Server als auch lokal auf.

Vielen Dank schonmal und viele Grüße

Mastershrimp

  1. Hi,

    Wo ist mein Fehler? Das Problem tritt sowohl auf meinem Produktiv-System-Server als auch lokal auf.

    Lokal hast du die Möglichkeit, das Rewrite-Log zu nutzen - also mach das bitte.

    MfG ChrisB

    --
    The most exciting phrase to hear in science, the one that heralds new discoveries, is not “Eureka!” but “That's funny...” [Isaac Asimov]
    1. Heyho!

      Danke für den Hinweis. Das kannte ich noch nicht.
      Ich habs jetzt hinbekommen indem ich %{REQUEST_URI} für die letzte Rewriteond nehme.

      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteCond %{REQUEST_URI} !.(gif|jpe?g|png|ico|bmp|js|swf)$ [NC]
      RewriteRule ^(.*)$ index.php5?page=$1 [L]

      Dennoch habe ich eine Verständnisfrage:
      In obigem Beispiel (meinedomain.de/ordner/bild.jpg), in dem es weder den Ordner "ordner" noch das Bild "bild.jpg" gibt, sieht das RewriteLog wie folgt aus:

      ---
      add path info postfix: D:/Pfad/zu/meinem/System/ordner -> D:/Pfad/zu/meinem/System/ordner/bild.jpg
      strip per-dir prefix: D:/Pfad/zu/meinem/System/ordner/bild.jpg -> ordner/bild.jpg
      applying pattern '^(.*)$' to uri 'ordner/bild.jpg'
      RewriteCond: input='D:/Pfad/zu/meinem/System/ordner' pattern='!-f' => matched
      RewriteCond: input='D:/Pfad/zu/meinem/System/ordner' pattern='!-d' => matched
      RewriteCond: input='/mec-cms/ordner/bild.jpg' pattern='!.(gif|jpe?g|png|ico|bmp|js|swf)$' [NC] => not-matched
      add path info postfix: D:/Pfad/zu/meinem/System/ordner -> D:/Pfad/zu/meinem/System/ordner/bild.jpg
      strip per-dir prefix: D:/Pfad/zu/meinem/System/ordner/bild.jpg -> ordner/bild.jpg
      applying pattern '^$' to uri 'ordner/bild.jpg'
      pass through D:/Pfad/zu/meinem/System/ordner
      ---

      Ich finde den Teil, in dem er "-f" und "-d" auswertet, merkwürdig. Warum nimmt er da nur alles bis /ordner und schneidet das "bild.jpg" ab? Das war ja letztendlich auch mein Denkfehler - nur seh ich immer noch nicht ein warum?

      Wenn "ordner" existieren würde, würde er den kompletten Pfad als input nehmen:

      ---
      strip per-dir prefix: D:/Pfad/zu/meinem/System/ordner/bild.jpg -> ordner/bild.jpg
      applying pattern '^(.*)$' to uri 'ordner/bild.jpg'
      RewriteCond: input='D:/Pfad/zu/meinem/System/ordner/bild.jpg' pattern='!-f' => matched
      RewriteCond: input='D:/Pfad/zu/meinem/System/ordner/bild.jpg' pattern='!-d' => matched
      RewriteCond: input='/mec-cms/ordner/bild.jpg' pattern='!.(gif|jpe?g|png|ico|bmp|js|swf)$' [NC] => not-matched
      strip per-dir prefix: D:/Pfad/zu/meinem/System/ordner/bild.jpg -> ordner/bild.jpg
      applying pattern '^$' to uri 'ordner/bild.jpg'
      pass through D:/Pfad/zu/meinem/System/ordner/bild.jpg
      ---

      {REQUEST_FILENAME} scheint nur alles bis zum ersten nicht auffindbaren Objekt zu enthalten, stimmt das? Find ich ne merkwürdige Implementierung und wird auch mit keiner Silbe in den Apache Docs erwähnt...("The *full* local filesystem path to the file or script matching the request, if this has already been determined by the server at the time REQUEST_FILENAME is referenced. Otherwise, such as when used in virtual host context, the same value as REQUEST_URI.")
      Ok, ich habe den Verdacht dass der letzte Satz mir den Denkfehler beschert hat. Vermutlich kann der Server REQUEST_FILENAME nicht komplett determinen sondern scheitert halt am ersten nicht auffindbaren Objekt.

      Hmmm...stimmt das so? Hab ungern so Blackbox-Lösungen wo ich zwar weiß dass es klappt - aber nicht warum ;-)

      Viele Grüße

      Mastershrimp

      1. Hi,

        Ich finde den Teil, in dem er "-f" und "-d" auswertet, merkwürdig. Warum nimmt er da nur alles bis /ordner und schneidet das "bild.jpg" ab?
        [...]
        Wenn "ordner" existieren würde, würde er den kompletten Pfad als input nehmen

        Das mag der Performance-Steigerung dienen; wenn schon das Filesystem befragt wurde und gesagt hat, dass /order nicht existiert - dann wird /ordner/bild.jpg ganz sicher auch nicht existieren, also braucht man da auch nicht mehr nach fragen.

        MfG ChrisB

        --
        The most exciting phrase to hear in science, the one that heralds new discoveries, is not “Eureka!” but “That's funny...” [Isaac Asimov]
        1. Das mag der Performance-Steigerung dienen; wenn schon das Filesystem befragt wurde und gesagt hat, dass /order nicht existiert - dann wird /ordner/bild.jpg ganz sicher auch nicht existieren, also braucht man da auch nicht mehr nach fragen.

          Mhja, das macht Sinn. Nur war in meinem Fall etwas verwirrend ;-)
          Danke nochmal für den Tipp mit dem Logging - sehr praktisch

          Viele Grüße

          Mastershrimp