Problems
I get too many redirect: all urls redirect infinitely to themselves, why?
Apache rewrite rules are processed top-to-bottom, so your custom rewrite rule is always processed first. The R
redirect flag instructs Apache to tell the browser to make a new request to the altered URL instead of serving the destination of the rewrite at the current address, and the L
"last" flag tells Apache to ignore all proceeding rewrite rules - so whenever your RewriteRule
is applied, a new request is made and your rules are processed once again from the top.
Your RewriteCond
instructs Apache to process the proceeding RewriteRule
whenever the request URI path does not begin with /privacy-policy
- so virtually every request is resulting in a redirect before any of the other rules in your .htaccess
can be so much as evaluated.
As @MarkKaplun alluded to in the comments $1
is a back-reference that's substituted with the portion of the matched URI contained in the first "capture-group" (the first set of parenthesis in the pattern). Since .*
literally matches any number of any characters, in your RewriteRule
$1
is substituted with the entire URI path.
In essence, your rewrite rules:
RewriteCond %{REQUEST_URI} !^/privacy-policy/
RewriteRule (.*) http://www.mywebsite.com/$1 [R=301,L]
evaluate to "If the URI does not begin with /privacy-policy/
, have the web-browser send a new request to http://www.mywebsite.com/(original URI path)
".
So, for illustrative purposes, say you navigated to http://www.mywebsite.com/blog/2015
; here's what happens with each request:
/blog/2015
does not start with /privacy-policy/
, tell the browser to go to http://www.mywebsite.com/blog/2015
.
/blog/2015
does not start with /privacy-policy/
, tell the browser to go to http://www.mywebsite.com/blog/2015
.
/blog/2015
does not start with /privacy-policy/
, tell the browser to go to http://www.mywebsite.com/blog/2015
.
- [...]
Removing the $1
back-reference from the RewriteRule
is insufficient, as a URI path of /
(or a simply empty one) still does not qualify as beginning with /privacy-policy/
, resulting the in the behavior:
/blog/2015
does not start with /privacy-policy/
, tell the browser to go to http://www.mywebsite.com/
.
/
does not start with /privacy-policy/
, tell the browser to go to http://www.mywebsite.com/
.
/
does not start with /privacy-policy/
, tell the browser to go to http://www.mywebsite.com/
.
- [...]
You can verify this behavior by taking a look at your Apache installation's log files.
Solution
If you don't plan on using WordPress's intended address routing, there's no reason to keep the default rewrite rules and stack more on top of them. Tailor them to your needs instead of adding complexity:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^(/|index\.php)$ /index.php? [L]
RewriteRule ^/?privacy-policy/?$ /index.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /? [L,R=301]
</IfModule>
In summary,
- .
RewriteRule ^(/|index\.php)$ /index.php? [L]
If /
or index.php
was explicitly requested, serve index.php
, but drop the querystring (in order to prevent changing pages via query-var manipulation) and stop processing rewrites.
- .
RewriteRule ^/?privacy-policy/?$ /index.php [L]
If privacy-policy
(with or without leading and trailing slashes) was explicitly requested, serve index.php
and stop processing rewrites.
- .
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /? [L,R=301]
If the requested filename is not a file and not a directory, match a single character anywhere (in order to apply the rule no matter the URI) and tell the browser to make a new request to /
and discard it's querystring. Stop processing rewrites.
It's worth noting that your intended outcome will probably produce a lot of unexpected behaviors - you'll likely be unable to access the administrative dashboard, for one. Attachments may also break. But the above should at the very least provide a good starting point for learning more about rewrite directives.
$1
does ;)