Apache mod_rewrite RewriteRule with query string

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.

2 comments to Apache mod_rewrite RewriteRule with query string

  • Thank you, I was ripping my hair out about this. I’m creating a search engine with pretty URLs that are feed through a framework routed by index.php. parsing the get string two different ways was not a smart option because not only would look ugly but I’d have to parse the $_GET array in two different ways.

    I’m at a new crossroadds now though because the search form allows for checkboxes which are passed as an array which in a query string looks something like >> option[]=1&option[]=3&option[]=7

    So this is going to be a pain in the ass :)

    Thanks though! :D

  • Ahh, perfect! I was just wondering why it wasn’t working!

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">