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 ---

  • Do you have a DirectoryIndex document located in the root of example.com? eg. index.html or index.php etc.? – MrWhite May 5 '20 at 10:08
  • The index.php of Wordpress is located at the root. – Alex Huber May 5 '20 at 11:56
  • What version of Apache are you on? – MrWhite May 5 '20 at 13:58
  • Apache/2.4.10 (Debian) – Alex Huber May 5 '20 at 15:11

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.

  • Thanks, but that actually caused a 400 error for me. I may have to point out again that the RewriteCond seem to be fine (even if too complex), because if I use [L,R=301] for the RewriteRule, the url is rewritten correctly (but of course visible to the user, which I do not want). It's just when using [P], nothing seems to happen at all. – Alex Huber May 5 '20 at 15:07
  • Hhhmm I don't see how this would generate a 400 Bad Request, except if there is an underlying issue with the proxy or perhaps a conflict with other directives in your .htaccess file? Please include the contents of you .htaccess file in your question, with these directives in-place. Do you have other .htaccess files along the filesystem path? – MrWhite May 5 '20 at 15:40
  • The directive RewriteCond %{REQUEST_URI} ^($|\/$|\?|\/\?) is the same as simply RewriteCond %{REQUEST_URI} ^/$ since scenario 1, 3 and 4 are "impossible" (unless ? is URL encoded in the URL-path and you are intentionally accepting requests of the form /%3Ffoobar - which that condition will accept). This may be "OK" for the redirect (since processing stops and the redirect response is immediately sent back to the client), but we are dealing with mod_proxy which might be triggered later, after mod_dir has processed the request. – MrWhite May 5 '20 at 15:54
  • 1
    Also try changing the RewriteRule pattern from ^(index\.php)?$ to ^index\.php$ - do you still get the 400 response? – MrWhite May 5 '20 at 16:43
  • Thank you, I updated my question with the progress, your new pattern does work, but it also conflicts with Wordpress now. – Alex Huber May 6 '20 at 8:02

I've tested this with my .htaccess containing only

RewriteRule ^ "/info.php?orig=%{REQUEST_URI}" [P]

When I requested http://localhost/, REQUEST_URI contained "/index.html", which of course did not fit with your second RewriteCond.

  • Thanks. I may have to point out again that the RewriteCond seem to be fine, because if I use [L,R=301] for the RewriteRule, the url is rewritten correctly (but of course visible to the user, which I do not want). It's just when using [P], nothing seems to happen at all. – Alex Huber May 5 '20 at 15:13
  • Does your backend understand HTTPS? – Gerard H. Pille May 5 '20 at 16:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.