Apache RewriteRule and query string

At first look, the way Apache mod_rewrite module deals with query strings can be a little confusing. From the RewriteRule documentation:

qsappend|QSA’ (query string append) This flag forces the rewrite engine to append a query string part of the substitution string to the existing string, instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule.

Let’s try to redirect a page depending on its query string. Our rewrite rule should looks like this:

RewriteCond %{QUERY_STRING} ^id=([0-9]*)$ RewriteRule ^page\.php$ http://mydomain.site/page/%1.php [R=302,L]

According to the official documentation, you would expect the following behavior:

/page.php?id=37 -> http://mydomain.site/page/37.php /page.php?id=40 -> http://mydomain.site/page/40.php # and so on

However, if you don’t append something new, then the original query is passed through the rules unchanged by default.

/page.php?id=37 -> http://mydomain.site/page/37.php?id=37 /page.php?id=40 -> http://mydomain.site/page/40.php?id=40 # and so on

If you want to discard the original query string you must append an empty question mark at the end of the rule. Let’s call it the query string not append or query string discard flag.

RewriteCond %{QUERY_STRING} ^id=([0-9]*)$ RewriteRule ^page\.php$ http://mydomain.site/page/%1.php**?** [R=302,L]

Here’s a quick reference for dealing with query string in a RewriteRule.

``` Keep original query (default behavior) RewriteRule ^page.php$ /target.php [L] # from http://example.com/page.php?foo=bar # to http://example.com/target.php?foo=bar

Discard original query RewriteRule ^page.php$ /target.php? [L] # from http://example.com/page.php?foo=bar # to http://example.com/target.php

Replace original query RewriteRule ^page.php$ /target.php?bar=baz [L] # from http://example.com/page.php?foo=bar # to http://example.com/target.php?bar=baz

Append new query to original query RewriteRule ^page.php$ /target.php?bar=baz [QSA,L] # from http://example.com/page.php?foo=bar # to http://example.com/target.php?foo=bar&bar=baz ```