Komisches Verhalten von RewriteRule
MrSnoot
- webserver
Hio,
ich habe bspw. folgende RewriteRule:
(#1): RewriteRule ^([^/\.]*)/$ hl.php?bereich=$1
um über '/grundlagen' auf /hl.php?bereich=grundlagen zuzugreifen.
Das klappt, '/grundlagen' wird in der Adresszeile allerdings automatisch zu '/grundlagen/'.
Anders sieht es bei einem zusätzlichen Unterverzeichnis aus:
(#2): RewriteRule ^([^/\.]*)/([^/\.]*)$ hl.php?bereich=$1&thema=$2
Zu beachten ist, dass hier am Ende des Suchstrings kein '/' steht. Bei der Eingabe von '/grundlagen/atombau' kommt auch diese Seite.
Wenn ich bei nur einer Variable (#1) den '/' am Ende des Suchstrings weglasse, wird die Seite nicht gefunden.
Wenn ich bei zwei Variablen (#2) den '/' am Ende des Suchstrings hinzufüge, muss ich explizit die Adresse auch mit '/' am Ende aufrufen.
Wieso kann ich bei (#1) den '/' am Ende also nicht weglassen, die Seite wird aber sowohl bei '/grundlagen' als auch '/grundlagen/' gefunden, bei (#2) muss ich jedoch die URL genau so mit oder ohne '/' eingeben, wie ich es in der Rule definiert habe?
echo $begrüßung;
ich habe bspw. folgende RewriteRule:
(#1):
RewriteRule ^([^/\.]*)/$ hl.php?bereich=$1um über '/grundlagen' auf /hl.php?bereich=grundlagen zuzugreifen.
Das klappt, '/grundlagen' wird in der Adresszeile allerdings automatisch zu '/grundlagen/'.
Das ist ein übliches Verhalten der Webserver. Die Ressource heißt /grundlagen/ mit / am Ende, da es ein Verzeichnis und keine Datei ist. Wenn der Server beim Request nach /foo keine Datei aber ein Verzeichnis foo findet, sendet er einen Redirect auf /foo/ zum Client. Das muss so sein, damit der Client relativ verlinkte Dokumente finden kann. Hieße die Ressource /foo ergäbe ein Link auf bar einen Request nach /bar. Bei /foo/ wird jedoch /foo/bar nachgefragt.
Dein Request nach /grundlagen passt nicht auf die Regel. Es muss aber ein Verzeichnis namens grundlagen geben, sonst ergäbe es einen 404. Der Server schickt den Redirect, woraufhin der Client nach /grundlagen/ fragt und die Regel zutrifft.
Den Rest der Fragen, so hoffe ich, kannst du nun selbst klären. Hilfreiche Werkzeuge sind die livehttpheaders-Extension für den Firefox, um sich den HTTP-Header-Verkehr zwischen Client und Server anzusehen, sowie das RewriteLog des Apachen, bei Unklarheiten des mod_rewrite-Verhaltens. Um Letzeres zu aktivieren braucht man aber administrativen Zugriff auf den Apachen.
echo "$verabschiedung $name";
Vielen Dank für die ausführliche Erklärung, das klingt plausibel :)
Jetzt muss ich doch noch einmal nachhaken, da wieder etwas merkwürdiges (oder doch erklärliches? :D) passiert.
Ich habe also diese Regel:
RewriteRule ^([^/.]*)/$ hl.php?bereich=$1
RewriteRule ^([^/.]*)/([^/.]*)/$ hl.php?bereich=$1&thema=$2
Wenn ich als Adresse 'grundlagen/atombau' eingebe, wird also zu 'grundlagen/atombau/' umgeleitet, passt also. Ebenso klappt das mit jeder anderen Adresse, bis auf eine. Dort wird eben der '/' am Ende nicht automatisch ergänzt und die Seite nicht gefunden.
Habe es mit Opera/FF/IE probiert um zu verhindern, dass irgendwas altes aus dem Cache kommt.
Mit der FF-Extension seh ich leider nichts, was mir da weiterhelfen könnte.
Irgendwas kleines muss ich da übersehen, aber was?
Wenn ich als Adresse 'grundlagen/atombau' eingebe, wird also zu 'grundlagen/atombau/' umgeleitet
Existiert denn der Ordner grundlagen/atombau/ physisch auf dem Server, oder ist das ein „virtueller Pfad“? Wenn er nicht existiert, würde ich nicht „passt also“ sagen – dann liegt nämlich irgendwo anders eine Fehlfunktion vor.
Punkte innerhalb von Zeichenklassen bzw. negierten Zeichenklassen [^/.] müssen nicht escaped werden, nur außerhalb, da die dort sonst eine andere Bedeutung (beliebiges Zeichen) haben.
(#1):
RewriteRule ^([^/\.]*)/$ hl.php?bereich=$1um über '/grundlagen' auf /hl.php?bereich=grundlagen zuzugreifen.
Das klappt, '/grundlagen' wird in der Adresszeile allerdings automatisch zu '/grundlagen/'.
Ein Verzeichnis grundlagen/ existiert auch physisch auf dem Server? Dann bist du auf einen (bereits bekannten) Bug gestoßen. Nach dem fixup-hook von mod_rewrite und dem internal redirect processing, läuft der fixup-hook von mod_dir des ursprünglichen Requests. Er läuft folglich noch mit einem eigentlich nicjht mehr korrekten r->uri-Wert, was nunmehr zu dem unterwünschten Redirect durch mod_dir führt.
Du musst dir das (vereinfacht) so vorstellen:
mod_rewrite fixup orig. request
internal redirect
mod_rewrite fixup internal redirect
mod_dir fixup internal redirect
ende internal redirect
mod_dir fixup orig. request <-- hier entsteht das Problem
content handler
Also nachdem das Processing des internal redirects abgeschlossen ist, greift erst der fixup-hook des urspr. requests von mod_dir. Das führt zu dem o.a. Fehlverhalten. Normalerweise müssten nach dem Einleiten des internal redirects durch mod_rewrite alle weiteren fixup-hooks des urpsr. requests gecanceled werden.