Lighttpd, mod_rewrite, url.rewrite and Error 404 Handlers

Categories: news — Tags: , , — Posted by: Grant @ March 19, 2008 : 4:19 pm

Alert: Total geek post.

Thought I would do a favor to anyone Googling for answers out there that might experience what I’ve run into the last day. Lighttpd is a relatively new webserver that I’ve picked over Apache, simply due to speed. Light does not handle .htaccess files however, which can post a major problem to developers familiar with the already arcane mod_rewrite, RewriteCond and RewriteRule voodoo that already goes on.

Many off-the-shell CMS packages like Joomla, WordPress and Drupal use URL friendly filenames to help with SEO. It turns URLS that look like:
http://www.coffee.net/index.php?id=52&page=2&content=article

Into the more readable:
http://www.coffee.net/article/51/2.html

This is most often achieved with the very simple .htaccess command of:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php

As mentioned earlier, lighttpd does not support .htaccess files or this mod_rewrite syntax. It uses url.rewrite and url.redirect instead for various common redirection and rewriting tasks.

Searching on Google, I came across various posts on how to achieve the same effect, some using mod_magnet with a combination and others simply having their error 404 handler take care of things. I didn’t want to do either of these, because:
1) Having gone the error handler route, the server will DROP (yes, drop) any GET requests sent. I’ve tested this in Apache initially as a shortcut to save some cpu cycles thinking that Apache’s error handler would be faster than mod_write examining the disk. It worked great until my entire CMS system failed completely and left me debugging the hell out of the system until I realized the GET vars were just being dropped. (For the curious, light works in the same way)
2) Mod_magnet and lua, while I’m sure work fine, look like more overhead on top of mod_rewrite already. I hate overhead. Like, a lot.

So, Googling around more, I found some nice clues. First was lighttpd’s very own configuration docs that mention two servers variables: $PHYSICAL["existing-path"] and $PHYSICAL["path"], both of which seemed to be promising as variables to indicate whether a URL requested is a file that exists on the system. Paydirt. Then I realized it requires light 1.5.0 and that I don’t yet have that installed. Poop. (Yes, I could simply upgrade, but having just got things working, I don’t want to risk destroying anything until AFTER I get everything solidified. Looks like we’ll have to do things the hard way.

Here’s the eventual code that I came up with do perform the similar feature:

url.rewrite = (
"^/reserved/(.*)$" => "$0",
"^/static.html" => "$0",
"^/.+\.(html)$" => "/index.php",
"^/(.+)/$" => "/index.php"
)

It’s short, sweet and leaves many lovely CPU cycles untouched vs some big regex monsters. Obviously, this specific code is made for Coffee.net’s own CMS, but it’s not hard to tweak it to your own desire. The first and second line is to set aside any special directories or filenames that you don’t want rewrite to process. The rest looks for .html or directory requests- which should be what your webserver is receiving if you’re using friendly URLs.

Of course, I’d prefer -f and -d anyday given it’s probably faster, but this will do for now (at least until I upgrade lighty to 1.5 and see if I can get the $PHYSICAL var to do some magic).

No Comments »

No comments yet.

RSS feed for comments on this post.

Leave a comment

Home | About Us | Seattle Restaurants | Food Articles | Blog | Friends | Charity | Advertising | Contact Us
Blogging platform by WordPress
36 queries. 0.530 seconds.