molily: mod_rewrite, Rewriterules werden mehrfach angewendet

Hallo,

ich möchte Dateien mit der Endung .html anspeichern und möchte, dass sie auch ohne Dateiendung erreichbar sind. Zusätzlich soll immer auf die jeweilige URL ohne Dateiendung weitergeleitet werden. Mangels MultiViews habe ich es mit mod_rewrite versucht. /bla/blub.html soll also extern auf /bla/blub umgeleitet werden, was intern wieder auf /bla/blub.html umgesetzt wird. Ich dachte an folgendes:

RewriteEngine On
RewriteBase /
RewriteRule (.+).html$ /$1 [redirect=permanent,last]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+) $1.html [last,nosubreq]

Der last-Flag bei der ersten Regel wirkt, die Flags bei der zweiten habe ich nur testweise eingefügt, sie bringen beide nicht das Erhoffte.

Wenn ich localhost/bla/test.html aufrufe, zeigt das Rewrite-Log:

[per-dir c:/projekte/] strip per-dir prefix: c:/projekte/bla/test.html -> bla/test.html
[per-dir c:/projekte/] applying pattern '(.+).html$' to uri 'bla/test.html'
[per-dir c:/projekte/] rewrite bla/test.html -> /bla/test
[per-dir c:/projekte/] explicitly forcing redirect with http://localhost/bla/test
[per-dir c:/projekte/] escaping http://localhost/bla/test for redirect
[per-dir c:/projekte/] redirect to http://localhost/bla/test [REDIRECT/301]

Das ist wie beabsichtigt. Wenn der Browser dem Redirect folgt, kommt:

initial (...) [per-dir c:/projekte/] strip per-dir prefix: c:/projekte/bla/test -> bla/test
initial (...) [per-dir c:/projekte/] applying pattern '(.+).html$' to uri 'bla/test'
initial (...) [per-dir c:/projekte/] strip per-dir prefix: c:/projekte/bla/test -> bla/test
initial (...) [per-dir c:/projekte/] applying pattern '^(.+)' to uri 'bla/test'
initial (...) RewriteCond: input='c:/projekte/bla/test' pattern='!-f' => matched
initial (...) RewriteCond: input='c:/projekte/bla/test.html' pattern='-f' => matched
initial (...) [per-dir c:/projekte/] rewrite bla/test -> bla/test.html
initial (...) [per-dir c:/projekte/] add per-dir prefix: bla/test.html -> c:/projekte/bla/test.html

Bis hier ist alles wie beabsichtigt. /bla/test wird intern zu /bla/test.html umgeschrieben, weil keine Datei /bla/test existiert. Danach kommt allerdings ein »internal redirect«, den ich mir nicht erklären kann:

initial (...) [per-dir c:/projekte/] strip document_root prefix: c:/projekte/bla/test.html -> /bla/test.html
initial (...) [per-dir c:/projekte/] internal redirect with /bla/test.html [INTERNAL REDIRECT]
initial/redir#1 (...) [per-dir c:/projekte/] strip per-dir prefix: c:/projekte/bla/test.html -> bla/test.html
initial/redir#1 (...) [per-dir c:/projekte/] applying pattern '(.+).html$' to uri 'bla/test.html'
initial/redir#1 (...) [per-dir c:/projekte/] rewrite bla/test.html -> /bla/test

Hier wendet er wieder Regel eins auf den umgeschriebenen Pfad an und schneidet .html wieder ab.

initial/redir#1 (...) [per-dir c:/projekte/] explicitly forcing redirect with http://localhost/bla/test
initial/redir#1 (...) [per-dir c:/projekte/] escaping http://localhost/bla/test for redirect
initial/redir#1 (...) [per-dir c:/projekte/] redirect to http://localhost/bla/test [REDIRECT/301]

Somit leitet /bla/test letztlich wieder auf /bla/test weiter und der Browser wird endlos weitergeleitet. Wie kann das verhindert werden?

Mathias

  1. Hallo Mathias,

    Somit leitet /bla/test letztlich wieder auf /bla/test weiter und der Browser wird endlos weitergeleitet. Wie kann das verhindert werden?

    RewriteEngine On
    RewriteBase /
    RewriteRule (.+).html$ /$1 [redirect=permanent,last,nosubreq]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME}.html -f
    RewriteRule ^(.+) $1.html [last]

    Damit sollte es klappen. Denn: Sobald die letzte RewriteRule erfolgreich war, wird zwansgläufig ein virtual Subrequest mit der neuen URI gestartet (es sei denn, es ist ein Redirect oder so etwas). Das kann man nicht deaktivieren, so funktioniert mod_rewrite. nosubreq dagegen sagt nur, dass diese Regel *übersprungen* werden soll, falls ein Subrequest durchgeführt wird. Aus der Doku:

    | This flag forces the rewriting engine to skip a rewriting rule if the current request is an internal sub-request.

    Daher muss das nosubreq zur Redirect-Regel und nicht zur HTML-Anfüge-Regel.

    Viele Grüße,
    Christian

    1. RewriteRule (.+).html$ /$1 [redirect=permanent,last,nosubreq]

      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME}.html -f
      RewriteRule ^(.+) $1.html [last]

      Das hatte ich schon versucht, es hat nicht den gewünschten Effekt. Es ändert sich nichts: Die erste Regel wird trotzdem wieder auf den Subrequest angewendet. Der Rewrite-Log ist identisch. /bla/test wird also auf /bla/test.html umgeschrieben und wieder im Subrequest auf /bla/test weitergeleitet.
      Ich teste auf 1.3.26 und 2.0.48 für Win32 und 1.3.28 für Linux, alle zeigen dasselbe Verhalten.

      nosubreq dagegen sagt nur, dass diese Regel *übersprungen* werden soll, falls ein Subrequest durchgeführt wird.

      Ja, das hört sich in der Theorie logisch an, deckt sich aber kein bisschen mit meinen Beobachtungen. Dies führt etwa zu einer Endlosschleife:

      RewriteRule (.+).html$ /$1 [last,nosubreq]
      RewriteRule ^(.+) $1.html [last,nosubreq]

      Jede andere Kombination, ob mit oder ohne last und nosubreq, an welcher Stelle und in welcher Kombination auch immer, hat denselben Effekt. Es werden unendlich viele Subrequests gestartet, in denen die Regeln immer wieder angewendet werden. Die Flags scheinen keine Auswirkung zu haben. Grmbl.

      1. Hallo Mathias,

        Das hatte ich schon versucht, es hat nicht den gewünschten Effekt.

        Dann setze bei der internen Rule per [E=HTML_STRIPPED:1] eine Umgebungsvariable und prüfe die bei der Weiterleitungsrule (RewriteCond).

        Viele Grüße,
        Christian

        1. Dann setze bei der internen Rule per [E=HTML_STRIPPED:1] eine Umgebungsvariable und prüfe die bei der Weiterleitungsrule (RewriteCond).

          Gute Idee. Leider lässt sich im Subrequest nicht auf die Umgebungsvariablen des initial request zugreifen:

          [Regel 1 matcht nicht, keine äußere Weiterleitung]
          [Regel 2 matcht und conditions ebenfalls]
          initial (2) [per-dir c:/projekte/] rewrite bla/test -> bla/test.html
          initial (5) setting env variable 'HTML_APPENDED' to '1'
          [Wenn hier eine dritte Regel folgen würde, könnte diese auf HTML_APPENDED==1 zugreifen.]
          ...
          initial (1) [per-dir c:/projekte/] internal redirect with /bla/test.html [INTERNAL REDIRECT]
          initial/redir#1 (3) [per-dir c:/projekte/] strip per-dir prefix: c:/projekte/bla/test.html -> bla/test.html
          initial/redir#1 (3) [per-dir c:/projekte/] applying pattern '(.+).html$' to uri 'bla/test.html'
          [Hier wird RewriteCond %{ENV:HTML_APPENDED} !^1$ abgearbeitet:]
          initial/redir#1 (4) RewriteCond: input='' pattern='!^1$' => matched
          initial/redir#1 (2) [per-dir c:/projekte/] rewrite bla/test.html -> /bla/test
          ...
          initial/redir#1 (1) [per-dir c:/projekte/] redirect to http://localhost/bla/test [REDIRECT/301]

          input ist leer, obwohl HTML_APPENDED auf 1 gesetzt wurde. Meine Tests zeigen, dass man nur auf die Variablen zugreifen kann, die Regeln des gleichen Requests gesetzt haben, im initial also auf die des initials, im redir#X auf die des redir#X.

          Langsam verzeifle ich. Danke aber für deine Tipps.

  2. Moin!

    ich möchte Dateien mit der Endung .html anspeichern und möchte, dass sie auch ohne Dateiendung erreichbar sind. Zusätzlich soll immer auf die jeweilige URL ohne Dateiendung weitergeleitet werden. Mangels MultiViews habe ich es mit mod_rewrite versucht. /bla/blub.html soll also extern auf /bla/blub umgeleitet werden, was intern wieder auf /bla/blub.html umgesetzt wird.

    Dein Vorhaben mag ja nett klingen, aber zumindest den Teil mit "Redirect auf URL ohne .html" würde ich mir an deiner Stelle sparen. Wenn du auf deiner Site ausschließlich URLs ohne Dateiendung verlinkst, sollte es keine Notwendigkeit geben, den Redirect zu benutzen. MultiViews funktioniert genauso - auch dort kann man eine Ressource explitzit anfordern durch Angabe der passenden Endungen - oder sich eine aussuchen lassen, wenn man keine Daten angibt.

    Mal so grundsätzlich gesagt: Wenn du endungslose URLs für HTML-Seiten verwendest - was machst du bei Bildern dann? Gemäß der Gleichbehandlung müßtest du die dann auch ohne Endung ausliefern.

    Alternativ kannst du natürlich dem Teufelskreis entwischen, indem du deine existierenden Dateien mit einer anderen Dateiendung bezeichnest. ".htm" wäre beispielsweise nett. Dann kommen dir jedenfalls keine Subrequests nach ".html" mehr in die Quere.

    - Sven Rautenberg

    --
    Die SelfHTML-Developer sagen Dankeschön für aktuell 20885,68 Euro Spendengelder!
    1. Dein Vorhaben mag ja nett klingen, aber zumindest den Teil mit "Redirect auf URL ohne .html" würde ich mir an deiner Stelle sparen. Wenn du auf deiner Site ausschließlich URLs ohne Dateiendung verlinkst, sollte es keine Notwendigkeit geben, den Redirect zu benutzen.

      Hm, das stimmt allerdings, wirklich notwendig ist diese Weiterleitung nicht und die Wahrscheinlichkeit, dass jemand eine Adresse mit Endung aufschnappt, ist gering. Wenn ich keine brauchbare Lösung finde, werde ich wohl ganz einfach auf diesen Teil verzichten, das Umschreiben von /request auf /request.html usw. alleine ist ja kein Problem.

      MultiViews funktioniert genauso - auch dort kann man eine Ressource explitzit anfordern durch Angabe der passenden Endungen - oder sich eine aussuchen lassen, wenn man keine Daten angibt.

      Wenn tatsächlich eine URL auf mehrere Dateien zeigt, die der Server je nach Request aussucht, hat das natürlich seinen Sinn. Allerdings gibt es in diesem Fall nur eine Ressource und ich würde MultiViews nicht wirklich für »Negotiation« einsetzen, weil in jedem Fall diese und nur diese Ressource gesendet wird. Es würden also mehrere URLs für unter allen Umständen ein- und dieselbe Ressource existieren, und das gefällt mir nicht, da ich die Adressierung eindeutig halten will.

      Mal so grundsätzlich gesagt: Wenn du endungslose URLs für HTML-Seiten verwendest - was machst du bei Bildern dann? Gemäß der Gleichbehandlung müßtest du die dann auch ohne Endung ausliefern.

      Das hatte ich vor und hätte es auch umgesetzt, wenn ich MultiViews zur Verfügung hätte. Aber jetzt wäre ich bereits froh, wenn für den Anfang die Inhaltsdokumente .html- und .php-Dateien ohne Endung aufgerufen werden können, ganz einfach weil deren URLs häufiger »benutzt« werden. Ich habe keine Grafiken, deren Adressen großartig einzeln benutzt werden (Adresszeile, Links, Bookmarks, Suchmaschinen, Merkbarkeit...).

      1. Moin!

        MultiViews funktioniert genauso - auch dort kann man eine Ressource explitzit anfordern durch Angabe der passenden Endungen - oder sich eine aussuchen lassen, wenn man keine Daten angibt.

        Wenn tatsächlich eine URL auf mehrere Dateien zeigt, die der Server je nach Request aussucht, hat das natürlich seinen Sinn. Allerdings gibt es in diesem Fall nur eine Ressource und ich würde MultiViews nicht wirklich für »Negotiation« einsetzen, weil in jedem Fall diese und nur diese Ressource gesendet wird.

        Mit anderen Worten: Es gibt überhaupt keinen Grund, auf die Dateiendung zu verzichten.

        Du hast den Grund für deine Aktion noch nicht genannt. Was also willst du erreichen?

        Es würden also mehrere URLs für unter allen Umständen ein- und dieselbe Ressource existieren, und das gefällt mir nicht, da ich die Adressierung eindeutig halten will.

        Diesen Zustand hast du so oder so. Mit Redirects von endungshaltigen URLs auf endungslose URLs machst du einen ganzen Satz zusätzlicher URLs gültig - auch wenn die nur einen permanenten Redirect auslösen. Die korrekte Antwort für eine nichtexistente URL wäre 404. Dann hast du Eindeutigkeit, nämlich ausschließlich ".html".

        Mal so grundsätzlich gesagt: Wenn du endungslose URLs für HTML-Seiten verwendest - was machst du bei Bildern dann? Gemäß der Gleichbehandlung müßtest du die dann auch ohne Endung ausliefern.

        Das hatte ich vor und hätte es auch umgesetzt, wenn ich MultiViews zur Verfügung hätte. Aber jetzt wäre ich bereits froh, wenn für den Anfang die Inhaltsdokumente .html- und .php-Dateien ohne Endung aufgerufen werden können, ganz einfach weil deren URLs häufiger »benutzt« werden. Ich habe keine Grafiken, deren Adressen großartig einzeln benutzt werden (Adresszeile, Links, Bookmarks, Suchmaschinen, Merkbarkeit...).

        Dann hast du das falsche Werkzeug für die Aufgabe eingesetzt. Multiviews wären dafür sowieso nicht wirklich zuständig.

        Du willst also eine vernünftige URL-Struktur mit der Möglichkeit, kurze, direkte URLs nutzen zu können?

        Lass die Endung ".html" an allen URLs dran. Ändere die Endung ".php" in ".html" um (in den URLs, nicht in den Dateinamen - umbiegen mit mod_rewrite). Schon hast du Einheitlichkeit: HTML-Seiten enden auf .html, JPEG-Bilder auf .jpg, etc...

        Und wenn du kurze, prägnante URLs haben willst, kannst du ja immer noch Kurzlinks definieren, die auf die längere Location redirecten. Oder als einzeln definierter Alias denselben Inhalt direkt ausliefern.

        Ich glaube aber nicht, dass das Weglassen von Dateiendungen irgendwie mehr Klarheit oder Einsparung in der Tipparbeit bringt. Denn wenn du keine Endung verwendest, benutzt du ein ungewöhnliches URL-Schema.

        Einerseits sind Benutzer durchaus gewohnt, am Ende auch mal ".html" zu tippen. Andererseits werden deine Unterseiten mutmaßlich sowieso nicht durch "tippen" der URL aufgerufen, sondern überwiegend durch Verfolgen von Links (auf deinen eigenen oder den Seiten anderer, z.B. in Suchmaschinen), Aufrufen von Bookmarks bzw. Nutzen der automatischen URL-Ergänzung des Browsers. Ohne Endung schaffst du die Verwirrung zwischen Verzeichnissen (die ja eigentlich auf "/" enden sollten, aber auch ohne funktionieren können) und Seitennamen. Außerdem ließen sich solche Seiten nicht einfach so abspeichern und lokal nutzen, weil die Endung fehlt.

        - Sven Rautenberg

        --
        Die SelfHTML-Developer sagen Dankeschön für aktuell 20885,68 Euro Spendengelder!
        1. Mit anderen Worten: Es gibt überhaupt keinen Grund, auf die Dateiendung zu verzichten.

          Ich sehe keinen Grund für Dateiendungen, das ist der Grund zum Verzicht.

          Es würden also mehrere URLs für unter allen Umständen ein- und dieselbe Ressource existieren, und das gefällt mir nicht, da ich die Adressierung eindeutig halten will.

          Diesen Zustand hast du so oder so. Mit Redirects von endungshaltigen URLs auf endungslose URLs machst du einen ganzen Satz zusätzlicher URLs gültig - auch wenn die nur einen permanenten Redirect auslösen.

          Sicherlich ist die URL gültig im Sinne von zielführend und verwendbar (ich bezeifle aber, dass das ein Kriterium ist, denn alle URLs sollten in dem Sinne zielführend und verwendbar sein, sei es auch 410 Gone usw.), aber nicht gültig im Sinne von aktuell und »richtig«. Eine permanente Weiterleitung heißt meinem Verständnis nach, dass die alte URL obsolet ist (nun gut, in diesem Fall waren die endungshaltigen nie die »richtigen«, von Migration von endungshaltigen zu endungslosen URLs abgesehen).

          Die korrekte Antwort für eine nichtexistente URL wäre 404. Dann hast du Eindeutigkeit, nämlich ausschließlich ".html".

          Das wäre wirklich eine Idee, ich würde es allerdings anders herum lösen. Für mich ist dies in Form einer allgemeinen Rewrite-Regel (mache alle .html-Dateien nur endungslos zugänglich und gebe in allen anderen Fällen 404) dennoch nicht praktikabel, da ich .html durchaus in Einzelfällen einsetze, etwa um .html von .xhtml nach außen sichtbar zu unterscheiden oder Bereiche der Sites mit Endungen zu versehen, damit sie exakt einer herunterladbaren Offline-Version entsprechen. Da müsste ich wieder Ausnahmen in die Regeln einbauen und Listen von Dateien verwalten, die umgeschrieben werden müssen oder nicht dürfen. Ob ich da mit verschiedenen .htaccess-Dateien arbeiten will, die sich gegenseitig aufheben, kann ich noch nicht abschätzen, daher lässt mir die inkonsequente Lösung möglicherweise in Zukunft nötigen Spielraum.

          Du willst also eine vernünftige URL-Struktur mit der Möglichkeit, kurze, direkte URLs nutzen zu können?

          Lass die Endung ".html" an allen URLs dran. Ändere die Endung ".php" in ".html" um (in den URLs, nicht in den Dateinamen - umbiegen mit mod_rewrite). Schon hast du Einheitlichkeit: HTML-Seiten enden auf .html, JPEG-Bilder auf .jpg, etc...

          Prinzipiell sehe ich kein Problem darin, nur den hauptsächlichen Inhaltsträgern, deren URL nach außen hin sichtbar ist, die Endung zu nehmen. Das ist bei Hypertext wohl meist HTML, bei Bildern als Hauptinhalt vermittelt auch immer HTML. Alles andere Interaktive arbeitet nicht mit dem Konzept einzeln adressierbarer Dokumente. Daher wäre es zumindest in der Inkonsequenz konsequent, dass nur (möglicherweise generierte) HTML-Dokumente endungslos erreichbar sind. Anders gesagt wüsste ich nicht, was die bedingungslose Einheitlichkeit, also ganz oder gar nicht, für einen Vorteil bringt, wenn möglichst eindeutige Konventionen bestehen.

          Und wenn du kurze, prägnante URLs haben willst, kannst du ja immer noch Kurzlinks definieren, die auf die längere Location redirecten. Oder als einzeln definierter Alias denselben Inhalt direkt ausliefern.

          Möchte ich nicht, das würde mein Bestreben nach Eindeutigkeit wieder untergraben. Da versuche ich die Adresse lieber anders zu verkürzen.

          Ich glaube aber nicht, dass das Weglassen von Dateiendungen irgendwie mehr Klarheit oder Einsparung in der Tipparbeit bringt. Denn wenn du keine Endung verwendest, benutzt du ein ungewöhnliches URL-Schema.

          Von der Seite der Gewohnheit aus mag das eingeschränkt zutreffen. Ich sehe aber nicht als einzig normativ an.

          Einerseits sind Benutzer durchaus gewohnt, am Ende auch mal ".html" zu tippen.

          Sie sagen ihnen aber nichts, sie erkennen diese Zeichenkette nicht als den Ressourcentyp anzeigenden Suffix, genauso wenig wie sie .php, .pl, .cgi usw. als Endungen von Ressourcen identifizieren, die in der Regel denselben Typ wie .html haben bzw. potenziell haben können.
          Wer nicht weiß, was .html bedeutet, wird es als Nullinformation auffassen und wird nur eine Häufigkeit von URLs mit .html am Ende haben bemerken, die für ihn nichts bedeutet, eben weil es die Konvention, dass alle text/html-Ressourcen einheitlich .html in der Adresse haben, nicht gibt (und ich bin ferner nicht der Meinung, dass man diese durchsetzen sollte, allerdings sollten .pl, .cgi, .php, .py usw. wirklich vermieden werden).
          Ich sehe keinen Vorteil darin, dass für den Großteil der Besucher nicht-sprechende Zeichenketten Teil von Adressen sind (das heißt nicht, dass ich .webdokument, .grafik, .formatvorlage, .videofilm oder .musikstueck sonderlich besser finde, aber es würde zumindest einen Zweck erfüllen).

          Andererseits werden deine Unterseiten mutmaßlich sowieso nicht durch "tippen" der URL aufgerufen, sondern überwiegend durch Verfolgen von Links (auf deinen eigenen oder den Seiten anderer, z.B. in Suchmaschinen), Aufrufen von Bookmarks bzw. Nutzen der automatischen URL-Ergänzung des Browsers.

          Das sehe ich anders, ich für meinen Teil kenne viele Adressen auswendig und tippe sie schneller ein, als ich sie in meinen Bookmarks über die Schnellsuche gefunden habe.

          Ohne Endung schaffst du die Verwirrung zwischen Verzeichnissen und Seitennamen.

          Da sehe ich kein großes Problempotenzial, da es für diejenigen, die die Bestandteile einer URL verstehen, sehr wohl erkennbar ist, dass es sich nicht um ein Verzeichnis handelt. Die anderen sind m.E. nicht sehr verunsichert, wenn sie auf eine URL ohne Endung stoßen, vor allem wenn sie sich ab dem letzten Slash aus erkennbaren Wörtern zusammensetzt, die höchstens durch »-« getrennt sind.

          Diejenigen, die Verzeichnisse prinzipiell ohne abschließendes »/« aufrufen und somit, wenn auch unbewusst, andauernd der Fehlererkennung der Server vertrauen, sollten vielleicht ab und zu der Adressleiste entnehmen, wie die richtige URLs lautet. Schließlich wird extern und permanent weitergeleitet, sodass ihnen Verzeichnisse fast im kompletten WWW ausschließlich mit »/« am Ende begegnen.
          Natürlich lässt sich auch hier der DAU konstruieren, der nicht weiß, dass es sich um Verzeichnisse handelt und sich nie darüber Gedanken gemacht hat, dass eine URL einen Pfad zu einer bestimmten Datei in einer Hierarchie abbildet. Aber der darf die Konzepte »Verzeichnis« und »Datei« nicht einmal ansatzweise verstehen, also, das ist wirklich konstruiert.

          Diejenigen, die solchen URLs beim Eintippen einen Schrägstrich anfügen, weil sie irrtümlich annehmen, es handle sich um ein Verzeichnis, halte ich für vernachlässigbar, weil ich mir nicht vorstellen kann, dass jemand, der weiß, wie sich Dateien und Verzeichnisse in der URL konstituieren, ein Einzeldokument mit einem Verzeichnis verwechseln, wenn er weiß, dass die URL ein Einzeldokument ist. Und das weiß er höchstwahrscheinlich, wenn er die URL aus dem Kopf direkt eintippt.

          Beide Szenarien des Eintippens sind wie gesagt schon an sich selten.

          Außerdem ließen sich solche Seiten nicht einfach so abspeichern und lokal nutzen, weil die Endung fehlt.

          Gibt es dazu empirische Untersuchungen, in wie weit das wirklich ein Problem ist?

  3. Hallo molily,

    ich möchte Dateien mit der Endung .html anspeichern und möchte, dass
    sie auch ohne Dateiendung erreichbar sind.

    So bei mir aktiv und getestet:

    RewriteEngine On

    RewriteCond %{REQUEST_URI} .html$
    RewriteRule (.*).html http://rain/test/$1 [QSA,L,NS,R=301]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}.html -f
    RewriteRule (.*) $1.html [QSA,L]

    Apache 1.3.29, FreeBSD 4.6-RELEASE

    Gruesse,
     CK

    --
    Wenn der Schüler bereit ist, erscheint der Meister.