Redirect Query String via .htaccess
In general, redirecting URLs is a piece of cake with Apache’s .htaccess. The only trick is redirecting based on the URL’s query-string value. Doing so requires slightly different directives that many people are not aware of, so it’s common to see a questions like, “why isn’t my redirect working for query strings?” This quick tutorial aims to clear up any confusion and explains how to redirect any URL based on its query string.
Query Strings in URLs
What are we talking about when we say “query string”? Here are some examples:
http://example.com/index.php?this=is-a-query-string
http://example.com/directory/?and=this-is-a-query-string
http://example.com/path/?also-a-query-string
So basically anything included after the first question mark, ?
, is considered the query string. So for those three URLs, the query strings would be:
this=is-a-query-string
and=this-is-a-query-string
also-a-query-string
Notice the query strings can have a key and value (first two examples), or just a key with no value (third example). Either way, it makes no difference to Apache, because it treats the entire query string — whatever it may be — as a single string. That is, Apache makes no distinction between keys and values; the query string simply is whatever comes after the first question mark in the URL. This greatly simplifies things when it comes to redirecting based on query strings.
Redirecting query strings
To redirect based on the URL’s query string, we must use Apache’s mod_rewrite. Unfortunately, mod_alias does not recognize query strings. But no problem, mod_rewrite is super powerful and provides a LOT of flexibility to get the job done.
Here is the basic technique for redirecting a URL based on the value of its query string:
# Redirect Query String
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} key=value
RewriteRule (.*) /path/ [R=302,L]
</IfModule>
Here is what’s happening in this rule set, line by line:
<IfModule mod_rewrite.c>
– Check ifmod_rewrite
is availableRewriteEngine On
– Enable the rewrite engine (if not already enabled)RewriteCond %{QUERY_STRING} key=value
– Check the value ofQUERY_STRING
for the string,key=value
RewriteRule (.*) /path/
– For any matching URLs, redirect to/path/
[R=302]
– Send a 302 “Temporary” header along with the response[L]
– Instruct Apache to stop processing this rule set</IfModule>
– Close the check formod_rewrite
That’s the basic idea. If you are familiar with regular expressions (regex) and mod_rewrite
, you can pretty much stop reading here. Otherwise, continue reading for some examples showing how to customize the redirect however is necessary.
Example 1: Target query string of a specific URL
In the previous (basic) example, we are matching any URL that has a query string that contains the specified string, key=value
. Here is how to limit the redirect to only a specific URL:
# Redirect Query String
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} ^/specific/url/
RewriteCond %{QUERY_STRING} key=value
RewriteRule (.*) /path/ [R=301,L]
</IfModule>
This does the same thing as before, only now the redirect will happen only if the requested URL begins with /specific/url/
. Hence the caret ^
indicates the beginning of the REQUEST_URI
variable. Note also that here we change the status code for the redirect from 302
to 301
.
Example 2: Redirect more than one query string
Now say that we want to redirect any query string that includes any of the following:
key=value-01
key=value-02
key=value-03
.
.
.
..such that any number appended to key=value-
will match and redirect. Here is the code:
# Redirect Query String
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} key=value-([0-9]+) [NC]
RewriteRule (.*) /path/ [R=302,L]
</IfModule>
The trick here is using ([0-9]+)
to match any number of numerical digits, 0 thru 9. Also note that the [NC]
flag makes the match case-insensitive.
Example 3: Include the query string in the redirect URL
Lastly, here is an example that shows how to include the value of the matched query string in the URL to which the request will be redirected. To illustrate, say we want to redirect these URLs:
http://example.com/directory/?key=value-01
http://example.com/directory/?key=value-02
http://example.com/directory/?key=value-03
.
.
.
..to these target files:
http://example.com/directory/file-01.html
http://example.com/directory/file-02.html
http://example.com/directory/file-03.html
.
.
.
..such that the matching number is used in the target file name. Here is the magic code to make it happen:
# Redirect Query String
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} key=value-([0-9]+) [NC]
RewriteRule (.*) /directory/file-%1.html? [R=301,L]
</IfModule>
Here we are using the same basic technique as in previous examples. There are two important things happening here:
%1
– Returns the value of the number matched in theRewriteCond
?
– Instructs Apache to remove the query string from the rewrite URL
Removing the query string
To remove the query string from the rewrite URL for Apache 2.2, use the question-mark technique described in the previous section. To remove the query string for Apache version 2.4+, you must use the [QSD]
flag instead. For example, here is the same technique as before, only rewritten for compatibility with Apache 2.4:
# Redirect Query String (Apache 2.4)
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} key=value-([0-9]+) [NC]
RewriteRule (.*) /directory/file-%1.html [R=301,L,QSD]
</IfModule>
Notice the QSD
in the RewriteRule
? That’s the ticket for Apache 2.4 and better. Also note that we removed the question mark ?
from the rewrite URL; otherwise it would have triggered an error.
Until next time..
Hopefully these examples enable you to customize your own query-string redirects. If you have any questions, feel free to ask via the comments section below.