Werner: Apache-Rewrite und PHP-Zugriff auf vorige URL

Hallo,

ich leite auf meiner Webseite sämtliche fehlerhaft eingegebenen URLs, (=zu denen es keine entsprechende Datei gibt) auf die Indexdatei index.php um.

Ich habe das mittels rewrite in der .htaccess gelöst, was wie gewünscht funktioniert:

  
  RewriteEngine on  
  RewriteCond %{REQUEST_FILENAME} !-f  
  RewriteRule .*   /index.php [R=301]  

Nun will ich in der index.php noch die fehlerhaft eingegebene URL auswerten (mittels $_SERVER["REQUEST_URI"]).
Durch den rewrite ging die ursprüngliche URL aber verloren und in $_SERVER["REQUEST_URI"] befindet sich schon die URL, zu der weitergeleitet wurde ("index.php")

Frage: hat ein Profi eine Idee, wie ich das Ganze zum Zusammenspiel bringen kann?

  1. Hi,

    ich leite auf meiner Webseite sämtliche fehlerhaft eingegebenen URLs, (=zu denen es keine entsprechende Datei gibt) auf die Indexdatei index.php um.

    Das klingt, als wolltest Du eher das ErrorDocument für 404 definieren.

    RewriteEngine on
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule .*   /index.php [R=301]

      
    Du machst hier einen Redirect, keinen Rewrite ...  
      
    cu,  
    Andreas
    
    -- 
    [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
    [O o ostern ...](http://ostereier.andreas-waechter.de/)  
      
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
    
    
    1. Hallo,

      dankschön für die bisherigen Antworten. Ich bin bei kein Server-Experte und habe selten bis nie mit Apache rewrites bzw. redirects zu tun gehabt.
      Bin aber gerne bereit mich anhand eurer Tipps für mein spezifisches Anliegen ein bissl schlauer zu machen ;-)

      Also individuelle Errordocuments lässt mein Webhoster leider nicht zu. Bleibt mir nur eine Lösung mittels anderer .htaccess "Kniffe".

      Mein Wunsch:

      wenn jemand "www.meinedomain.com/nichtvorhandes.htm" eingibt, soll anschließend die Datei "www.meinedomain.com/index.php" in seinem Browser erscheinen.
      Sinnvoll wäre daher natürlich wenn in seiner Adressleiste dann auch das nun richtige "www.meinedomain.com/index.php" erscheinen würde.

      Dies alles funktioniert derzeit zufriedenstellend!

      Allerdings will ich nun in der index.php die zuvor eingegebene URL "www.meinedomain.com/nichtvorhandes.htm" oder zumindest "nichtvorhandes.htm" weiterverarbeiten.

      Und da fehlt mir die einfach die Erfahrung von euch Experten wie ich das nun am besten machen kann - ist dies überhaupt gemeinsam möglich?

      1. Hi,

        Also individuelle Errordocuments lässt mein Webhoster leider nicht zu.

        das spricht nicht gerade für den Hoster. :-(

        wenn jemand "www.meinedomain.com/nichtvorhandes.htm" eingibt, soll anschließend die Datei "www.meinedomain.com/index.php" in seinem Browser erscheinen.

        Bitte verwende für Beispiele nicht wahllos irgendwelche existierenden Domains, sondern eine von denen, die extra dafür vorgesehen sind.

        Sinnvoll wäre daher natürlich wenn in seiner Adressleiste dann auch das nun richtige "www.meinedomain.com/index.php" erscheinen würde.

        Das ist aber ein Widerspruch zu deiner zweiten Forderung:

        Allerdings will ich nun in der index.php die zuvor eingegebene URL "www.meinedomain.com/nichtvorhandes.htm" oder zumindest "nichtvorhandes.htm" weiterverarbeiten.

        Der erste Request (der auf /nichtvorhandenes.htm) ist Geschichte. Den hast du ja mit einem Redirect beantwortet. Der zweite Request (auf /index.php) ist technisch gesehen komplett unabhängig davon.

        Und da fehlt mir die einfach die Erfahrung von euch Experten wie ich das nun am besten machen kann - ist dies überhaupt gemeinsam möglich?

        Soweit ich das überblicken kann, nein. Ich lasse mich aber gern vom Gegenteil überzeugen.

        Ciao,
         Martin

        --
        PCMCIA: People Can't Memorize Computer Industry Acronyms
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Hi,

          Allerdings will ich nun in der index.php die zuvor eingegebene URL "www.meinedomain.com/nichtvorhandes.htm" oder zumindest "nichtvorhandes.htm" weiterverarbeiten.

          [...]

          Soweit ich das überblicken kann, nein. Ich lasse mich aber gern vom Gegenteil überzeugen.

          Mit ErrorDocument könnte man sowas hinkriegen:
          Der ursprüngliche Request wird per ErrorDocument auf ein error-Script gelenkt.
          Dieses error-Script gibt, falls die aufgerufene URL nicht direkt die des error-Scripts ist (bzw. der Return-Status noch 404 ist - falls das abfragbar ist), einen Redirect auf die tatsächliche Url des error-Scripts aus, mit der ursprünglichen URL als Parameter (entsprechend escaped natürlich)

          Aber ErrorDocument kann Werner ja laut seiner Aussage nicht einsetzen ...

          cu,
          Andreas

          --
          Warum nennt sich Andreas hier MudGuard?
          O o ostern ...
          Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
          1. Danke für alle Tips, hab mich dadurch in letzter Zeit ein bischen mit Firefox-Live HTTP headers, diversen .htaccess Direktiven herumgespielt und die ein- oder andere Apache-Dokuseite überflogen ;-)

            Letzendlich habt ihr eh alle Optionen genannt die es diesbezüglich geben würde.
            Es wäre noch "die relativ neue" Apache-Direktive "FallbackResource" zu nennen, die bei falschen URLs einen internen Rewrite auf eine Fallbackdatei macht.

            Ich benutze jetzt diesen internen Apache-Fallback auf eine fallback.php
            Dadurch wird auch [REQUEST_URI] der fehlerhaften URL ans Skript ausgeliefert. Dort verarbeitet das Skript alle Infos und redirected schließlich per
            header ("Location: /index.php")
            auf die anzuzeigende Indexdatei, welche nun auch so richtig in der Browseradressleiste steht.

            Somit hab ich die richtige URL der Indexseite und ohne Fehler-Querystring im Adressfeld stehen.

            1. Hallo,

              fallback.php [...] und redirected schließlich per
              header ("Location: /index.php")
              auf die anzuzeigende Indexdatei, welche nun auch so richtig in der Browseradressleiste steht.

              wenn du es jetzt noch ein bisschen besser machen möchtest, dann ergänzt du den Pfad im Location-Header noch um Protokoll und Hostnamen. Die HTTP-Spezifikation verlangt an der Stelle nämlich eine vollständige, absolute Adresse.

              Erfahrungsgemäß kommen die gängigen Browser zwar auch mit unvollständigen oder relativen URLs zurecht, müssen sie aber nicht. Für den IE hat vor langer Zeit mal jemand ein Beispiel konstruiert, wo der nicht mehr mitspielt.

              Somit hab ich die richtige URL der Indexseite und ohne Fehler-Querystring im Adressfeld stehen.

              Je nachdem, welchen Zweck die ganze Aktion erfüllen soll, finde ich das immer noch nicht ganz okay. Wenn es den 404er-Fehler abfangen soll, wäre es IMO anständiger, die ursprüngliche (falsche) URL stehenzulassen (was beim internen Rewriting oder auch beim ErrorDocument passieren würde), so dass man als Nutzer noch sehen kann, _was_ man da falsch eingegeben hat.
              Wenn das Nicht-Vorhandensein einer Ressource aber durch deinen Eingriff passiert ist, etwa durch eine Umstrukturierung der Site, dann mag das Umleiten, so wie du es jetzt machst, in Ordnung sein. Noch schöner wäre natürlich, wenn du dann nicht auf /index.php leiten würdest, sondern dorthin, wo der Nutzer jetzt nach dem Umbau das findet, was er ursprünglich gesucht hat.

              So long,
               Martin

              --
              Man gewöhnt sich an allem, sogar am Dativ.
              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      2. Allerdings will ich nun in der index.php die zuvor eingegebene URL "www.meinedomain.com/nichtvorhandes.htm" oder zumindest "nichtvorhandes.htm" weiterverarbeiten.

        Und da fehlt mir die einfach die Erfahrung von euch Experten wie ich das nun am besten machen kann - ist dies überhaupt gemeinsam möglich?

        Dann schreib doch mal

        <pre>
        <?php print_r($_SERVER); ?>
        </pre>

        oder auch nur

        <?php phpinfo(); ?>

        in die index.php. Beides ist sehr erhellend, denn die Lösung wird dann augenscheinlich:$_SERVER['REQUEST_URI']  enhält, was Du suchst.

        Das gilt natürlich nur, wenn Deine .htacces wie folgt aussieht:

        RewriteEngine on  
        RewriteCond %{REQUEST_FILENAME} !-f  
        RewriteCond %{REQUEST_FILENAME} !-d  
        RewriteRule .*   /index.php [L]
        

        Zum Zwecke des Testens kannst Du statt der index.php gerne erst mal eine test.php benutzen.

        Du kannst weiter schauen, ob Dein Server in dem Fall auch

        $_SERVER['REDIRECT_URL']  
        $_SERVER['REDIRECT_UNIQUE_ID']  
        $_SERVER['REDIRECT_REQUEST_METHOD']  
        $_SERVER['REDIRECT_STATUS']
        

        setzt.

        Jörg Reinholz

      3. Sinnvoll wäre daher natürlich wenn in seiner Adressleiste dann auch das nun richtige "www.meinedomain.com/index.php" erscheinen würde.

        ok... Ich habe das jetzt NATÜRLICH NICHT durchgetestet. Die folgenden Beispiele können also kleine Fehler enthalten.

        =====================================================
        Variante 1 mit unsichtbarer, falscher URL und SESSION:

        Schritt 1 (.htaccess, Anweisung, den Request mit /ERR404.php abarbeiten):

        RewriteEngine on  
        #####################################  
        ## Nach allen anderen Umleitungen! ##  
        #####################################  
        RewriteCond %{REQUEST_FILENAME} !-f  
        RewriteCond %{REQUEST_FILENAME} !-d  
        RewriteRule .*   /ERR404.php [L]  
        
        

        Schritt 2: (ERR404.php) Variante 1:
        ----------------------------------

        <?php  
           session_start();  
           $_SESSION['REDIRECT_URL']=$_SERVER['REDIRECT_URL'];  
           # was immer Du noch willst, aber keine Ausgaben!  
          
           # Abschließende Weiterleitung  
           header('Location: http://' . $_SERVER['SERVER_NAME'] . '/index.php');  
        
        

        ----------------------------------

        Schritt 3: (index.php): Variante 1:

        <?php  
        # Vorher keine Ausgaben senden:  
        session_start();  
        # was immer Du noch willst  
        if ( isset($_SESSION['REDIRECT_URL']) ) {  
            # was immer Du noch willst  
            # $_SESSION['REDIRECT_URL'] enthält, was Du suchst  
          
            # Löschen, damit die Info beim nächsten Aufruf weg ist:  
            unset($_SESSION['REDIRECT_URL']);  
            # oder sogar: Vollständiges Löschen der gesamten Session in 3 Schritten:  
          
            # // a) Löschen aller Session-Variablen.  
            # $_SESSION = array();  
          
            # // b) Session-Cookie.  
            # if (ini_get("session.use_cookies")) {  
            #     $params = session_get_cookie_params();  
            #     setcookie(session_name(), '', time() - 42000, $params["path"],  
            #         $params["domain"], $params["secure"], $params["httponly"]  
            #     );  
            # }  
          
            # // c) Löschen der Session auf dem Server:  
            # session_destroy();  
          
        }
        

        =====================================================
        Variante 2 mit unsichtbarer, falscher URL und Cookie:

        Schritt 1 (.htaccess, Anweisung, den Request mit /ERR404.php abarbeiten):

        RewriteEngine on  
        #####################################  
        ## Nach allen anderen Umleitungen! ##  
        #####################################  
        RewriteCond %{REQUEST_FILENAME} !-f  
        RewriteCond %{REQUEST_FILENAME} !-d  
        RewriteRule .*   /ERR404.php [L]  
        
        

        Schritt 2: (ERR404.php) Variante 1:
        ----------------------------------

        <?php  
           $_COOKIE['REDIRECT_URL']=$_SERVER['REDIRECT_URL'];  
           # was immer Du noch willst, aber keine Ausgaben!  
           # Abschließende Weiterleitung  
           header('Location: http://' . $_SERVER['SERVER_NAME'] . '/index.php');  
        
        

        ----------------------------------

        Schritt 3: (index.php): Variante 1:

        <?php  
        # Vorher keine Ausgaben senden:  
        # was immer Du noch willst  
        if ( isset($_COOKIE['REDIRECT_URL']) ) {  
            # was immer Du noch willst  
            # $_COOKIE['REDIRECT_URL'] enthält, was Du suchst  
            # Cookie löschen, damit die Info beim nächsten Aufruf weg ist:  
            setcookie ('REDIRECT_URL', '', time() - 3600);  
        }
        

        =====================================================
        Variante 3 mit sichtbarer falscher URL

        Schritt 1 (.htaccess, Anweisung, den Request mit /index.php abarbeiten):

        RewriteEngine on  
        #####################################  
        ## Nach allen anderen Umleitungen! ##  
        #####################################  
        RewriteCond %{REQUEST_FILENAME} !-f  
        RewriteCond %{REQUEST_FILENAME} !-d  
        RewriteRule ^(.*)$   /index.php?Err=$1 [L,R=301] # wenn permanent - sonst 302!  
        
        

        Schritt 2: (index.php)
        ----------------------------------

        <?php  
           if ( isset($_GET['Err']) ) {  
               #was immer Du dann tun willst, wenn wegen der  
               #nicht existierenden Ressource umgeleitet wurde  
           }?>  
        
        

        Jede dieser Varianten hat Vor- und Nachteile. 1 und 2 bedingen Cookies und eine etwas höhere Serverlast (auch das Session-Cookie ist eines) bei Variante 3 bleibt der vorherige Request dennoch als Teil der URL sichtbar. Wenn Du nichts davon willst verzichte auf die Forderung.

        Jörg Reinholz

  2. Hi,

    ich leite auf meiner Webseite sämtliche fehlerhaft eingegebenen URLs, (=zu denen es keine entsprechende Datei gibt) auf die Indexdatei index.php um.

    warum das? Da wäre es einfacher und sinnvoller, ein 404-ErrorDocument festzulegen.

    RewriteEngine on

    RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule .*   /index.php [R=301]

      
    Was bringt dich auf die Idee, Apache-Code als Perl zu taggen?  
    Außerdem machst du hier kein Rewriting, sondern eine Umleitung, wie Andreas schon erwähnt hat. Du weist also den Client (Browser) an: Was du eigentlich willst, holst du dir bitte woanders ab. Der Client setzt daraufhin einen neue Request ab und holt sich die Ressource, die ihm empfohlen wurde. Vom vorherigen Request, der ja erfolglos beendet wurde, ist dann natürlich nichts mehr verfügbar.  
      
    Deine Redirect-Lösung hat außerdem noch einen entscheidenden Nachteil für den Nutzer: Nach der Umleitung sieht er in der Browser-Adresszeile die URL des neuen Requests auf http://example.org/index.php anstatt des ursprünglich eingegebenen Ziels.  
      
    
    > Frage: hat ein Profi eine Idee, wie ich das Ganze zum Zusammenspiel bringen kann?  
      
    Ja. Nutze [ErrorDocument](http://httpd.apache.org/docs/2.2/mod/core.html#errordocument). Und gib da bitte einen lokalen Pfad an, keine HTTP-URL - sonst hast du nämlich doch wieder einen Redirect und bist keinen Schritt weiter als vorher.  
      
    So long,  
     Martin  
    
    -- 
    Wer keiner Fliege etwas zuleide tut, darf sich nicht über die Maden im Fleisch wundern.  
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    
    1. warum das? Da wäre es einfacher und sinnvoller, ein 404-ErrorDocument festzulegen.

      Das habe ich neulich auch mal versucht:

      ErrorDocument 404 /index.php

      Ich wollte damit allen Ernstes eine Menge Rewrite-Regeln "erschlagen". Problem: Der Apache ließ sich jedenfalls von mir nicht überzeugen den "404er" NICHT zu senden. Wenn jemand dazu (also mit ErrorDocument 404 einen effektiven Rat hat: her damit.

      Möglich wäre, dass der TO genau das Problem auch hat. Also wäre ihm mit etwas wie:

      RewriteEngine on  
      RewriteCond %{REQUEST_FILENAME} !-f  
      RewriteRule .*   /test.php [L]
      

      womöglich besser geholfen.

      Natürlich müsste dann in Abhängigkeit von den Wünschen der "404er" via header('HTTP/1.1 404') gesendet werden.

      Jörg Reinholz

      1. Hallo,

        warum das? Da wäre es einfacher und sinnvoller, ein 404-ErrorDocument festzulegen.

        Das habe ich neulich auch mal versucht:
        ErrorDocument 404 /index.php

        Ich wollte damit allen Ernstes eine Menge Rewrite-Regeln "erschlagen". Problem: Der Apache ließ sich jedenfalls von mir nicht überzeugen den "404er" NICHT zu senden.

        okay, aber *das* wäre dann IMO wieder ein Missbrauch des ErrorDocument. Bei der Fragestellung von Werner, insbesondere der Formulierung "fehlerhaft eingegebenen URLs", gehe ich davon aus, dass er eigentlich einen 404er-Status senden will. Zumindest denke ich, er sollte das wollen. ;-)

        Davon abgesehen: Ich hab's nie versucht, aber hilft es tatsächlich nicht, den Default-Status 404 explizit mit einem "HTTP/1.1 200 OK" zu überschreiben?

        RewriteEngine on

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule .*   /test.php [L]

          
        Halte ich immer noch nicht für die optimale Lösung, aber wenn, dann möchte man eventuell noch eine Zeile ergänzen:  
          
        
        > ~~~apache
        
        RewriteEngine on  
        
        > RewriteCond %{REQUEST_FILENAME} !-f  
        > RewriteCond %{REQUEST_FILENAME} !-d  
        > RewriteRule .*   /test.php [L]
        
        

        Sonst lässt sich das Default-Dokument in einem Verzeichnis nicht mehr aufrufen, ohne es ausdrücklich zu adressieren.

        Natürlich müsste dann in Abhängigkeit von den Wünschen der "404er" via header('HTTP/1.1 404') gesendet werden.

        Hmm. Kommt mir vor, als ob da jemand krampfhaft versucht, einer Gurke mit künstlichen Aromastoffen den Geschmack von Pfirsich zu geben ...

        Ciao,
         Martin

        --
        Der Professor sitzt beim Essen in der Mensa. Ein Student setzt sich ihm unaufgefordert gegenüber.
        Professor: Seit wann essen denn Schwein und Adler an demselben Tisch?
        Student:   Na gut, dann flieg' ich eben zum nächsten Tisch.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Tach!

          Davon abgesehen: Ich hab's nie versucht, aber hilft es tatsächlich nicht, den Default-Status 404 explizit mit einem "HTTP/1.1 200 OK" zu überschreiben?

          Es hilft, jedenfalls in der Modul-Variante von PHP. Besser ist aber:

          header($_SERVER['SERVER_PROTOCOL'] . " 200 OK");

          Für (F)CGI muss man einen anderen Header nehmen:

          header("Status: 200 OK");

          dedlfix.

          1. header("Status: 200 OK");

            Shit! Alles klar. PHP läuft auf dem Host als CGI. Das geht also doch.

            Frage:

            Wäre etwas wie ...

            <?php  
            if ( false !==strpos(PHP_SAPI,'cgi') ) {  
                 header('STATUS: 200 OK');  
            } else {  
                header($_SERVER['SERVER_PROTOCOL'] . " 200 OK");  
            }  
            ?>
            

            als "API-Weiche" gut genug? Funktioniert hat es...

            Jörg Reinholz

        2. ErrorDocument 404 /index.php

          Ich wollte damit allen Ernstes eine Menge Rewrite-Regeln "erschlagen". Problem: Der Apache ließ sich jedenfalls von mir nicht überzeugen den "404er" NICHT zu senden.

          okay, aber *das* wäre dann IMO wieder ein Missbrauch des ErrorDocument. Bei der Fragestellung von Werner, insbesondere der Formulierung "fehlerhaft eingegebenen URLs", gehe ich davon aus, dass er eigentlich einen 404er-Status senden will. Zumindest denke ich, er sollte das wollen. ;-)

          Davon abgesehen: Ich hab's nie versucht, aber hilft es tatsächlich nicht, den Default-Status 404 explizit mit einem "HTTP/1.1 200 OK" zu überschreiben?

          Meine ziemlich ernst gemeinten Versuche haben ergeben, dass genau das nicht geht.

          RewriteEngine on

          RewriteCond %{REQUEST_FILENAME} !-f
            RewriteCond %{REQUEST_FILENAME} !-d
          RewriteRule .*   /test.php [L]

            
          
          > Sonst lässt sich das Default-Dokument in einem Verzeichnis nicht mehr aufrufen, ohne es ausdrücklich zu adressieren.  
            
          Nice. Danke.  
            
          
          > > Natürlich müsste dann in Abhängigkeit von den Wünschen der "404er" via header('HTTP/1.1 404') gesendet werden.  
          >   
          > Hmm. Kommt mir vor, als ob da jemand krampfhaft versucht, einer Gurke mit künstlichen Aromastoffen den Geschmack von Pfirsich zu geben ...  
            
          Jein. Es kann ja sein, dass zu einer Abfrage keine passenden Daten da sind. So kann man z.B. versuchen die Suchmaschinen zu überreden, alte, aus Datenbeständen erzeugte, (quasi-)statische Seiten zu vergessen. Ist natürlich "SEO-Kram".  
            
          [Jörg Reinholz](http://www.fastix.org)  
          
          
  3. Du kannst den Dateinamen als Parameter übergeben:

      
      RewriteRule (.*)   /index.php?redirect=$1 [R=301]  
    
    

    Die ursprüngliche URL liegt dann in $_GET['redirect'].

    Allen einen schönen Tag!

    danger