Jonathan Polansky

A pretty good webpage.

Using mod_rewrite to redirect URIs with GET query parameter strings

I recently came across a situation where I had to redirect URI paths and GET query parameter string combinations to a single URI.  The URI path could be the same between requests and the GET query strings could be the same between requests but the combination of the two was guaranteed to be unique.

My first instinct was to simply use mod_rewrite and the REQUEST_URI server variable to match the URI path and GET query string combination.  Much to my disappointment, I quickly learned that REQUEST_URI doesn’t include the GET query string appended to the URI path.

Next I considered using RewriteConds checking the REQUEST_URI and QUERY_STRING server variables.  This would result in a set of rules similar to below:

RewriteCond ${REQUEST_URI} /something/here/index\.php [NC]
RewriteCond ${QUERY_STRING} var1=hello&var2=world [NC]
RewriteRule .* /final/destination/index.php [R=301,L]

How obnoxious to have to specify two RewriteConds and then a Rewrite rule for each request URI, not to mention the fact that the RewriteRule destination URI would be the same for each set.  Convinced there had to be a better way, I forged on with google.

Eventually, I came across this post on webmasterworld.  It suggested using the THE_REQUEST server variable and matching against the entire HTTP request.  As taken from that post, the above request rewrite rule set becomes

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /something/here/index\.php\?var1=hello&var2=world\ HTTP/ [NC]
RewriteRule .* /final/destination/index.php [R=301,L]

There it is.  A nice, compact rule set to match a URI and a GET query string.  As a bonus, you can use the [OR] RewriteCond flag to match multiple request URIs for redirection to the same destination URI.  This wasn’t possible when using the REQUEST_URI and QUERY_STRING method.

One final thing to note is that these rewrite rules will only catch HEAD and GET requests.  Other request methods do not include the query string as part of THE_REQUEST so you cannot match against it.  For that you’ll have to try other creative solutions.


Tagged as , + Categorized as Tech

2 Comments

  1. Thanks a lot.
    In RewriteCond “?” should be escaped.
    “…index\.php?var1…” => “…index\.php\?var1…”
    In my case it was a bug. And thanks again :)

  2. @bearain Nice catch. I have updated the post to reflect this.

comment_type == "trackback" || $comment->comment_type == "pingback" || ereg("", $comment->comment_content) || ereg("", $comment->comment_content)) { ?>

Trackbacks & Pingbacks

  1. bearain

    Thanks a lot.
    In RewriteCond “?” should be escaped.
    “…index\.php?var1…” => “…index\.php\?var1…”
    In my case it was a bug. And thanks again :)

  2. comment_type == "trackback" || $comment->comment_type == "pingback" || ereg("", $comment->comment_content) || ereg("", $comment->comment_content)) { ?>

    Trackbacks & Pingbacks

    1. jpolansky

      @bearain Nice catch. I have updated the post to reflect this.

    Leave a Reply