November 07, 2006

Extensible mod_rewrite with Lua

I was running an experiment with apache + mod_rewrite that required rules that cannot be expressed with regular expressions. mod_rewrite has the notion of rewrite maps, which let you choose from a couple of built in functions (int:tolower, int:toupper, etc.) or a key-value pair map backed by a text or dbm file.

Unfortunately, there's no way to plug in arbitrary mapping functions*, so my first thought was to extend mod_rewrite by adding a new built in function. This lets me write:


LoadModule rewrite_module modules/mod_rewrite.so
RewriteEngine on
RewriteMap foo int:foo

RewriteRule (.*) ${foo:$1} [L]


It works great, but this approach requires forking mod_rewrite.c, which is obviously not a good thing.

Inspired by Brian's mod_wombat, which allows you write http handlers in Lua, I thought "wouldn't it be nice to be able to extend mod_rewrite with custom Lua scripts?". Say, something like:



LoadModule rewrite_module modules/mod_rewrite.so
RewriteEngine on
RewriteMap foo lua:/usr/local/apache2/rewrite-rules.lua

RewriteRule (.*) ${foo:$1} [L]



30 lines of code later, my lua-enabled mod_rewrite prototype is able to do exactly that. Mind you, this is a very crude implementation and doesn't check for errors, cache compiled scripts, etc. But all those details can be improved.

Anyway, this is all becomes somewhat irrelevant with the latest version of mod_wombat, which allows you to define transform_name hooks in Lua, as well.

It was a interesting experiment, nonetheless :)



* To be fair, there is actually a way to do this, but I consider it to be too clunky and non-scalable to be of any value in a real production system. The mechanism consists on mod_rewrite talking to an external process that does translations via its stdin/stdout streams. As a result, a global mutex is required to guarantee correctness in the face of multiple simultaneous requests.