I was converting some mod_rewrite rules from the Lighttpd webserver to Apache today. While Lighttpd and Apache both have request rewriting modules with pretty equivalent functionality, there are some significant differences nonetheless. Specifically, I was trying to rewrite a URL of the form:

/script?key=123abcxyz
to a file on the local disk:
/abc/123/123abcxyz
In Lighttpd, I had a single rewrite rule handling both the URL and its query string:
"^/script?key=(([0-9a-f]{3})([0-9a-f]{3}).*)" => "/$2/$3/$1"
The regular expression might be a little confusing at first, but its reasonably straight forward. My first thought was that I could do pretty much exactly the same thing with an Apache RewriteRule, like so:
RewriteRule ^/script?key=(([0-9a-f]{3})([0-9a-f]{3}).*) /$2/$3/$1
Unfortunately this won't work - the RewriteRule will only be passed the URL - that is, /script without the query string (?key=foo). So how do you make the RewriteRule aware of the value of the query string to rewrite to the local on-disk file correctly? You must have a RewriteCond directive preceeding the RewriteRule. RewriteCond can run a grouping regular expression over the query string, and RewriteRule can pull those groups out of the previous RewriteCond with a special syntax:
RewriteCond %{QUERY_STRING} key=(([0-9a-f]{3})([0-9a-f]{3}).*)
RewriteRule ^/script /%2/%3/%1
So there you are - how to have an Apache RewriteRule operate on parts of the query string as well as on the URL. The solution ends up being a little more convoluted under Apache than under Lighttpd, but is still manageable.

Niall O'Higgins is an author and software developer. He wrote the O'Reilly book MongoDB and Python. He also develops Strider Open Source Continuous Deployment and offers full-stack consulting services at FrozenRidge.co.

blog comments powered by Disqus