RewriteRule (Reverse Proxy) of front page in htaccess not working

.htaccessmod-rewritereverse-proxyrewrite

The following rule should target my front page (WordPress) to serve a different page instead.

RewriteCond %{HTTP_HOST} ^example.com$
RewriteCond %{REQUEST_URI}  ^($|\/$|\?|\/\?)
RewriteRule ^(.*) https://yy.example.com [P]

so https://example.com should serve https://yy.example.com behind the scenes.

I also do this with several other sub-sites, like this:

RewriteCond %{HTTP_HOST} ^example.com$
RewriteCond %{REQUEST_URI}  ^/zzz($|\/$|\?|\/\?)
RewriteRule ^(.*) https://yy.example.com/zzz [P]

which successfully serves https://yy.example.com/zzz for a request on https://example.com/zzz. This needs to be done for specific URLs only, and not for the whole domain btw.

However, the first rule for the front page does not work.

If I use [L,R=301] instead, it does redirect to https://yy.example.com so the RewriteCond work correctly. But for some reason, only on the front page, the RewriteRule does not work with [P] while it does work with [L,R].

What could be the reason? Is there anything specific that needs to be added for the front page? Is WordPress somehow messing with this? The rewrite rules are at the very top of the .htaccess file, so no earlier rule is messing with this. Also note that [R] works which also indicates that this rule is actually reached but not correctly executed when using [P] directive.

UPDATE:
The following rule (by MrWhite) makes is possible to correctly redirect the front page:

RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^index\.php$ https://yy.example.com/ [P]

BUT, since there is WordPress running, it also redirects any other WordPress page, because from what I see, WordPress rewrites any "non-existing" path (due to pretty links, like https://example.com/zzz) to index.php, which then handles which page to display, with this default WordPress directives.

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

So, we are getting close, thanks to MrWhite, but we're not quite there yet.

ANOTHER UPDATE:
Fixed the WordPress redirects by renaming the index file of WordPress to index-wp.php and adapt the rule to:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index-wp.php [L]

So effectively I use MrWhite's updated rule to forward access on the front page (index.php), then I filter the few /zzz sub-pages with the rules above, and everything else is then forwarded to either the actual server paths or to WordPress (index-wp.php) with those last rules.

— SOLVED —

Best Answer

The index.php of Wordpress is located at the root.

mod_dir may be issuing an internal subrequest for the directory index (ie. index.php) before mod_rewrite/mod_proxy catches the request, in which case your directive won't match. However, there are other issues with your directive...

RewriteCond %{HTTP_HOST} ^example.com$
RewriteCond %{REQUEST_URI}  ^($|\/$|\?|\/\?)
RewriteRule ^(.*) https://yy.example.com [P]

The substitution string is missing a trailing slash after the hostname. Something needs to append this in order to make a valid HTTP request. In the case of an external redirect, the browser effectively appends the trailing slash here.

The CondPattern ^($|\/$|\?|\/\?) is overly complex and matching too much. It will only ever match the 2nd alternation segment (ie. \/$) - if any. The REQUEST_URI variable always starts with a slash and does not contain the query string. There is also no need to backslash escape the slash here (there are no regex delimiters). However, this RewriteCond directive is not required - you can perform the necessary check in the RewriteRule pattern - which will also be more efficient.

Try the following instead:

RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^(index\.php)?$ https://yy.example.com/ [P]

The RewriteRule pattern ^(index\.php)?$ matches either / or /index.php.

Related Topic