Regina Schlauklug: Mit .htaccess alle Requests von einem Skript abhandeln lassen

Hi,

irgendwie bin ich immer zu doof für .htaccess …

Ich möchte dass alle requests abhängig von der sub-domain von einem perl skript abgehandelt werden. Ich habe folgende Ordnerstruktur und Dateien:

~/html-root
~/html-root/.htaccess
~/html-root/master
~/html-root/master/main.pl

Die main.pl gibt im Moment nur den angeforderten Pfad aus. In der .htaccess steht folgendes:

Options +ExecCGI
AddHandler fcgid-script .pl
RewriteEngine On

RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com$
RewriteCond %1::%{REQUEST_URI} !^(.*?)::/\1/main.pl
RewriteRule ^(.*)$ /%1/main.pl/$1 [L]

Wenn ich nun master.example.com/foobar aufrufe gibt mir mein Perl Skript /foobar aus. Das ist das gewünschte Verhalten.
Wenn ich aber master.example.com/master/main.pl aufrufe gibt mir mein Perl Skript einen Leerstring aus. Das ist meinem Verständnis nach weil ich Requests an /master/main.pl eben nicht an /master/main.pl/$1 weiterleite. Wenn ich sie aber weiterleite habe ich eine Endlosschleife.

Wie kann ich das beheben?

  1. ...

    RewriteRule !\.(zip|cgi|css|jpg|js|gif|ico|txt|pac|png|appcache|htm|bin|pdf|nph)$ /cgi-bin/fwdbf.cgi [L]
    

    PS: Markdown ist mächtig, aber für ein Forum völlig ungeeignet. So get Forum

    1. Ich muss sagen ich kann mit deiner Antwort gerade wenig anfangen.

      Die von dir vorgeschlagene RewriteRule würde master.example.com/foo.jpg nicht an mein Perl Skript weiterreichen, oder?

      Zudem, warum an /cgi-bin/fwdbf.cgi? Wenn dann müsste das doch /fcgi-bin/… sein, oder? Zudem habe ich das Perl Skript eben nicht in diesem Ordner.

      1. Ich muss sagen ich kann mit deiner Antwort gerade wenig anfangen.

        Die von dir vorgeschlagene RewriteRule würde master.example.com/foo.jpg nicht an mein Perl Skript weiterreichen, oder?

        Nuja, zu einer solchen Regel, die ich mir von Magento abgeschaut habe, gehört eine Routingtable RT. Steht in der RT der URL /foo.jpg so ist das Script für die Auslieferung zuständig. Ansonsten guckt der Webserver ob es eine Datei DOCUMENT_ROOT/foo.jpg gibt. Wenn nicht, schmeißt der Webserver einen 404.

        Zudem, warum an /cgi-bin/fwdbf.cgi? Wenn dann müsste das doch /fcgi-bin/… sein, oder? Zudem habe ich das Perl Skript eben nicht in diesem Ordner.

        Als FastCGI: ModRewrite plus Servereintrag in Apache httpd.conf

        # framework fastcgi
        <VirtualHost 127.0.0.1:80>
            ServerName framework
        
            <Directory d:/home/framework/html>
                AllowOverride all   
                Order allow,deny
                Allow from all
                AddHandler fastcgi-script .fastcgi
            </Directory>
        
        
            FastCgiServer d:/home/framework/html/cgi-bin/fwng.fastcgi -processes 1
        
            DocumentRoot d:/home/framework/html
            ScriptAlias /cgi-bin/ d:/home/framework/html/cgi-bin/
        
        </VirtualHost>
        

        Als FastCGI flink wie ein Windhund und in mod_perl hab ich das auch, mein geliebtes Framework ;)

        Bei Interesse, melde Dich.

        1. Nuja, zu einer solchen Regel, die ich mir von Magento abgeschaut habe, gehört eine Routingtable RT. Steht in der RT der URL /foo.jpg so ist das Script für die Auslieferung zuständig. Ansonsten guckt der Webserver ob es eine Datei DOCUMENT_ROOT/foo.jpg gibt. Wenn nicht, schmeißt der Webserver einen 404.

          Ich will alle Request an mein Skript weiterreichen. Nicht schauen ob die Datei existiert. Nicht schauen ob irgendwelche Dateiendungen oder Pfade irgendwelchen Kriterien entsprechen. Alles an mein Skript.

          Als FastCGI: ModRewrite plus Servereintrag in Apache httpd.conf

          # framework fastcgi
          <VirtualHost 127.0.0.1:80>
          …
          
          </VirtualHost>
          

          Ich habe in der .htaccess einen entsprechenden Eintrag, dass mein Skript richtig ausgeführt wird.
          Ich verstehe leider wieder nicht inwiefern mir das in die httpd.conf zu verlagern irgendwie bei meinem Problem hilft alle Requests an mein Skript weiterzugeben?

          1. Alles an mein Skript.

            Wie bereits festgestellt: RewriteRule + RoutingTable

            Also Beides zusammen. Der entscheidende Vortei FastCGI gegenüber reinem CGI-Betrieb liegt darin, dass die RoutingTable permanent im Hauptspeicher liegt. Und bei Jedem Request wird der Hauptspeicher weiter angereichert mit Code und Templates. Also: Eine Seite einmal requestet, bleibt danach das Template im Hauptspeicher. Jedenfalls macht das mein Framework so und genau deswegen ist es auch so performant, insbesondere als FastCGI: Je mehr Requests, desto schneller wird es.

            Persistente DB-Verbindungen inklusive. Nachdenken lohnt sich gelegentlich ;)

            1. Das heißt deine Lösung für mein Problem ist: Dein Framework verwenden?

              Irgendwie glaube ich stehe ich da gerade auf dem Schlauch. Was muss ich jetzt konkret in meiner .htaccess haben um alle Requests an mein Skript weiter zu reichen?

              1. Was an meiner RewriteRule, die im Ausschlussverfahren alles an einen ScriptAlias leitet, hast Du nicht verstanden?

                1. Wie damit Requests an z.B. /foo.jpg an mein Skript weitergegeben werden.

                  Wenn ich das richtig verstehe würde bei diesem Request versucht die Datei ~/html-root/foo.jpg auszuliefern, richtig?

                  1. Wie damit Requests an z.B. /foo.jpg an mein Skript weitergegeben werden.

                    Wenn ich das richtig verstehe würde bei diesem Request versucht die Datei ~/html-root/foo.jpg auszuliefern, richtig?

                    Je nach Konfiguration. Guck einfach mal Hier: http://handwerkzeugs.de/foo.jpg

                    Der Trick: Apache-ErrorDocument 404 und RewriteRule zeigen auf dasselbe Script. In meinem Fall die 'main' vom Framework.

                    Multiple Domains: http://handwerkzeugs.de und http://rolfrost.de laufen über einunddasselbe Script und nutzen gemeinsame Libraries.

                    Der Trick: Apache-ScriptAlias und der funktioniert selbstverständlich auch mit Subdomains. Bedingung ist, dass die Dateien auf der gleichen Maschine liegen. Selbstverständlich kriegt eine andere Domain auch eine andere RoutingTable.

                    Tags: Apache, rewrite, ScriptAlias, RoutingTable, .htaccess, ErrorDocument

                    1. Wie damit Requests an z.B. /foo.jpg an mein Skript weitergegeben werden.

                      Wenn ich das richtig verstehe würde bei diesem Request versucht die Datei ~/html-root/foo.jpg auszuliefern, richtig?

                      Je nach Konfiguration. Guck einfach mal Hier: http://handwerkzeugs.de/foo.jpg

                      Wenn die Datei existieren würde, würde sie aber ausgeliefert, und nicht das Skript aufgerufen. Richtig?
                      Das will ich nämlich nicht.

                      1. Wie damit Requests an z.B. /foo.jpg an mein Skript weitergegeben werden.

                        Wenn ich das richtig verstehe würde bei diesem Request versucht die Datei ~/html-root/foo.jpg auszuliefern, richtig?

                        Je nach Konfiguration. Guck einfach mal Hier: http://handwerkzeugs.de/foo.jpg

                        Wenn die Datei existieren würde, würde sie aber ausgeliefert, und nicht das Skript aufgerufen. Richtig?
                        Das will ich nämlich nicht.

                        Kein Problem, entferne jpg aus der von mir gezeigten Regel. Konfigurieren kannste alles, machs einfach mal. Also einfach mal machen und hier nich zum Vielposter werden. afür die Posts der Anderen maln bischen besser lesen. Und ich mach jetzt Schluss für heute, bin Rentner und muss morgen früh raus.

                        --
                        Merke: Wer früh pinkeln will, muss früh aufstehen.
  2. Moin!

    Warum eigentlich so kompliziert?

    Würde:

         RewriteRule ^(.*)$ /main.pl?route=$1 [L]
    

    nicht völlig ausreichen?

    Jörg Reinholz

    1. Hi,

      das berücksichtigt die sub-domain nicht.

      Später wird es neben dem Verzeichnis master noch weitere geben, die über entsprechend dem Verzeichnis gleichlautende sub-domain erreichbar sein sollen.

      1. Hi,

        das berücksichtigt die sub-domain nicht.

        Arg, Du wirst das doch nicht über Rewrite in einer htaccess regeln wollen!? Tues nicht. Regele das besser über die RoutingTable in Verbindung mit einem SciptAlias.

        1. Arg, Du wirst das doch nicht über Rewrite in einer htaccess regeln wollen!? Tues nicht. Regele das besser über die RoutingTable in Verbindung mit einem SciptAlias.

          Arg, doch will ich. Was spricht denn dagegen?

          1. Moin!

            das berücksichtigt die sub-domain nicht.

            Arg, Du wirst das doch nicht über Rewrite in einer htaccess regeln wollen!? Tues nicht. Regele das besser über die RoutingTable in Verbindung mit einem SciptAlias.

            Arg, doch will ich. Was spricht denn dagegen?

            Der Regex ist teurer als eine Umgebungsvariable zu fragen: $ENV{'SERVER_NAME'}

            Jörg Reinholz

  3. Tach!

    RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com$
    RewriteCond %1::%{REQUEST_URI} !^(.*?)::/\1/main.pl
    RewriteRule ^(.*)$ /%1/main.pl/$1 [L]
    

    Die erste Cond ist also nur da, um die Subdomain als Backreferenz zu erhalten. Die zweite hat anscheinend einen Fehler, weil da statt \1 wohl %1 stehen sollte. Aber an der Stelle muss doch gar nicht großartig die Subdomain hinzuverknotet werden, wenn du sie sowieso nur auf .* vergleichst. Es sollte reichen, %{REQUEST_URI} auf !^/%1/main.pl zu prüfen. Andererseits solltest du diese Regel auch weglassen und stattdessen auf existierende Dateien und Verzeichnisse prüfen können, also

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    

    Oder hast du einen Anwendungsfall, auch existierende Dateien (außer den main.pl) umzuschreiben?

    dedlfix.

    1. Hi,

      ursprünglich hatte ich mal diese Regel:

      RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com$
      RewriteRule ^(.*)$ /%1/main.pl/$1 [L]
      

      Das hat bei mir aber auch eine Endlosschleife verursacht. Ich werde das später heute Abend nochmal testen ob ich da evtl. einfach etwas anderes falsch hatte.

      Oder hast du einen Anwendungsfall, auch existierende Dateien (außer den main.pl) umzuschreiben?

      Statische Dateien werden im Ordner ~/html-root/master/static/ abgelegt und sollen über die sub-sub-domain static.master.example.com/… erreichbar sein. Nicht über master.example.com/master/static/….

      1. Tach!

        ursprünglich hatte ich mal diese Regel:

        RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com$
        RewriteRule ^(.*)$ /%1/main.pl/$1 [L]
        

        Das hat bei mir aber auch eine Endlosschleife verursacht.

        Ja, weil nach dem Rewriting der Request nochmal an die interne Verarbeitung geschickt wird und wieder an dieser Regel vorbeikommt und sie auch wieder passt. Deswegen schließt man existierende Dateien und Verzeichnisse aus, denn dann passt die Regel nicht mehr und das Rewriting findet keinen Grund mehr, die Verarbeitung noch eine Runde drehen zu lassen.

        Oder hast du einen Anwendungsfall, auch existierende Dateien (außer den main.pl) umzuschreiben?

        Statische Dateien werden im Ordner ~/html-root/master/static/ abgelegt und sollen über die sub-sub-domain static.master.example.com/… erreichbar sein. Nicht über master.example.com/master/static/….

        Ist es denn ein Fehler, wenn jemand zufällig das Verzeichnis kennt und die Dateien auf diese Weise aufruft, anstatt über die Subdomain zu gehen? Du kannst ja in deiner Anwendung die URLS in der Subdomain-Variante formulieren nehmen und ansonsten ignorieren, dass die in dem Verzeichnis liegen. Das sollte doch keine negativen Auswirkungen auf irgendwas haben. Jedenfalls sehe ich keinen wirklichen Grund auf die -d/-f-Conditions zu verzichten.

        dedlfix.

        1. Das Ganze rewriting hier ist kosmetischer Natur. Natürlich kann ich meine Requests auch einfach an example.com/master/main.pl/… schicken und Requests auf example.com/master/static/… entsprechend die Datei zurück liefern.

          Anders fände ich es schöner. Und ich hatte gedacht dass das mit .htaccess relativ einfach gehen sollte und ich nur zu doof dafür war.

          Scheinbar geht es aber nicht. Dann mach ich das halt anders.