tkoch: .htaccess Problem

Hallo,

ich habe eine Webseite welche mit meiner .htaccess Probleme hat. Code:

Options +Includes AddHandler server-parsed .shtml .html .htm AddType text/html .html AddType text/html .shtml AddHandler server-parsed .shtml AddHandler server-parsed .html AddType application/x-httpd-cgi .cgi Options Indexes FollowSymLinks Includes RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)$ index.php?site=$1 [QSA,L] # Dauerhafte Umleitung von HTTP auf HTTPS RewriteCond %{SERVER_PORT} !^443$ RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L] # Einzelnen Seiten umgeleiten RewriteRule ^Lindau-am-Bodensee$ /orte/lindau.php [R=301,L] RewriteRule ^lindau$ /orte/lindau.php [R=301,L]

Nun ist es so das die Seite "Lindau-am-Bodensee" nicht auf /orte/lindau.php umleitet. Wenn ich nun "/orte" und "RewriteRule ^(.+)$ index.php?site=$1 [QSA,L]" lösche funktioniert es aber einige anderen Seiten funktionieren durch das fehlende "RewriteRule ^(.+)$ index.php?site=$1 [QSA,L]" nicht mehr. Ich hoffe es kann mir jemand helfen.

Vielen Dank

  1. RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)$ index.php?site=$1 [QSA,L] # Einzelnen Seiten umgeleiten RewriteRule ^Lindau-am-Bodensee$ /orte/lindau.php [R=301,L] RewriteRule ^lindau$ /orte/lindau.php [R=301,L]

    Nun ist es so das die Seite "Lindau-am-Bodensee" nicht auf /orte/lindau.php umleitet.

    Die Reihenfolge der Regeln spielt eine Rolle („The order in which these rules are defined is important - this is the order in which they will be applied at run-time.“), die URI "Lindau-am-Bodensee" erfüllt bereits die erste RewriteRule, weil jede URI diese erfüllt und die zusätzlichen RewriteCond dafür vermutlich auch, d.h. es gibt keine Datei oder Ordner diesen Namens. Also wird dort die URI auf "index.php?site=Lindau-am-Bodensee" umgeschrieben und da das L-Flag gesetzt ist, werden keine weiteren RewriteRule berücksichtigt (das würde auch nichts ändern, da diese ja nicht mehr matchen würden).

    1. Tach!

      Die Reihenfolge der Regeln spielt eine Rolle („The order in which these rules are defined is important - this is the order in which they will be applied at run-time.“), die URI "Lindau-am-Bodensee" erfüllt bereits die erste RewriteRule, weil jede URI diese erfüllt und die zusätzlichen RewriteCond dafür vermutlich auch, d.h. es gibt keine Datei oder Ordner diesen Namens.

      Wenn jede URL sie erfüllte, gäbe es eine Endlosschleife.

      Also wird dort die URI auf "index.php?site=Lindau-am-Bodensee" umgeschrieben und da das L-Flag gesetzt ist, werden keine weiteren RewriteRule berücksichtigt (das würde auch nichts ändern, da diese ja nicht mehr matchen würden).

      Das L-Flag gilt nur für diesen Durchlauf. Nach Ende eines Rewrite-Prozess, der nicht auf einen Redirect hinauslief - den ja der Browser ausführt, und somit als ganz neuer Request wieder reinkommt, so er nicht sonstwohin geschickt wird - wird mit der umgeschriebenen URL erneut die interne Abarbeitung gestartet, da sie ja nun ein anderes Ziel ist und auch auf andere Orte zeigen könnte.

      Jedenfalls kommt der Request wieder oben an und stellt nun fest, dass die index.php (hoffentlich) existiert. Die erste Regel wird damit übergangen. Die Weiterleitung auf HTTPS könnte notwendig sein. Dann kommt der Request vom Browser gestellt erneut rein, die erste Regel trifft nicht zu, die zweite auch nicht, und die dritte und vierte ebenfalls nicht, weil index.php nicht dazu passt. Wenn HTTPS on war - oder genauer, wenn der Request auf dem Port 443 reinkommt, was nicht zwangsläufig bedeutet, dass er auch HTTPS ist - dann treffen die Regeln ebenfalls nicht zu.

      Abgesehen von dieser Ergänzung bleibt die Lösung, dass die Reihenfolge beachtet werden muss.

      dedlfix.

      1. Tach!

        Die Reihenfolge der Regeln spielt eine Rolle („The order in which these rules are defined is important - this is the order in which they will be applied at run-time.“), die URI "Lindau-am-Bodensee" erfüllt bereits die erste RewriteRule, weil jede URI diese erfüllt und die zusätzlichen RewriteCond dafür vermutlich auch, d.h. es gibt keine Datei oder Ordner diesen Namens.

        Wenn jede URL sie erfüllte,

        Ich wüsste keine URI, die "^(.+)$" nicht erfüllen würde, beliebig viele beliebige Zeichen.

        gäbe es eine Endlosschleife.

        Die wird durch die RewriteConds (hoffentlich) verhindert, wie du schriebst; aber vermutlich habe ich mich nur uneindeutig ausgedrückt.

        1. Tach!

          Wenn jede URL sie erfüllte,

          Ich wüsste keine URI, die "^(.+)$" nicht erfüllen würde, beliebig viele beliebige Zeichen.

          gäbe es eine Endlosschleife.

          Die wird durch die RewriteConds (hoffentlich) verhindert, wie du schriebst; aber vermutlich habe ich mich nur uneindeutig ausgedrückt.

          Das denke ich auch, dass es nur ein sprachliches Missverständnis war. Das klang für mich so, als ob sowohl die Rule als auch die Conds in jedem Fall passen.

          Wichtiger war mir, hinzuzufügen dass das Rewriting nicht generell bei einem L-Flag aufhört, sondern dass durch den umgeschriebenen Request die Maschinerie von vorn anfängt. Deswegen hat sich auch die Einschränkung auf nicht existierende Dateien und Verzeichnisse eingebürgert, damit an der Stelle das Rewriting wirklich aufhört und der Request ohne Umschreiben durchläuft.

          dedlfix.

        2. Hi,

          Ich wüsste keine URI, die "^(.+)$" nicht erfüllen würde, beliebig viele beliebige Zeichen.

          Nein, nicht beliebig viele, ist ja .+, nicht .* - also mindestens 1 Zeichen.

          Gematcht wird der Teil nach hostname+port, und vor dem Querystring.

          Bei http://example.org/bla?blubb also das /bla.

          Ob bei http://example.org der / automatisch ergänzt wird, weiß ich nicht - wenn nicht, wäre eine Url wie http://example.org eine, die nicht gematcht würde von ^(.+)$.

          cu,
          Andreas a/k/a MudGuard

          1. Tach!

            Ob bei http://example.org der / automatisch ergänzt wird, weiß ich nicht - wenn nicht, wäre eine Url wie http://example.org eine, die nicht gematcht würde von ^(.+)$.

            Es kann keinen leeren Request ohne / geben. Den muss der Browser ergänzen, denn er kann nicht

            GET HTTP/1.1

            statt

            GET / HTTP/1.1

            senden. Das wäre ein ungültiger Request, der auch gar nicht bis zum VHost kommen sollte.

            Ein Request zu einem Verzeichnis wird von meinem Apachen zum DirectoryIndex-Dokument umgeschrieben, bevor er die .htaccess des Verzeichnisses erreicht. Ohne DirectoryIndex-Dokument gibts ein Verzeichnislisting oder eine Fehlermeldung, wenn das nicht erlaubt ist. Ich weiß grad nicht, ob man ihm sagen kann: "Geh einfach auch ohne Dokument in das Verzeichnis, die .htaccess wird es schon regeln." Wenn es sowas nicht gibt, kann auch kein leerer Request an der RewriteRule ankommen.

            Der Rewrite-Mechanismus kürzt übrigens alles aus der URL, das zu übergeordneten Verzeichnissen gehört, und auch den / am Anfang weg, bevor es die RewriteRule zu sehen bekommt.

            dedlfix.

            1. Hi,

              Es kann keinen leeren Request ohne / geben. Den muss der Browser ergänzen, denn er kann nicht

              ich hab da irgendwas im Kopf, daß man im Apache konfigurieren konnte, ob der / automatisch hinzugefügt wird (oder eben nicht).

              Unter Eid würde ich das aber nicht aussagen …

              cu,
              Andreas a/k/a MudGuard

              1. Tach!

                Es kann keinen leeren Request ohne / geben. Den muss der Browser ergänzen, denn er kann nicht

                ich hab da irgendwas im Kopf, daß man im Apache konfigurieren konnte, ob der / automatisch hinzugefügt wird (oder eben nicht).

                Wenn du den DirectorySlash meinst ... das ist aber eine andere Baustelle. Dazu muss erstmal ein Pfad im Request vorhanden sein, der auf ein existierendes Verzeichnis passt.

                Übrigens wird ein Request mit leerer URL (GET HTTP/1.0) vom Apachen sofort nach dem Zeilenumbruch mit 400 beantwortet. Da wird nicht mal auf den zweiten gewartet, der das Ende der Header angibt.

                dedlfix.

                1. Hi,

                  Wenn du den DirectorySlash meinst ... das ist aber eine andere Baustelle. Dazu muss erstmal ein Pfad im Request vorhanden sein, der auf ein existierendes Verzeichnis passt.

                  Mag sein, daß es das war. Ist ewig her.

                  Übrigens wird ein Request mit leerer URL (GET HTTP/1.0) vom Apachen sofort nach dem Zeilenumbruch mit 400 beantwortet. Da wird nicht mal auf den zweiten gewartet, der das Ende der Header angibt.

                  ok.

                  cu,
                  Andreas a/k/a MudGuard

          2. Ich wüsste keine URI, die "^(.+)$" nicht erfüllen würde, beliebig viele beliebige Zeichen.

            Nein, nicht beliebig viele, ist ja .+, nicht .* - also mindestens 1 Zeichen.

            ah natürlich, danke

            Gematcht wird der Teil nach hostname+port, und vor dem Querystring.

            Bei http://example.org/bla?blubb also das /bla.

            nein, hier ging es um .htaccess, wir befinden uns also in einem Apache-Directory-Context:

            „In per-directory context (Directory and .htaccess), the Pattern is matched against only a partial path, for example a request of "/app1/index.html" may result in comparison against "app1/index.html" or "index.html" depending on where the RewriteRule is defined.

            The directory path where the rule is defined is stripped from the currently mapped filesystem path before comparison (up to and including a trailing slash). The net result of this per-directory prefix stripping is that rules in this context only match against the portion of the currently mapped filesystem path "below" where the rule is defined.“

            Der beginnende Slash wird also entfernt.

            Ob bei http://example.org der / automatisch ergänzt wird, weiß ich nicht - wenn nicht, wäre eine Url wie http://example.org eine, die nicht gematcht würde von ^(.+)$.

            Korrekt