Apache, Rewriting, Zugriff auf umgeschriebene URL in RewriteCond
MudGuard
- webserver
Hi,
In meinem Verzeichnis d:/HTML/test befinden sich 2 Dateien:
foo.htm
index.htm
Ich hätte jetzt gerne folgende Dateien ausgeliefert:
Request: Auslieferung:
/test/index.htm index.htm (index.htm existiert ==> benutzen)
/test/index.html index.htm (.html --> .htm, index.htm existiert ==> benutzen)
/test/foo.htm foo.htm (foo.htm existiert ==> benutzen)
/test/foo.html foo.htm (.html --> .htm, foo.htm existiert ==> benutzen)
/test/bar.htm index.htm (bar.htm existiert nicht ==> index.htm)
/test/bar.html index.htm (.html --> .htm, bar.htm existiert nicht ==> index.htm)
/test/baz.htm index.htm (baz.htm existiert nicht ==> index.htm)
/test/baz.html index.htm (.html --> .htm, baz.htm existiert nicht ==> index.htm)
Mit anderen Worten: die Endung .html auf .htm umschreiben, danach, falls die Datei existiert, diese ausliefern, ansonsten die index.htm ausliefern.
(zwischen den Schritten .html --> .htm und nichtexistierend --> index.htm sollen noch weitere Schritte folgen, in denen noch der Pfad geändert werden könnte)
DocumentRoot ist d:/HTML
Folgendes steht in meiner rewrite.conf
RewriteEngine On
RewriteLog "logs/rewrite.log"
RewriteLogLevel 9
RewriteRule /test/(.*).html /test/$1.htm
RewriteCond %{REQUEST_URI} (/test/[^/]+/[^/]+/.*)
RewriteCond %{DOCUMENT_ROOT}%1 !-f
RewriteRule /test/([^/]+)/([^/]+)/(.*) /test/$1/$2/index.htm
Im Rewritelog steht für den Aufruf von http://localhost/test/foo.html folgendes (die Spalten mit IP, Zeit usw. hab ich weggetan, die sind uninteressant, dafür hab ich Zeilennummern davorgesetzt):
1: (2) init rewrite engine with requested uri /test/foo.html
2: (3) applying pattern '/test/(.*).html' to uri '/test/foo.html'
3: (2) rewrite /test/foo.html -> /test/foo.htm
4: (3) applying pattern '/test/([^/]+)/([^/]+)/(.*)' to uri '/test/foo.htm'
5: (4) RewriteCond: input='/test/foo.html' pattern='(/test/[^/]+/[^/]+/.*)' => matched
6: (4) RewriteCond: input='D:/HTML/test/foo.html' pattern='!-f' => matched
7: (2) rewrite /test/foo.htm -> /test/index.htm
8: (2) local path result: /test/index.htm
9: (2) prefixed with document_root to D:/HTML/test/index.htm
10: (1) go-ahead with D:/HTML/test/index.htm [OK]
Angezeigt wird also die index.htm, nicht die foo.htm
Zeile 1 zeigt den ursprünglichen Request.
Zeile 2 und 3 zeigen, daß das Entfernen des l vom .html klappt.
Zeile 4 zeigt, daß jetzt versucht wird, die Regel für index.htm anzuwenden, hier mit der korrekten Endung .htm
Zeile 5 zeigt, daß die erste Bedingung geprüft wird, allerdings mit der Original-URI, nicht mit der aktuellen.
Damit ist auch das %1 in der zweiten Bedingung falsch belegt, es wird nach foo.html gesucht, welches natürlich nicht gefunden wird.
Damit wird auf index.htm umgeschrieben.
Wenn ich das richtig sehe, brauche ich also in der ersten Bedingung statt %{REQUEST_URI} eher %{REQUEST_URI_AFTER_PREVIOUS_REWRITES_ARE_APPLIED}.
Dazu finde ich in der Doku aber leider nichts.
Auch der Versuch, der ersten Rule ein [N] zu verpassen, hat nichts wesentliches geändert:
1: (2) init rewrite engine with requested uri /test/foo.html
2: (3) applying pattern '/test/(.*).html' to uri '/test/foo.html'
3: (2) rewrite /test/foo.html -> /test/foo.htm
3a: (3) applying pattern '/test/(.*).html' to uri '/test/foo.htm'
4: (3) applying pattern '/test/([^/]+)/([^/]+)/(.*)' to uri '/test/foo.htm'
5: (4) RewriteCond: input='/test/foo.html' pattern='(/test/[^/]+/[^/]+/.*)' => matched
6: (4) RewriteCond: input='D:/HTML/test/foo.html' pattern='!-f' => matched
7: (2) rewrite /test/foo.htm -> /test/index.htm
8: (2) local path result: /test/index.htm
9: (2) prefixed with document_root to D:/HTML/test/index.htm
10: (1) go-ahead with D:/HTML/test/index.htm [OK]
Es ist nur die Zeile 3a dazugekommen.
[R] darf ich nicht benutzen, der Client soll nichts von der Umschreiberei mitbekommen.
cu,
Andreas
Hi,
Folgendes steht in meiner rewrite.conf
RewriteEngine On
RewriteLog "logs/rewrite.log"
RewriteLogLevel 9.html ---> .htm (for historical reasons)
RewriteRule /test/(.*).html /test/$1.htm
if file does not exist --> index.htm
RewriteCond %{REQUEST_URI} (/test/[^/]+/[^/]+/.*)
RewriteCond %{DOCUMENT_ROOT}%1 !-f
RewriteRule /test/([^/]+)/([^/]+)/(.*) /test/$1/$2/index.htm
Kleiner Fehler beim Anonymisieren, in Wirklichkeit stehen da noch 2 Verzeichnisebenen dazwischen, es muß passend zum Beispiel heißen:
RewriteCond %{REQUEST_URI} (/test//.*)
RewriteCond %{DOCUMENT_ROOT}%1 !-f
RewriteRule /test/(.*) /test/index.htm
Im Rewritelog steht für den Aufruf von http://localhost/test/foo.html folgendes (die Spalten mit IP, Zeit usw. hab ich weggetan, die sind uninteressant, dafür hab ich Zeilennummern davorgesetzt):
1: (2) init rewrite engine with requested uri /test/foo.html
2: (3) applying pattern '/test/(.*).html' to uri '/test/foo.html'
3: (2) rewrite /test/foo.html -> /test/foo.htm
4: (3) applying pattern '/test/([^/]+)/([^/]+)/(.*)' to uri '/test/foo.htm'
5: (4) RewriteCond: input='/test/foo.html' pattern='(/test/[^/]+/[^/]+/.*)' => matched
Hier dann entsprechend
4: (3) applying pattern '/test/(.*)' to uri '/test/foo.htm'
5: (4) RewriteCond: input='/test/foo.html' pattern='(/test/.*)' => matched
(und analog im zweiten Rewrite-Log listing)
6: (4) RewriteCond: input='D:/HTML/test/foo.html' pattern='!-f' => matched
7: (2) rewrite /test/foo.htm -> /test/index.htm
8: (2) local path result: /test/index.htm
9: (2) prefixed with document_root to D:/HTML/test/index.htm
10: (1) go-ahead with D:/HTML/test/index.htm [OK]
cu,
Andreas
Hi,
Wenn ich das richtig sehe, brauche ich also in der ersten Bedingung statt %{REQUEST_URI} eher %{REQUEST_URI_AFTER_PREVIOUS_REWRITES_ARE_APPLIED}.
Ok, aus reiner Verzweiflung hab ich jetzt mal REQUEST_FILE_NAME probiert - trotz der Beschreibung "The full local filesystem path to the file or script matching the request." - und siehe da, da steht tatsächlich nicht der vollständige lokale Dateisystempfad des Requests drin, sondern die URL, wie sie nach den bisherigen Rewrites aussieht.
Mit
RewriteCond %{REQUEST_FILENAME} /test/[^/]+/[^/]+/.*
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule /test/([^/]+)/([^/]+)/(.*) /test/$1/$2/index.htm
funktioniert es jetzt.
cu,
Andreas
Hi MudGuard,
Prima, du hast dein Problem ja jetzt schon gelöst, aber:
.html ---> .htm (for historical reasons)
RewriteRule /test/(.*).html /test/$1.htm
Das hier dürfte ja einwandfrei funktionieren.
if file does not exist --> index.htm
RewriteCond %{REQUEST_URI} (/test/[^/]+/[^/]+/.*)
RewriteCond %{DOCUMENT_ROOT}%1 !-f
RewriteRule /test/([^/]+)/([^/]+)/(.*) /test/$1/$2/index.htm
Und warum nimmst du hier nicht ErrorDocument?
MfG, Dennis.
Hi,
if file does not exist --> index.htm
RewriteCond %{REQUEST_URI} (/test/[^/]+/[^/]+/.*)
RewriteCond %{DOCUMENT_ROOT}%1 !-f
RewriteRule /test/([^/]+)/([^/]+)/(.*) /test/$1/$2/index.htm
Und warum nimmst du hier nicht ErrorDocument?
Weil kein Error beim Client ankommen soll und das File statisch ist.
Und weil außerdem noch ähnliche Manipulationen im Pfad stattfinden (wenn ein Verzeichnis nicht real existiert, benutze ein bestimmtes vordefiniertes Verzeichnis), wo mit ErrorDocument nicht geholfen wäre, da ggf. nur eine Verzeichnisebene manipuliert wird, alle anderen Teile aber gleichbleiben sollen.
Und ich find es dann schöner, wenn alle derartigen Manipulationen an einer einzigen Stelle stehen, und nicht einige bei den RewriteRules, andere bei den ErrorDocuments usw.
cu,
Andreas