mod_fastcgi und mod_rewrite

Tja, da hab ich das doch glatt mal ausprobiert mit dem PHP als FastCGI - unter anderem weil ich dann auch gleich ein neueres PHP benutzen könnte. Und was ist? Nix ist. Und zwar gab es ein massives Problem mit modrewrite Regeln. In der .htaccess vom WordPress wird nämlich alles auf die index.php umgeschrieben. Dazu wird der eigentliche Pfad der angesprochen wurde als PATHINFO an die index.php angehängt. Tja, und das PHP flöht dann diese Informationen da wieder raus und macht das richtige.

Aber als ich FastCGI aktiviert hatte, klappte das nicht - das PHP behauptete immer, das kein Input-File übergeben wurde. Also als hätte ich das PHP ohne Parameter aufgerufen. Die WordPress Administration - die mit normalen PHP Files arbeitet - funktionierte wunderbar. Und auch die Rechtegeschichte klappte gut, alles lief unter meinem eigenen User.

Nur die Rewrite-Rules halt nicht - und damit die ganze Site nicht. Ziemlich blöd, das ganze. Vor allem weil ich das nicht vernünftig testen kann ohne meine Hauptsite runterzureissen. Blöd ist auch, das scheinbar suexec die eigentlichen FCGI-Starter in der Document-Root des primären virtuellen Servers sucht - nicht in denen der eigentlichen Virtuellen Server. Macht die ganze Situation etwas unübersichtlich, da die Programme (die Starter sind ja kleine Shellscripte) nicht da liegen, wo die Dateien liegen. Ausser man hat seine virtuellen Server unterhalb des primären virtuellen Servers angelegt - aber das halte ich persönlich für hochgradig schwachsinnig, da man dann unter Umständen durch direkte Pfadangaben über den Default-Server an im virtuellen Server geladenen Perl-Modulen vorbeikommen kann.

Ergo: ein Reinfall. Leider. Ärgerlich. Jetzt muss ich mir irgendwie erstmal eine Testkiste zusammenstellen mit der ich dieses Problem analysieren kann ...

Update: ein bischen Suchen und Wühlen im Netz und ein kurzer Test und ich bin schlauer: PATH_INFO bei PHP als FCGI-Version unter Apache ist kaputt. Scheinbar kriegt PHP den falschen PATHINFO Eintrag geliefert und den falschen SCRIPTNAME. Dadurch findet der Interpreter bei gesetztem PATHINFO einfach schlicht sein Script nicht und nix geht mehr. Jetzt muss ich also weiter suchen, ob es eine Lösung gibt. cgi.fixpathinfo = 1 (was allgemein als Hilfe dafür geboten wird) funktioniert jedenfalls nicht. Aber wenn ich das richtig sehe gibts keine brauchbare Lösung dafür - jedenfalls keine für mich offensichtliche. Mist.

Update 2: Ich hab eine Lösung gefunden. Diese basiert darauf einfach nicht den Apache zu benutzen, sondern den lighttpd - und den Apache nur als transparenten Proxy vorne vor zu stellen. Das geht ganz gut, vor allem wenn ich den Apache stark entkerne und das PHP dort rauswerfe wird er auch deutlich schlanker. Und lighttpd kann unter verschiedenen User-Accounts laufen, dadurch spare ich mir auch das wilde gehacke mit suexec. Allerdings läuft dann pro User ein lighttpd Prozess (lighttpd braucht nur einen Prozess pro Server, da es mit asynchroner Kommunikation arbeitet) und die PHPs toben sich als FastCGI Prozesse aus, nicht als Apache-integrierte Module. Apache selber ist dann nur für rein statische Präsenzen oder Sites mit Perlmodulen zuständig - davon habe ich nämlich noch eine ganze Reihe. Im Moment habe ich da nur eine Spiel-Site laufen, aber vielleicht wird das in den nächsten Tagen umgestellt. Die Methode wie cruft-free URIs produziert werden ist übrigens recht witzig: bei WordPress kann man einfach das index.php als Error-Document eintragen: ErrorDocument 404 /index.php?error=404 wäre der Eintrag in der .htaccess, bei lighttpd gibt es eine äquivalente Eintragung. Dadurch werden automatisch nicht existierende Files (und die cruft-free URIs existieren ja nicht als physikalische Files) auf WordPress umgeleitet. Dort wird dann geguckt ob wirklich keine Daten da sind für die URI und wenn doch was da ist (weil es eine WordPress URI ist), wird einfach der Status zurückgesetzt. Für letzteres musste ich einen kleinen Patch in WordPress einbauen. Dadurch spart man sich die ganzen RewriteRules und kommt mit fast jedem Server zurecht. Und weil jetzt 1:41 ist, geh ich jetzt mal pennen ...

tags: Apache, Sysadmin, Texte

Kai Feb. 23, 2005, 10:04 a.m.

ich weiss nicht, ob das in der letzten version von lighttpd schon drin war, aber ich habe in der mailingliste gelesen, dass bei einem 404 auch wirklich _immer_ ein status 404 gesendet wird.. egal, was man in dem php dokument nachtraeglich setzt oder sonstwie tut.. das waere natuerlich unguenstig, da eine suchmaschine nichts mehr indizieren wuerde.. und manche browser ersetzen serverfehler durch eigene meldungen..

hugo Feb. 23, 2005, 12:14 p.m.

Man kann einfach einen Header "Status: 200 OK" erzeugen, der wird von lighttpd korrekt auf einen Status 200 umgesetzt. Klappt auch mit den anderen Statuswerten. Hatte ich extra mit curl --head ausprobiert, weil ich das von dir beschriebene Problem von anderen Servern kenne. Das ist auch der Patch den ich in WordPress gemacht habe: die haben das explizite Setzen des Status 200 weggelassen, weshalb ErrorDocument-basierte Sites bei WordPress nur mit 404ern ausgeliefert werden ...

Kai Feb. 23, 2005, 5:17 p.m.

achso.. dann hat der programmierer von lighttpd das in der neusten version schon drin, dass man den http status aendern kann.. das ging naemlich vorher nicht.. da wurde der status, egal wie oft und wie konform gesetzt, immer zu einem 404 uebergebuegelt.

Matthias Urlichs Dec. 3, 2005, 6:21 p.m.

Man kann auch das mod_fastcgi hacken. Ist sich häßlich, geht aber.

Der Patch ist hier.