seth_not@home: loop verhindern bei redirect-rewrite-kombination

gudn tach!

hmm, ist das nun der themenbereich http, server oder projektverwaltung?

jedenfalls gibt es derzeit bei einem projekt urls der form

http://www.example.com/bar/...

kuenftig sollen die urls aber lauten:

http://www.example.com/foo/bar/...

es soll also noch ein "/foo" eingeschoben werden. die filestruktur auf dem server soll unangetastet bleiben. also dachte ich da an folgende kombination:

* redirect von http://www.example.com/bar/(.*) nach http://www.example.com/foo/bar/$1
* rewrite von http://www.example.com/foo/bar/(.*) nach http://www.example.com/bar/$1

das ergaebe aber vermutlich normalerweise eine schleife, oder?
an der apache-syntax verzweifle ich alle paar jahre, wenn ich mich mit sowas beschaeftige. gaeb es da eine loesung? mit dem [L]? vielleicht folgendermassen?

RedirectMatch ^/bar(|/.*)$         /foo/bar$1
RewriteRule   ^/foo(/bar(/.*)?)$   $1          [L]

prost
seth

  1. Lieber seth,

    http://www.example.com/bar/... [...]
      http://www.example.com/foo/bar/...

    es soll also noch ein "/foo" eingeschoben werden. die filestruktur auf dem server soll unangetastet bleiben.

    es soll dem Client also der tatsächliche Pfad mit Gewalt vorenthalten werden, intern aber statt des vorgeblichen Pfades tatsächlich benutzt werden.

    also dachte ich da an folgende kombination:

    * redirect von http://www.example.com/bar/(.*) nach http://www.example.com/foo/bar/$1
    * rewrite von http://www.example.com/foo/bar/(.*) nach http://www.example.com/bar/$1

    1. Client fragt mit der realen Pfadangabe nach und bekommt erklärt, diese sei falsch, er solle unter Pfad/foo//Datei nachschauen [redirect].

    2. Client fragt mit der korrigierten Pfadangabe nach und erhält vom Server eine 200er-Antwort. Intern verwedet der Server eine Rewrite-URL, um die "korrigierte" Pfadangabe korrekt aufzulösen.

    RedirectMatch ^/bar(|/.*)$         /foo/bar$1
    RewriteRule   ^/foo(/bar(/.*)?)$   $1          [L]

    Ist das jetzt geraten oder getestet? Wird hier erstens und zweitens vertauscht, oder warum sehe ich nicht, dass der Client in der ersten Zeile einen Redirect ausgehändigt bekommt?

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. gudn tach!

      http://www.example.com/bar/... [...]
        http://www.example.com/foo/bar/...

      es soll also noch ein "/foo" eingeschoben werden. die filestruktur auf dem server soll unangetastet bleiben.

      es soll dem Client also der tatsächliche Pfad mit Gewalt vorenthalten werden, intern aber statt des vorgeblichen Pfades tatsächlich benutzt werden.

      man koennte nun philosophische diskussionen darueber fuehren, was der "tatsaechliche pfad" sei, aber im prinzip: ja, im url soll von nun an das neue "foo" sichtbar sein.
      etwaige alte links (ohne "foo") sollen weiterhin funktionieren. und auf dem server darf die verzeichnisstruktur leider nicht veraendert werden.

      also dachte ich da an folgende kombination:

      * redirect von http://www.example.com/bar/(.*) nach http://www.example.com/foo/bar/$1
      * rewrite von http://www.example.com/foo/bar/(.*) nach http://www.example.com/bar/$1

      1. Client fragt mit der realen Pfadangabe nach und bekommt erklärt, diese sei falsch, er solle unter Pfad/foo//Datei nachschauen [redirect].

      2. Client fragt mit der korrigierten Pfadangabe nach und erhält vom Server eine 200er-Antwort. Intern verwedet der Server eine Rewrite-URL, um die "korrigierte" Pfadangabe korrekt aufzulösen.

      genau. klappt diese kombination vom theoretischen standpunkt aus gesehen? gibt's bessere loesungen?

      RedirectMatch ^/bar(|/.*)$         /foo/bar$1
      RewriteRule   ^/foo(/bar(/.*)?)$   $1          [L]

      Ist das jetzt geraten oder getestet?

      ist geraten und ungetestet. testen kann ich's hier leider nicht; mir geht's hier vor allem um die theorie.

      Wird hier erstens und zweitens vertauscht, oder warum sehe ich nicht, dass der Client in der ersten Zeile einen Redirect ausgehändigt bekommt?

      die beiden zeilen von mir sollten dem entsprechen, was du mit 1. und 2. bezeichnetest. die erste zeile ist der redirect, die zweite zeile der rewrite. wieso sollte in der zweiten zeile noch ein redirect passieren?

      danke fuers antworten! :-)

      prost
      seth

      1. Lieber seth_not@home,

        RedirectMatch ^/bar(|/.*)$         /foo/bar$1

        da wird für den Client (Browser) kein Redirect zur neuen URL gefordert. Laut Dokumentation fehlt da ein [R] dahinter. Sonst versucht nur der Server die alte Adresse intern als neue zu verstehen, die dann in der nächsten Zeile wieder zurückmodifiziert wird - und Du hast Deine von Dir beschriebene Schleife.

        Du müsstest also durch eine passende RewriteCondition dafür sorgen, dass der Request nach der Zeile fertig beantwortet ist.

        RewriteCond %{REQUEST_URI} ^/bar/.*$  
        RewriteRule ^(/bar.*) /foo$1               [R]  
          
        RewriteCond %{REQUEST_URI} ^/foo/bar/.*$  
        RewriteRule ^/foo(/bar.*) ^$1
        

        Obiger Code ist ungetestet, könnte aber aus Versehen so passen.

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. gudn tach!

          RedirectMatch ^/bar(|/.*)$         /foo/bar$1

          da wird für den Client (Browser) kein Redirect zur neuen URL gefordert. Laut Dokumentation fehlt da ein [R] dahinter.

          hmm, entweder steh ich auf dem schlauch oder du hast dich verlesen.
          du hast ja jetzt die erste zeile von mir zitiert und da handelt es sich ja nicht um einen rewrite, sondern um einen redirect, und bei "RedirectMatch" gibt's meines wissens nicht die flags, die es bei rewrites gibt (also [R], [L], [PT], etc.). "[R]" ist ja nur bei rewrites sinnvoll, um jene als redirects zu benutzen. bei zeilen, die an sich schon redirects sind, waere das [R] ja ueberfluessig (und vermutlich sogar ein syntaxfehler). oder nicht?

          Sonst versucht nur der Server die alte Adresse intern als neue zu verstehen, die dann in der nächsten Zeile wieder zurückmodifiziert wird - und Du hast Deine von Dir beschriebene Schleife.

          die haette ich (so war zumindest mein plan und gedanke) nur, wenn ich zwei rewrites oder zwei redirects verwenden wuerde.

          Du müsstest also durch eine passende RewriteCondition dafür sorgen, dass der Request nach der Zeile fertig beantwortet ist.

          RewriteCond %{REQUEST_URI} ^/bar/.*$

          RewriteRule ^(/bar.*) /foo$1               [R]

          RewriteCond %{REQUEST_URI} ^/foo/bar/.$
          RewriteRule ^/foo(/bar.
          ) ^$1

          
          >   
          > Obiger Code ist ungetestet, könnte aber aus Versehen so passen.  
            
          ah, ok, richtig. mit der condition kaeme ich um das loop-problem wohl ganz gut drumherum. wuerde der code  
            
          ~~~apache
            
          RedirectMatch ^(/bar.*) /foo$1  
            
          RewriteCond %{REQUEST_URI} ^/foo/bar/.*$  
          RewriteRule ^/foo(/bar.*) ^$1  
          
          

          etwa das gleiche tun?
          (dass du andere regexps gewaehlt hast, die mehr matchen, als ich wollte, soll jetzt mal egal sein; ich hatte den relativ komplizierten regexp absichtlich genutzt, um nur "/bar" und "/bar/irgendwas", aber nicht /barirgendwas zu matchen.)

          bei einem redirect wird im gegensatz zu einem rewrite die ganze redirect-rewrite-kette wegen des neuen client-requests von neuem abgearbeitet, oder? falls ja, gilt das fuer "RedirectMatch" genauso wie fuer "RewriteRule ... [R]"?

          prost
          seth

          1. Lieber seth_not@home,

            die erste zeile von mir zitiert und da handelt es sich ja nicht um einen rewrite, sondern um einen redirect, und bei "RedirectMatch" gibt's meines wissens nicht die flags, die es bei rewrites gibt (also [R], [L], [PT], etc.). "[R]" ist ja nur bei rewrites sinnvoll, um jene als redirects zu benutzen. bei zeilen, die an sich schon redirects sind, waere das [R] ja ueberfluessig (und vermutlich sogar ein syntaxfehler). oder nicht?

            hmm, vermutlich hast Du Recht. Ich kannte RedirectMatch vorher noch nicht. Ist das neuer?

            mit der condition kaeme ich um das loop-problem wohl ganz gut drumherum.

            Hoffentlich. Garantieren kann ich Dir das aber nicht.

            bei einem redirect wird im gegensatz zu einem rewrite die ganze redirect-rewrite-kette wegen des neuen client-requests von neuem abgearbeitet, oder? falls ja, gilt das fuer "RedirectMatch" genauso wie fuer "RewriteRule ... [R]"?

            Da bin ich mächtig überfragt. Tut mir leid.

            Liebe Grüße,

            Felix Riesterer.

            --
            ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
            1. Hi,

              hmm, vermutlich hast Du Recht. Ich kannte RedirectMatch vorher noch nicht. Ist das neuer?

              Nicht wirklich. Gibt's mind. schon seit Apache 1.3.

              cu,
              Andreas

              --
              Warum nennt sich Andreas hier MudGuard?
              O o ostern ...
              Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
      2. Tach!

        RedirectMatch ^/bar(|/.*)$         /foo/bar$1
        RewriteRule   ^/foo(/bar(/.*)?)$   $1          [L]
        wieso sollte in der zweiten zeile noch ein redirect passieren?

        Beim Rewriting wird üblicherweise der Request nach dem Umschreiben intern nochmal eingereiht und durchläuft alle Apache-Adressauflösungsmechanismen noch einmal. Das verhindert auch kein L-Flag, denn das sorgt nur bei der aktuellen Auflösung für eine Nichtbeachtung aller folgenden Regeln. Der neue interne Request weiß vom vorhergehenden L nichts.

        Rewrite und Redirect sind zwei eigene Mechanismen im Apachen, die auch nichts voneinander wissen. Man kann beim Rewriting noch mit Umgebungsvariablen tricksen, aber das Redirect ist davon nicht beeindruckbar. Vielleicht musst du bei deiner Lösung die Redirect-Direktiven meiden und alles mit Rewrite machen. Zumindest muss verhindert werden, dass nach dem Rewriten die Redirect-Regeln ausgewertet werden.

        Und dann wäre noch die Frage, welcher Apache vorliegt. Der 2.4er hat mit <If expression> ein mächtiges generelles Werkzeug hinzubekommen.

        dedlfix.

        1. gudn tach dedlfix!

          RedirectMatch ^/bar(|/.*)$         /foo/bar$1
          RewriteRule   ^/foo(/bar(/.*)?)$   $1          [L]
          wieso sollte in der zweiten zeile noch ein redirect passieren?

          Beim Rewriting wird üblicherweise der Request nach dem Umschreiben intern nochmal eingereiht und durchläuft alle Apache-Adressauflösungsmechanismen noch einmal.

          ach so. hmm. dann wuerde aber vielleicht die loesung von Felix wegen der conditions funzen, oder? die variable %{REQUEST_URI} aendert sich bei einem reinen(!) rewrite nicht, bei einem redirect aber schon, richtig?

          Und dann wäre noch die Frage, welcher Apache vorliegt. Der 2.4er hat mit <If expression> ein mächtiges generelles Werkzeug hinzubekommen.

          im zweifel ein aelterer.

          prost
          seth

          1. Tach!

            die variable %{REQUEST_URI} aendert sich bei einem reinen(!) rewrite nicht, bei einem redirect aber schon, richtig?

            Die angefragte URL bleibt dieselbe, die sieht man ja auch letzlich im PHP-Script, zum Beispiel, egal was für eine Umschreibung im Apachen vorgenommen wurde. Bei einem Redirect stellt der Client ja eine neue Anfrage und von der kennt der Apache kein Vorher, also auch keine ehemals angeforderte URL.

            dedlfix.