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, event organizer and software consultant. He wrote the book MongoDB and Python, published by O'Reilly. Events he organizes include We Have Tablets, the #1 Bay Area Tablet Computing Meet-up and PyWebSF. He also offers consulting services for Mobile, Tablet and Cloud Computing.

blog comments powered by Disqus