suit: mod_rewrite, Backreference auf RewriteCond

Funktioniert:
RewriteCond %{REQUEST_URI} /willkommen.php
RewriteCond %{HTTP_HOST} (www.example.(?:org|net|com))
RewriteRule .* http://%1/de/willkommen? [R=301,L]

RewriteCond %{REQUEST_URI} /presse.php
RewriteCond %{HTTP_HOST} (www.example.(?:org|net|com))
RewriteRule .* http://%1/de/presse? [R=301,L]

Funktioniert nicht:
RewriteCond %{REQUEST_URI} /(willkommen|presse).php
RewriteCond %{HTTP_HOST} (www.example.(?:org|net|com))
RewriteRule .* http://%2/de/%1? [R=301,L]

Laut Dokumentation ist das nicht möglich, da die die Backreference (%) nur auf das jeweilig letzte RewriteCond angewendet werden kann.

"RewriteCond backreferences: These are backreferences of the form %N (1 <= N <= 9), which provide access to the grouped parts (again, in parentheses) of the pattern, from the last matched RewriteCond in the current set of conditions."

Kann ich das umgehen? btw: mir ist klar, dass das obenstehende Beispiel schlecht gewählt ist, da ich den Pfad einfach in der RewriteRule prüfen könnte.

Wie kann ich das Problem lösen, ohne dass ich jetzt die RewriteCond/Rule-Abschnitte vervielfache?

  1. Funktioniert nicht:
    RewriteCond %{REQUEST_URI} /(willkommen|presse).php
    RewriteCond %{HTTP_HOST} (www.example.(?:org|net|com))
    RewriteRule .* http://%2/de/%1? [R=301,L]

    Kann ich das umgehen? btw: mir ist klar, dass das obenstehende Beispiel schlecht gewählt ist, da ich den Pfad einfach in der RewriteRule prüfen könnte.

    Ja, mir ist auch klar, dass das gewählte beispiel extrem schlecht gewählt ist - ich könnte natürlich einfach %{HTTP_HOST} in der RewriteRule notieren :)

    In meinem Fall brauche ich aber nur Teile aus HTTP_HOST und HTTP_REFERER[sic!] - die Holzhammermethode ist immer noch auf ein PHP-Script umschreiben, welches dann die Auswertung vornimmt und umleitet, aber schön wäre eine mod_rewrite-Lösung.

    Alternativ ist natürlich auch Denkbar, dass ich das Umschreiben in zwei Schritten mache und das L-Flag weglasse, das ist aber im Prinzip dann auch wieder das "zerstückeln", was ich eigentlich nicht möchte.

    1. Hi!

      Funktioniert nicht:
      RewriteCond %{REQUEST_URI} /(willkommen|presse).php
      RewriteCond %{HTTP_HOST} (www.example.(?:org|net|com))
      RewriteRule .* http://%2/de/%1? [R=301,L]
      Laut Dokumentation ist das nicht möglich, da die die Backreference (%) nur auf das jeweilig letzte RewriteCond angewendet werden kann.
      "RewriteCond backreferences: These are backreferences of the form %N (1 <= N <= 9), which provide access to the grouped parts (again, in parentheses) of the pattern, from the last matched RewriteCond in the current set of conditions."

      Du hast das Wörtchen "matched" überlesen. Und beide RewriteConds haben bei dir nur ein Element, also ist %2 ungültig und nur %1 vorhanden.

      Ja, mir ist auch klar, dass das gewählte beispiel extrem schlecht gewählt ist - ich könnte natürlich einfach %{HTTP_HOST} in der RewriteRule notieren :)

      Wirklich?

      Lo!

      1. Du hast das Wörtchen "matched" überlesen. Und beide RewriteConds haben bei dir nur ein Element, also ist %2 ungültig und nur %1 vorhanden.

        Ich steh' am Schlauch.

        Wenn ich im oberen Beispiel http://www.example.com/willkommen.php aufrufen, sollte doch die erste RewriteCond zu einem Match führen, nämlich "willkommen" und die zweite RewirteCond zu einem Match auf "www.example.com"

        Ja, mir ist auch klar, dass das gewählte beispiel extrem schlecht gewählt ist - ich könnte natürlich einfach %{HTTP_HOST} in der RewriteRule notieren :)

        Wirklich?

        Folgendes sollte doch kein Problem sein, oder?
        RewriteRule foo http://%{HTTP_HOST}/bar/? [R=301,L]

        1. Hi!

          Du hast das Wörtchen "matched" überlesen. Und beide RewriteConds haben bei dir nur ein Element, also ist %2 ungültig und nur %1 vorhanden.
          Ich steh' am Schlauch.
          Wenn ich im oberen Beispiel http://www.example.com/willkommen.php aufrufen, sollte doch die erste RewriteCond zu einem Match führen, nämlich "willkommen" und die zweite RewirteCond zu einem Match auf "www.example.com"

          Es müssen alle passen, denn AND ist das Default-Verhalten. Dann kann "the last matched RewriteCond in the current set of conditions" im Prinzip nur die letzte Regel vor der RewriteRule sein. Es sei denn, du hast sie mit OR verknüpft, dann könnte man mit dem Kurzschlussverfahren bereits nach der ersten zutreffenden Cond abbrechen, welche dann "the last matched ..." wäre. Aber dazu finde ich nicht genug Erklärungen in der Dokumentation.

          Ein Beispiel zeigt die mehrfache Verwendung der back references. Da bezieht sich das %1 der jeweils letzten RewriteCond auf den geklammerten Wert ihres Vorgängers und das %1 in der RewriteRule auf die letzte RewriteCond. Das zeigt, dass zumindest beim Default-AND sich die Referenz auf die jeweils davor stehende Cond bezieht.

          Folgendes sollte doch kein Problem sein, oder?
          RewriteRule foo http://%{HTTP_HOST}/bar/? [R=301,L]

          Ach, da "hinten". Im Muster der URL können diese Variablen natürlich nicht verwendet werden, aber im Ersetzungsteil soll das doch gehen. Wieder was gelernt.

          Lo!

          1. Es müssen alle passen, denn AND ist das Default-Verhalten.

            Davon gehe ich aus, ja.

            Dann kann "the last matched RewriteCond in the current set of conditions" im Prinzip nur die letzte Regel vor der RewriteRule sein. Es sei denn, du hast sie mit OR verknüpft, dann könnte man mit dem Kurzschlussverfahren bereits nach der ersten zutreffenden Cond abbrechen, welche dann "the last matched ..." wäre. Aber dazu finde ich nicht genug Erklärungen in der Dokumentation.

            Das könnte natürlich sein - aber ich gehe davon aus, dass ich explizit UND verwende, weil ich ja nichts angebe.

            Ein Beispiel zeigt die mehrfache Verwendung der back references. Da bezieht sich das %1 der jeweils letzten RewriteCond auf den geklammerten Wert ihres Vorgängers und das %1 in der RewriteRule auf die letzte RewriteCond. Das zeigt, dass zumindest beim Default-AND sich die Referenz auf die jeweils davor stehende Cond bezieht.

            Unterm Stich bestätigt das meine Erkenntnis, dass sich - im Fall von AND - die Backreference nur auf die letzte RewriteCond-Zeile anwenden lässt.

            Wird wohl ein PHP-Script herhalten müssen.