Rewrite und seine Folgen
Encoder
- webserver
Hallo, ich hätte da ein Phänomen für das ich eine Erklärung suche. (mit Firefox getestet)
Ich habe eine Rewrite Regel, die einen Aufruf example.de/seite in example.de/page.php?name=seite umleitet. Das funktioniert bisher auch.
Nun gibt es ein Unterverzeichnis namens bilder.
Beim Aufruf example.de/bilder/ lande ich in diesem Verzeichnis. Passt.
Beim Aufruf example.de/bilder ohne / steht in der URL Zeile des Browsers example.de/bilder?name=bilder
Warum ist das so?
Dass hier das Verzeichnis erkannt wird statt nur auf example.de/pahe-php?name=bilder aufzurufen leuchtet mir ein. Immerhin gibt es das Verzeichnis.
Aber warum weiß plötzlich der Browser davon?
Jetzt wirds noch kurioser, ich nennen das Verzeichnis bilder um in irgendwas anderes.
Auch dann erfolgt bei der Eingabe example.de/bilder die browserseitige Umleitung.
Ich muss den Browsercache löschen damit example.de/bilder stehen bleibt.
Wie muss ich mir das erklären? Wer wandelt hier was wie um und warum weiß der Browser plötzlich auch davon?
Es ist übrigens FollowSymLinks eingeschaltet, falls das was zu sagen hat.
Tach!
Ich habe eine Rewrite Regel, die einen Aufruf example.de/seite in example.de/page.php?name=seite umleitet. Das funktioniert bisher auch.
Die macht also ein Redirect. Welches 30x ist es denn?
Nun gibt es ein Unterverzeichnis namens bilder.
Beim Aufruf example.de/bilder/ lande ich in diesem Verzeichnis. Passt.
Beim Aufruf example.de/bilder ohne / steht in der URL Zeile des Browsers example.de/bilder?name=bilder
Warum ist das so?
Das wird an der Regel liegen. Oder an einer anderen Ursache. Ohne die Regel zu kennen, kann man keine Theorie dagegen prüfen.
Dass hier das Verzeichnis erkannt wird statt nur auf example.de/pahe-php?name=bilder aufzurufen leuchtet mir ein. Immerhin gibt es das Verzeichnis.
Aber warum weiß plötzlich der Browser davon?
Der Browser weiß nichts von einem serverseitigen Verzeichnis.
Jetzt wirds noch kurioser, ich nennen das Verzeichnis bilder um in irgendwas anderes.
Auch dann erfolgt bei der Eingabe example.de/bilder die browserseitige Umleitung.
Ich muss den Browsercache löschen damit example.de/bilder stehen bleibt.
Dann denkt sich der Browser bei einer permanenten Umleitung: "Bevor ich da wieder anfrage und nochmal weggeschickt werde, gehe ich doch lieber gleich zum Ziel. Wenn's permanent ist, ändert sich daran ja nichts." Nach Cache-Löschen hat der Browser aber keine Erinnerung mehr, und fragt wieder neu.
Wie muss ich mir das erklären? Wer wandelt hier was wie um und warum weiß der Browser plötzlich auch davon?
Glaskugel oder eine Analyse der von dir verwendeten Direktiven und der HTTP-Header, was ist dir lieber?
Es ist übrigens FollowSymLinks eingeschaltet, falls das was zu sagen hat.
Hast du in die Dokumentation geschaut, was diese Direktive bewirken soll?
dedlfix.
Die macht also ein Redirect.
Hm.... Sie sollte nicht, sie soll den Rewrite nur intern auf das eine Script leiten. Aus /seit soll /page.php?name=seite werden.
Aber ob das auch wirklich immer passiert ist mir nicht so klar, du hast mich da auf etwas gebracht wo ich weitersuchen könnte. Ich werde mir die Headerdaten mal ansehen die ich da bekomme.
Vielleicht werde ich daraus selber schlau.
Es ist übrigens FollowSymLinks eingeschaltet, falls das was zu sagen hat.
Hast du in die Dokumentation geschaut, was diese Direktive bewirken soll?
Ja ich meine sie auch verstanden zu haben. Die ist auch nötig wenn man Rewrite nutzen will, nur warum hab ich dann allerdings nicht mehr verstanden.
Tach!
Die macht also ein Redirect.
Hm.... Sie sollte nicht, sie soll den Rewrite nur intern auf das eine Script leiten.
Das sollte auch im Browser zu sehen sein, denn dann bleibt die ursprünglich angeforderte Adresse stehen. Außerdem könnte man anhand der RewriteRule erkennen, ob ein Redirect oder ein Rewrite stattfindet. Es gibt da ein Flag, das ein Redirect erzwingt und bei vollständiger URL passiert das ebenfalls.
Es ist übrigens FollowSymLinks eingeschaltet, falls das was zu sagen hat.
Hast du in die Dokumentation geschaut, was diese Direktive bewirken soll?
Ja ich meine sie auch verstanden zu haben. Die ist auch nötig wenn man Rewrite nutzen will, nur warum hab ich dann allerdings nicht mehr verstanden.
Ahja, diese Option (keine Direktive) hat zu ihrer eigentlichen Bedeutung noch eine Nebenwirkung, die das Rewriting erlaubt oder nicht. Wenn nicht erlaubt, dürfte ein 500er kommen. Hat mit deinem Problem nichts weiter zu tun.
dedlfix.
Hallo dedlfix!
Ich weiß jetzt mehr. Da kommt tatsächlich ein 301 Moved permanently. Und ich scheine noch ein krasses Verständnisproblem zu haben.
Die komplette .htaccess sieht so aus:
DirectoryIndex page.php
RewriteEngine On
RewriteRule ^([a-zA-Z_0-9]*)$ /page.php?name=$1 [qsa]
Hat sich hier von dem erwähnten Flag für Redirect was eingeschlichen?
Bisher wird das für einen Aufruf von /irgendwas wird auch korrekt umgesetzt in den Aufruf /page.php?name=irgendwas ohne dass der Browser etwas davon mitbekommt.
Für den Aufruf /bild könnte ich mir folgendes vorstellen.
Der Server merkt dass "bild" ein Verzeichnis ist. Er setzt sich /bild/ als Ziel und wendet dann die Rule darauf an. Da kommt dann tatsächlich /bild/?name=bild raus.
Aber wird die aufgerufene URL nicht ganz zu Beginn verarbeitet, noch bevor der Server anfängt zu suchen was er ausliefern muss und was er von der original URL alles kennt? Das verstehe ich nicht.
Und warum schickt er das dann als Redirect?
Tach!
DirectoryIndex page.php
RewriteEngine On
RewriteRule ^([a-zA-Z_0-9]*)$ /page.php?name=$1 [qsa]
Hat sich hier von dem erwähnten Flag für Redirect was eingeschlichen?
Die RewriteRule leitet nicht auf eine URL um, sondern nur auf ein internes Ziel, und es steht auch kein R-Flag dabei. Das wären die beiden Gründe für ein Redirect (meines Wissens nach).
Für den Aufruf /bild könnte ich mir folgendes vorstellen.
Der Server merkt dass "bild" ein Verzeichnis ist.
Normalerweise grift zuerst die RewriteRule ohne Beachtung der wahren Gegebenheiten. Um diese mit einzubeziehen, weil man meist kein Rewriting für existierende Dateien oder Verzeichnisse haben möchte, muss man spezielle RewriteConds hinzufügen, die die Anwendung dieser Regel beim Vorhandensein von Verzeichnissen oder Dateien ausschließt.
Und warum schickt er das dann als Redirect?
Das geht aus den bisherigen Indizien nicht hervor. Vielleicht wirken noch Regeln aus übergeordneten Verzeichnissen (.htaccess) oder generellen Konfigurationen. Ein RewriteLog kann auch Auskunft geben, das kann aber nur ein Serveradministrator einrichten.
dedlfix.
Ein RewriteLog kann auch Auskunft geben, das kann aber nur ein Serveradministrator einrichten.
Ok das war nochmal ein Stichwort.
Ich hab mir lokal das access.log angesehen. Da steht: GET /bilder HTTP/1.1" 301 396
Daraufhin hab ich mir ein RewriteLog erzeugen lassen. In dem steht
[perdir D:/Homepages/test/] strip per-dir prefix: D:/Homepages/test/bilder -> bilder
[perdir D:/Homepages/test/] applying pattern '^([a-zA-Z_0-9]*)$' to uri 'bilder'
[perdir D:/Homepages/test/] rewrite 'bilder' -> '/page.php?name=bilder'
split uri=/page.php?name=bilder -> uri=/page.php, args=name=bilder
[perdir D:/Homepages/test/] internal redirect with /page.php [INTERNAL REDIRECT]
[perdir D:/Homepages/test/] strip per-dir prefix: D:/Homepages/test/bilder/ -> bilder/
[perdir D:/Homepages/test/] applying pattern '^([a-zA-Z_0-9]*)$' to uri 'bilder/'
[perdir D:/Homepages/test/] pass through D:/Homepages/test/bilder/
perdir D:/Homepages/test/] strip per-dir prefix: D:/Homepages/test/bilder/page.php -> bilder/page.php
[perdir D:/Homepages/test/] applying pattern '^([a-zA-Z_0-9]*)$' to uri 'bilder/page.php'
[perdir D:/Homepages/test/] pass through D:/Homepages/test/bilder/page.php
Anschließend nochmal was für favico, das habe ich entfernt.
D:\Homepages\test ist das Rootverzeichnis.
Die ganzen Einträge haben in der selben Sekunde bei einem einzigen Aufruf der Seite /bilder stattgefunden.
Da passiert doch was doppelt? Einmal apply pattern to uri 'bilder' und dann nochmal mit 'bilder/'.
Ich löse es indem ich einfach den Namen "bilder" nicht verwende. Was da passiert würd mich aber trotzdem interessieren.
Tach!
Da passiert doch was doppelt? Einmal apply pattern to uri 'bilder' und dann nochmal mit 'bilder/'.
Erklären kann ich es nicht, dazu müsste ich selbst mal ein paar Tests machen. Aber beim Rewriting wird nach dem Umschreiben ein neuer interner Request erzeugt. Der kollidiert möglicherweise mit dem vorhandenen Verzeichnis.
Ich löse es indem ich einfach den Namen "bilder" nicht verwende.
Das wird wohl das beste sein. Ich handhabe das auch so, dass die existierenden und virtuellen Verzeichnisse/Dateien nicht kollidieren. Und dann nehme ich die beiden RewriteCond zum Ausschließen der existerenden Verzeichnissen und Dateien.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
dedlfix.
Für den Aufruf /bild könnte ich mir folgendes vorstellen.
Der Server merkt dass "bild" ein Verzeichnis ist. Er setzt sich /bild/ als Ziel und wendet dann die Rule darauf an. Da kommt dann tatsächlich /bild/?name=bild raus.
Jau.
Aber wird die aufgerufene URL nicht ganz zu Beginn verarbeitet, noch bevor der Server anfängt zu suchen was er ausliefern muss und was er von der original URL alles kennt? Das verstehe ich nicht.
Und warum schickt er das dann als Redirect?
Standardmäßig ist bei Apache die DirectorySlash-Direktive aktiviert. Diese sorgt dafür, dass man Verzeichnisse auch ohne den eigentlich nötigen Slash am Ende der URI aufrufen kann oder, anders gesagt, "Apache must send a redirect to add the trailing slash to the URL".
Daher kommt das 301 zurück. Apache muss den Browser anweisen, die "richtige" URI anzufragen.
Du kannst das theoretisch mittels
DirectorySlash Off
deaktivieren, würd ich aber nicht empfehlen. Das ist schon ganz sinnvoll so.
Inwiefern sich das jetzt genau mit den Angaben für mod_rewrite vermischt, kann ich so direkt auch nicht nachvollziehen (womöglich wendet er erst die Rule an, erhält daraus den QueryString name=bild, und dann wird klar, dass eine andere Datei als angefordert ausgegeben werden muss, weswegen nicht /bild/page.php?name=bild herauskommt, was ich jetzt so erwartet hätte, sondern eben /bild/?name=bild. Aber da bin ich überfragt).
Hi
weswegen nicht /bild/page.php?name=bild herauskommt
Sorry das hab ich falsch abgeschrieben! Es kommt schon /bild/page.php?name=bild heraus :-)