Lighttpd, mod_rewrite und die htaccess

Lighttpd Logo

Eins der wohl häufigsten Probleme bei der Umstellung von Apache auf Lighttpd ist sicherlich die Migration der htaccess Dateien. Grund dafür ist, dass (zumindest bis vor kurzem) das mod_rewrite Modul des Lighttpd nicht prüfen konnte ob eine Datei existiert und die Rewrite-Regeln somit immer angewendet wurden. Dieses Problem konnte man durch die Verwendung von mod_magnet und LUA zwar umgehen allerdings müssen dann alle rewrite-Regeln in LUA neu geschrieben werden, was nicht immer ganz trivial ist.

Auch ich stand vor diesem Problem bis ich in der mod_rewrite Doku des Lighttpd folgedes entdeckte:

New: For the 1.4.x branch as of 1.4.24 or r2647 from svn: Rewrites a set of URLs internally in the webserver BEFORE they are handled and checks that files do not exist.

Gute Nachrichten: Ab Version 1.4.24 des Lighty bietet das mod_rewrite Modul die Möglichkeit eine Rewrite-Regel erst anzuwenden nachdem geprüft wurde ob eine Datei existiert. Also genau das Feature was bisher fehlte. Schlechte Nachricht: Die Lighty Version im stable Repository von Debian ist noch nicht aktuell genug. Es ist gibt jedoch eine sehr elegante Möglichkeit unter Debian einzelne Pakte aus dem testing Repository zu installieren. Diese ist hier sehr schön beschrieben: Debian mit aktuelleren Paketen - stable und testing Nachdem man so den Lighty auf eine aktuelle Version gebracht hat ist es relativ einfach htaccess Dateien des Apache zur Verwendung mit Lighttpd zu ändern. Hier eine kurze Anleitung am Beispiel von Wordpress und einem SEO-phpBB: Zunächst das mod_rewrite Modul in der lighttpd.conf aktivieren:

server.modules  = (            
    "mod_expire",            
    "mod_access",            
    "mod_alias",            
    "mod_accesslog",            
    "mod_compress",            
    "mod_fastcgi",            
    "mod_auth",            
    "mod_rewrite",
)

Dann im entsprechenden Vhost eine Datei mit den Rewrite-Regeln einbinden:

$HTTP["host"] =~ "^(lemmingzshadow\.net|www\.lemmingzshadow\.net)$" {    
    server.document-root = "/var/www/lemmingzshadow.net/"    
    include "/var/www/lemmingzshadow.net/rewrite.conf"
}

Und so sehen Beispielsweise meine Rewrite-Regeln für dieses Blog aus:

url.rewrite-if-not-file = ( 
    "(wp-.+).*/?" => "$0",
    "^/(.+)/?$" => "/index.php/$1"
)

Man sieht direkt, dass die Syntax der einer htaccess Datei sehr ähnlich ist und man seine regulären Ausdrücke nahezu eins zu eins übernehmen kann. Wichtig ist das url.rewrite-if-not-file um wirklich nur dann die Url umzuschreiben wenn die aufgerufene Datei nicht existiert. Die erste Regel dient dazu alle wp-* Verzeichnisse nicht umzuschreiben. Die zweite leitet alle restlichen Anfragen auf die index.php um.Am Beispiel eines phpBB mit SEO-Urls sieht das ganze z.B. so aus:

url.rewrite-if-not-file = (  
    "/(.*)-f([0-9]*)/(.*)-t([0-9]*)-s([0-9]*).html" => "/viewtopic.php?f=$2&t=$4&start=$5",
    "/(.*)-f([0-9]*)/(.*)-t([0-9]*).html" => "/viewtopic.php?f=$2&t=$4",
    "/(.*)-f([0-9]*)/index-s([0-9]*).html" => "/viewforum.php?f=$2&start=$3",
    "/(.*)-f([0-9]*)" => "/viewforum.php?f=$2",
    "/global/(.*)-t([0-9]*).html" => "/viewtopic.php?f=1&t=$2"
)

Eine entsprechende htaccess Datei hätte so ausgesehen:

RewriteEngine on
RewriteBase /
RewriteRule ^(.*)-f([0-9]*)/(.*)-t([0-9]*)-s([0-9]*).html viewtopic.php?f=$2&t=$4&start=$5&%{QUERY_STRING} [L]
RewriteRule ^(.*)-f([0-9]*)/(.*)-t([0-9]*).html viewtopic.php?f=$2&t=$4&%{QUERY_STRING} [L]
RewriteRule ^(.*)-f([0-9]*)/index-s([0-9]*).html viewforum.php?f=$2&start=$3&%{QUERY_STRING} [L]
RewriteRule ^(.*)-f([0-9]*)/ viewforum.php?f=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-f([0-9]*) viewforum.php?f=$2&%{QUERY_STRING} [L]

Auch hier können die regeln fast eins zu eins übernommen werden. Noch ein wichtiger Hinweis zum Schluss: Um Änderungen an den Rewrite-Regeln zu übernehmen muss der Lighttpd neu gestartet werden!

Hoffentlich konnte ich mit diesem kurzem Beitrag dem ein oder anderen die Umstellung von Apache auf Lighttpd erleichtern.

Nachtrag vom 01.06.2010: lifeofguenter stellte fest, dass das mod_rewrite Modul aktuell wohl nur im 1.4er Trunk entsprechend angepasst ist. Für die 1.5er Versionen des Lighttpd ist die Möglichkeit url.rewrite-if-not-file zu nutzen aktuell wohl noch nicht implementiert.