No Query String? No Problem.

Patrick Reagan, Former Development Director

Article Category: #Code

Posted on

When rewriting URLs on your site with mod_rewrite, you'll typically want to preserve the query string while redirecting your users to the new location. You can accomplish this by either clobbering the existing query string:
RewriteRule ^category/tech/?$ https://www.viget.com/extend/ [R=301,L] 
Or appending to an existing one (with the QSA option):
RewriteRule ^category/tech/?$ https://www.viget.com/extend/ [QSA,R=301,L] 
Both of these rules assume that you want to preserve the query string, but what if you want to remove it entirely? We needed to do exactly that when moving the existing Viget site over to its new incarnation. Instead of our news items having antiquated ID-based URLs, each post now has a nice SEO-friendly "slug." A quick attempt at redirecting one of these news items looked like this:
RewriteCond %{QUERY_STRING} ^id=1889 RewriteRule ^news-detail.html$ https://www.viget.com/blog/nixon_reagan_williams_featured_in_computerworld/ [R=301,L] 
If we dissect this, the rule states: for a query string containing 'id=1889', permanently redirect the 'news-detail.html' URL to this new one and don't process any other rules. When it came time to test it out, it mostly worked, but would append ?id=1899 to the URL. Even though we didn't specify how to handle query strings, the original was added to the end of the URL – something we definitely didn't want. The official mod_rewrite documentation yielded this tip:
By default, the query string is passed through unchanged. You can, however, create URLs in the substitution string containing a query string part. Simply use a question mark inside the substitution string to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.
After simply adding a question mark to the rewritten URL, we now had the desired behavior:
 RewriteCond %{QUERY_STRING} ^id=1889 RewriteRule ^news-detail.html$ https://www.viget.com/blog/nixon_reagan_williams_featured_in_computerworld/? [R=301,L] 
Try it out for yourself.

Related Articles