Tim: mod_rewrite -> Fehlerhafte RewriteRule?

Hallo Forum!

Ich habe ein kleines Problem mit mod_rewrite für den Apache2. Unter Umständen bin ich auch inzwischen einfach  nur betriebsblind :)

Ich möchte, wenn eine URL

www.domain.de/index.html

aufgerufen wird, dass diese auf

www.domain.de/page.php?k=index.html

umgeleitet wird. Das klappt auch. Jetzt möchte ich aber zusätzlich, dass, wenn eingegeben wird:

www.domain.de/edit/index.html

dass diese auf www.domain.de/page_edit.php?k=index.html umgeleitet wird. So weit so gut, aber meine Konfiguration erfüllt diesen Zweck nicht.

Auszug aus der config:

RewriteCond %{REQUEST_URI} ^/[a-zA-Z0-9]*.html
RewriteRule (.+?.html)$ /page.php?k=$1

RewriteCond %{REQUEST_URI} edit/[a-zA-Z0-9]*.html
RewriteRule edit/(.+?.html)$ /page_edit.php?k=$1

Das alles steht in einer .htaccess im benötigten Verzeichnis im IfModule-Abschnitt. AllowOverride All ist für dieses Verzeichnis auch an.

Hoffe, mir kann jemand helfen!

Einen schönen Abend!
Tim

  1. Hellihello

    Auszug aus der config:

    RewriteCond %{REQUEST_URI} ^/[a-zA-Z0-9]*.html
    RewriteRule (.+?.html)$ /page.php?k=$1

    aus /edit/irgendwas.html wird hier gerade /page.php?k=/edit/irgendwas.html, oder?

    RewriteCond %{REQUEST_URI} edit/[a-zA-Z0-9]*.html
    RewriteRule edit/(.+?.html)$ /page_edit.php?k=$1

    Kann das überhaupt noch passieren? [L] könnte helfen und umdrehen. Zudem muss es nicht
    ^/edit/... heißen?

    Hoffe, mir kann jemand helfen!

    Probier doch erstmal _nur_ das mit dem edit und lass zum testen das andere weg. Und packs doch in die .htaccess zum Testen.

    Dank und Gruß,

    frankx

    --
    tryin to multitain  - Globus = Planet != Welt
    1. Hallo frankx!

      Eine kurze Anmerkung, wenn ich darf...

      Die regulären Audrücke in der Apache-Implementation sind zum einen lange nicht so mächtig wie in Perl, zum zweiten benötigen sie keine Delimiter, weswegen der "/" (Slash) nicht maskiert werden muss.

      Du kannst also schreiben:

      RewriteRule ^edit/foo/bar/(.*) http://example.org/$1.php

      Es gibt anscheinend auch Unterschiede zw. RewriteRule und RedirectMatch Permanent, der meines Erachtens noch den Slash braucht. Beispiele aus meiner .htacess:

      RedirectMatch permanent ^/forum(.*) http://old.atomic-eggs.com/old_forum$1

      aber:

      RewriteEngine on
      RewriteCond %{HTTP_REFERER} ^http.*buch.*eintrag.*$  [NC]
      RewriteRule ^(.*)ugb|wae_8.*$ http://www.atomic-eggs.com/z_testdir/ttt_7.shtml

      (letztere ist übrigens die Regel, die ich in dem Gästebuch-Spam-Thread erwähnt habe: https://forum.selfhtml.org/?t=183681&m=1217065)

      Genaueres werden uns die Server-Experten™ sagen, denn aus den Apache-Docs werde ich auch nicht schlauer.

      Viele Grüße aus Frankfurt/Main,
      Patrick

      --
      _ - jenseits vom delirium - _

         Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
      J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
      1. Die regulären Audrücke in der Apache-Implementation sind zum einen lange nicht so mächtig wie in Perl,

        Ist der Unterschied zw. PCRE und der built-in Implementierung in Perl so groß? (Gilt natürlich nicht für Apache 1.3, der die POSIX extended regEx library verwendet).

        Es gibt anscheinend auch Unterschiede zw. RewriteRule und RedirectMatch Permanent, der meines Erachtens noch den Slash braucht.

        Das kommt drauf an.  :-) mod_alias prüft immer gegen den URI-path (r->uri), der natürlich immer mit einem führenden Slash beginnt. Das macht mod_rewrite im Serverkontext auch, im Verzeichniskontext (u.a. .htaccess-Dateien) aber nicht. Dort prüfst du gegen einen lokalen physischen Pfad. D.h. von /var/www/foo wird bei einer Notation in /var/www/.htaccess das Verzeichnisprefix /var/www/ entfernt, sodass der reguläre Ausdruck auf letztendlich auf "foo" geprüft wird.

        Das meiste Durcheinander entsteht eigentlich durch das unterschiedliche Verhalten je nach Kontext verbunden mit dem Nichtfunktionieren bestimmter Beispiele je nach Kontext. Mit zwei unterschiedlichen Direktiven wäre man wohl besser gefahren...

        Du kannst also schreiben:

        RewriteRule ^edit/foo/bar/(.*) http://example.org/$1.php

        Das kann der OP schreiben, aber oberhalb seiner anderen Regel. Vom Speziellen zum Generellen. Die Conditions werden nach der RegEx der RewriteRule geprüft, sodass diese eigentlich hier entfallen können.

        RewriteRule ^edit/([a-zA-Z0-9]+.html)$ /page_edit.php?k=$1 [L]
        RewriteRule ^([a-zA-Z0-9]+.html)$ /page.php?k=$1 [L]

        1. Hallo Bob!

          Ist der Unterschied zw. PCRE und der built-in Implementierung in Perl so groß? (Gilt natürlich nicht für Apache 1.3, der die POSIX extended regEx library verwendet).

          Kann ich nicht genau sagen, ich bin da auch kein Experte. Zumindest Look arounds scheinen nicht implementiert zu sein.

          Danke für die ergänzenden Erläuterungen!

          Viele Grüße aus Frankfurt/Main,
          Patrick

          --
          _ - jenseits vom delirium - _

             Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
          J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
          1. Hallo Patrick.

            »» Ist der Unterschied zw. PCRE und der built-in Implementierung in Perl so groß? (Gilt natürlich nicht für Apache 1.3, der die POSIX extended regEx library verwendet).

            Kann ich nicht genau sagen, ich bin da auch kein Experte. Zumindest Look arounds scheinen nicht implementiert zu sein.

            Apache 2.2 nutzt die PCRE-Version 5.0 13-Sep-04, da müsste dann alles inkl. lookarounds laufen. Letzteres ist natürlich nur bei RedirectMatch/FilesMatch/LocationMatch etc. interessant, da im Fall des Einsatzes von mod_rewrite Teilzeichenketten ja über Conditions geprüft werden können.

            Apache 2.3+ wird die PCRE nicht mehr mitliefern und statisch linken, der Anwender darf sich die Abhängigkeit dann selbst laden.

            Grüße
            Bob

            1. Hallo Bob!

              Apache 2.3+ wird die PCRE nicht mehr mitliefern und statisch linken, der Anwender darf sich die Abhängigkeit dann selbst laden.

              Was bedeutet das krass™ konkret™?

              Viele Grüße aus Frankfurt/Main,
              Patrick

              --
              _ - jenseits vom delirium - _

                 Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
              J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
              1. Hallo Patrick.

                »» Apache 2.3+ wird die PCRE nicht mehr mitliefern und statisch linken, der Anwender darf sich die Abhängigkeit dann selbst laden.

                Was bedeutet das krass™ konkret™?

                Wenn du derzeit den Apache über configure/make etc. baust, wird eine in der Quellcode-Distribution mitgelieferte Perl Compatible Regular Expressions-Bibliothek automatisch mitkompiliert und statisch gelinkt. D.h. der Apache greift dann beim Funktionsaufruf nicht auf irgendwelche bereits im System vorhandene Bibliotheken (DLL) oder shared objects wie sie ja in der Unix-Welt genant werden, zurück, sondern ausschließlich auf die einkompilierte Bibliothek.

                In Zukunft muss diese Abhängigkeit dann (sollte sie nicht ohnehin bereits auf dem System vorhanden sein) von z.B. ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ geladen werden. Findet der Apache das pcre-config-Script nicht, lässt er sich nicht bauen.

                Damit darf sich dann der Systemadministrator selbständig um (Sicherheits-)updates bei PCRE kümmern.

                Unter Apache 2.2 kannst du auch eine externe PCRE-Bibliothek über ./configure --with-pcre=... angeben, die dann der Mitgelieferten vorgezogen wird.

                1. Hallo Bob!

                  Danke für die Erläuterungen!

                  Damit darf sich dann der Systemadministrator selbständig um (Sicherheits-)updates bei PCRE kümmern.

                  Sind Probleme bei Webhostern dann vorprogrammiert?

                  Viele Grüße aus Frankfurt/Main,
                  Patrick

                  --
                  _ - jenseits vom delirium - _

                     Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
                  J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
                  1. Hallo Patrick.

                    »» Damit darf sich dann der Systemadministrator selbständig um (Sicherheits-)updates bei PCRE kümmern.

                    Sind Probleme bei Webhostern dann vorprogrammiert?

                    Da würde ich mir keine Sorgen machen. Die Hoster, die ihre Systeme zumindest im Hinblick auf zu stopfende Sicherheitslücken in Software-Produkten aktuell halten (patchen), werden das auch weiterhin inkl. PCRE machen. Diejenigen, die eine Kiste nach dem Motto „Hauptsache sie läuft“ ins Netz stellen und sich dann um nichts mehr kümmern, da macht das dann auch nichts mehr aus... :-)

        2. Hellihello

          Das kann der OP schreiben, aber oberhalb seiner anderen Regel. Vom Speziellen zum Generellen. Die Conditions werden nach der RegEx der RewriteRule geprüft, sodass diese eigentlich hier entfallen können.

          RewriteRule ^edit/([a-zA-Z0-9]+.html)$ /page_edit.php?k=$1 [L]
          RewriteRule ^([a-zA-Z0-9]+.html)$ /page.php?k=$1 [L]

          Wobei es

          RewriteRule ^edit/(.*) page_edit.php?k=$1 [L]
          RewriteRule (.*) page.php?k=$1 [L]

          ja auch tun dürfte, oder? Es sei denn, er will explizit Underlines und Viertelgeviertstriche verbieten und die Datei _muss_ mit .html enden.

          Dank und Gruß,

          frankx

          --
          tryin to multitain  - Globus = Planet != Welt
          1. »» RewriteRule ^edit/([a-zA-Z0-9]+.html)$ /page_edit.php?k=$1 [L]
            »» RewriteRule ^([a-zA-Z0-9]+.html)$ /page.php?k=$1 [L]

            Wobei es

            RewriteRule ^edit/(.*) page_edit.php?k=$1 [L]
            RewriteRule (.*) page.php?k=$1 [L]

            ja auch tun dürfte, oder?

            Nicht direkt, mit der letzten Regel wirst du bedingt durch den internen redirect immer page.php?k=page.php im Verzeichniskontext erhalten.

            Es sei denn, er will explizit Underlines und Viertelgeviertstriche verbieten und die Datei _muss_ mit .html enden.

            Und natürlich alle anderen „eingeschleusten“ Zeichen wie &= etc oder andere Ressourcen wie foo.jpg oder other.php. Was an die PHP-Dateien weitergereicht werden soll, weiß natürlich nur der OP, oben schränkt er es zumindest ein. :-)

            1. Hellihello

              »» RewriteRule ^edit/(.*) page_edit.php?k=$1 [L]
              »» RewriteRule (.*) page.php?k=$1 [L]
              »»
              »» ja auch tun dürfte, oder?

              Nicht direkt, mit der letzten Regel wirst du bedingt durch den internen redirect immer page.php?k=page.php im Verzeichniskontext erhalten.

              Trotz des [L] am Ende? Wäre dann also "nicht am Anfang page.php" zu wählen
              ^!page.php(.*) ...???

              Dank und Gruß,

              frankx

              --
              tryin to multitain  - Globus = Planet != Welt
              1. »» »» RewriteRule ^edit/(.*) page_edit.php?k=$1 [L]
                »» »» RewriteRule (.*) page.php?k=$1 [L]
                »» »»
                »» »» ja auch tun dürfte, oder?
                »»
                »» Nicht direkt, mit der letzten Regel wirst du bedingt durch den internen redirect immer page.php?k=page.php im Verzeichniskontext erhalten.

                Trotz des [L] am Ende?

                Ja, das hat nur im aktuellen Durchlauf eine Funktion. Im content handler von mod_rewrite wird mit dem URL-path /page.php?k=foo.html ein interner redirect durchgeführt. Der hat ein erneutes Durchlaufen des Requestprocessings zur Folge, also Abbilden auf das Dateisystem, Directory-, Files-, Location-Walk, access,- und auth checks, fixup-hooks,...... All das wird erneut durchlaufen. Das ist praktisch fast wie eine neue Anfrage. Da die notierte Regel erneut erreicht wird, wird sie auch durchlaufen und ausgeführt.

                Wäre dann also "nicht am Anfang page.php" zu wählen
                ^!page.php(.*) ...???

                Du brauchst einen negativen Lookahead, also

                ^(?!page.php)(.*)

                oder eben über die mod_rewrite-Syntax das Ergebnis der RegEx umdrehen
                RewriteRule !^page.php$ foo?args=%{REQUEST_URI}

                Viele Anwender, das sollte auch das Forumsarchiv zeigen, werden mit der alles konsumierenden RegEx .* aber nicht glücklich und produzieren bedingt durch den internal redirect Endlosschleifen oder "das Statistik-Verzeichnis ist nicht mehr aufrufbar" und solche Sachen...

                1. Hellihello

                  »»  Wäre dann also "nicht am Anfang page.php" zu wählen
                  »» ^!page.php(.*) ...???

                  Du brauchst einen negativen Lookahead, also

                  ^(?!page.php)(.*)

                  ^
                       ^
                  wieso das Fragezeichen?

                  oder eben über die mod_rewrite-Syntax das Ergebnis der RegEx umdrehen
                  RewriteRule !^page.php$ foo?args=%{REQUEST_URI}

                  = "nicht - zwischen Anfang und Ende - "page.php" und %{REQUEST_URI} gibt den kompletten Pfad nach dem Domainnamen incl. Slash am Anfang?

                  Dank und Gruß,

                  frankx

                  --
                  tryin to multitain  - Globus = Planet != Welt
                  1. Hallo frankx!

                    »» Du brauchst einen negativen Lookahead, also
                    »»
                    »» ^(?!page.php)(.*)
                         ^
                         ^
                    wieso das Fragezeichen?

                    Da möchte sich jemand mit Look araound assertions
                    beschäftigen ;)

                    Viele Grüße aus Frankfurt/Main,
                    Patrick

                    --
                    _ - jenseits vom delirium - _

                       Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
                    J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
                    1. Hellihello

                      Da möchte sich jemand mit Look araound assertions beschäftigen ;)

                      Dank und Gruß,

                      frankx

                      --
                      tryin to multitain  - Globus = Planet != Welt
                    2. Hellihello

                      Da möchte sich jemand mit Look araound assertions

                      beschäftigen ;)

                      eine negative-look-ahjead assertion: "Ausdruck darf nicht auf vorgenannten Ausdruck folgen"

                      ^(?!page.php)(.*)

                      Am Anfang - nicht gefolgt von page.php gefolgt von irgendwas. Durch das Fragezeichen bedeutet die Klammer zudem, dass der Wert nicht in $1 auftaucht?

                      Und: "^" ist bereits ein ein "Ausdruck".

                      Dank und Gruß,

                      frankx

                      --
                      tryin to multitain  - Globus = Planet != Welt
                      1. Hallo frankx!

                        ^(?!page.php)(.*)
                        Durch das Fragezeichen bedeutet die Klammer zudem, dass der Wert nicht in $1 auftaucht?

                        Genau. Da wird nur gruppiert und nicht gemerkt.

                        Und: "^" ist bereits ein ein "Ausdruck".

                        Ja.

                        P.S.: Mein fehlerhafter Link entstand im Safari. Der hat ein so sonderbares Verrhalten in Textareas... Z.B. wenn ich mehrere Zeilen Text löschen will, beginnend von oben oder von unten (Shift-Taste gedrückt und mit Pfeiltasten die Zeilen markieren), passiert es oft, dass er irgendwo im Text aufhört zu markieren. Meistens Zeile, die ein Bindestrich enthalten...

                        Oder: Ich setze den Cursor hinter einem Buchstaben, ziehe die Maus nach Links, da wird der Buchstabe nicht immer mitmarkiert. Ich muss den Cursor wirklich mitten auf dem nächsten Buchstaben positionieren, damit der vorige »mitgenommen« wird...

                        Naja, jedenfalls waren da Leerzeichen in meinem Link, weswegen dieser nicht gefunzt™ hat.

                        Viele Grüße aus Frankfurt/Main,
                        Patrick

                        --
                        _ - jenseits vom delirium - _

                           Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
                        J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?