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: