1

I am building .htaccess for both localhost and godaddy when I stumbled upon this issue.

RewriteEngine on

SetEnvIf HOST ^localhost$ LOCAL=/company
SetEnvIf HOST ^((?!localhost).)+ LOCAL=/

<If "%{ENV:LOCAL} == '/'">
    RewriteRule (.+) index.php?test=godaddy [QSA,L]
</If>
<Else>
    RewriteRule (.+) index.php?test=localhost [QSA,L]
</Else>

I have tried searching for answers like adding ifmodule mod_rewrite inside and also tried to encapsulate the if directive but to no avail and would like to know why this is not working.

I did find that if you put a / before index.php it will return to dashboard for localhost and for godaddy, it will return an internal server error.

NewWeiNern
  • 13
  • 3

1 Answers1

0

The use of mod_rewrite directives inside <If> expressions is seemingly quite "buggy"*1 no doubt related to the late phase in which the directives are processed.

(*1 Whether it is really "buggy" or is "by design" I'm not sure, but it is certainly undocumented, peculiar and unhelpful!)

Inside an <If> block the RewriteRule pattern (ie. (.+)) matches against the full absolute filesystem path that the request maps to, instead of a relative (or root-relative) URL-path*2. And relative path substitutions (that don't start with a slash or scheme) are relative to what?! In testing the (directory?)prefix that is added back on relative path substitutions inside an <If> expression is the literal text *If/ - which is just weird. And this is regardless of context (.htaccess, directory, virtualhost or server).

(*2 This has been reported as a bug, although whether it really is or not I'm not sure. I thought I'd seen a more verbose/discussed bug report than the one I've linked to but I can't seem to find it?)

So, in your case the "Bad Request" results from the internal rewrite to *If/index.php?test=....

I did find that if you put a / before index.php it will return to dashboard for localhost and for godaddy, it will return an internal server error.

A slash prefix will result in a document-root-relative URL-path.

I would expect this to result in an internal rewrite loop (ie. 500 Internal Server Error response) since the rewrite engine starts over after the request is initially rewritten and there is nothing to prevent this from reoccurring repeatedly. Not sure why the difference in behaviour between localhost and GoDaddy, except possibly in how this interacts with other directives you might have?

So, I would avoid using mod_rewrite directives inside <If> expressions if possible. (In this limited example, the <If> expression is certainly unnecessary.)

However, there are better ways to solve this.

Presumably on "localhost" you have access to the server config / VirtualHost? In which case it would be easier to Define an Apache parameter/variable. For example:

# In <VirtualHost> on local development server
Define LOCAL 1

Then in .htaccess:

RewriteEngine on

# Local Development Server
<IfDefine LOCAL>
    RewriteCond %{QUERY_STRING} !^test
    RewriteRule (.+) index.php?test=localhost [QSA,L]
</IfDefine>

# Live Server
<IfDefine !LOCAL>
    RewriteCond %{QUERY_STRING} !^test
    RewriteRule (.+) index.php?test=godaddy [QSA,L]
</IfDefine>

Aside: The capturing RewriteRule pattern in the above directives is entirely superfluous.


See also my answer to a related question on StackOverflow that highlights other issues with using mod_rewrite inside Apache <If> expressions:

MrWhite
  • 11,643
  • 4
  • 25
  • 40
  • 1
    You deserve a round of applause! What you explained in the following makes absolute sense. I do wonder why they never intended to make If Directive more accessible for RewriteRule but your alternatives really works out miraculously for both localhost and godaddy. I hope that if anyone have the same doubts as me, they can look no further than this answer that you have posted! – NewWeiNern Feb 20 '21 at 15:12
  • Generally, you don't _need_ to use mod_rewrite inside `` expressions since mod_rewrite alone provides the necessary tools for the job. So, I think it's really a case of using "`` expressions" OR use mod_rewrite. Unfortunately, this does mean you can't simply encapsulate a group of mod_rewrite directives in an `` expression and expect them to work. I've updated my answer with a couple of reference links. The way `RewriteRule` matches inside `` expressions has been reported as a "bug", although whether it is or not I'm not sure. – MrWhite Feb 20 '21 at 18:31