The [OR]
flag isn't working consistently across different servers.
This is (almost) impossible. The OR
flag is a fundamental construct/operator in mod_rewrite. If this construct is not working properly then you have a serious problem with your server, requiring reinstallation or finding a new host. This scenario is just so improbable.
However, what is far more likely is that one of the operands in the OR'd expression is not as you expect. ie. In this instance, either one of the server variables HTTPS
or HTTP_HOST
is not set as you expect it to be. And out of the two, it is more likely that the HTTPS
server variable is not being set (or not set as you expect) - as I mentioned in my comment. This is quite "normal" and depends on your server config and how the SSL cert is managed. eg. If your SSL cert is managed by a front-end proxy (like CloudFlare) then the HTTPS
server variable probably is not set. This would seem to be consistent with the results you are seeing.
Debugging
The following tips are just to help with initial debugging in order to find an eventual solution.
NB: Whilst testing, it is preferable to use temporary (302) redirects, which are not cached by the browser. 301 (permanent) redirects are cached hard by the browser, so you must ensure the cache is disabled, which makes testing problematic. Please ensure the cache is cleared before continuing.
Try (temporarily) changing this to an HTTP to HTTPS (only) redirect, ie. remove the www canonicalisation. Do you still get a redirect loop? For example:
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R,L]
(Aside: No need to escape dots in the RewriteRule
substitution - this is an ordinary string, not a regex.)
If the above triggers a redirect loop then check what the server variable HTTPS
contains. ie. Remove the above HTTP to HTTPS redirect and add the following instead:
RewriteRule ^foo$ /?HTTPS=%{HTTPS} [R,L]
And access the URL https://example.com/foo
directly. You should be redirected to https://example.com/?HTTPS=<value>
. What is the <value>
? (The <value>
might be empty.)
Check the HTTP request headers your application is seeing. If you are using PHP then check the $_SERVER
and $_ENV
superglobal arrays and specifically check for the indices HTTPS
, SERVER_PORT
, SCRIPT_URI
and HTTP_X_FORWARDED_PROTO
(which corresponds to the X-Forwarded-Proto
header - if set at all). However, there could well be others, specific to your server. For example, some hosts set an environment variable called HTTPS
(as opposed to a server variable of the same name). Add what you find to your question.
If you see an X-Forwarded-Proto
request header then you are behind a front-end proxy, like this question on StackOverflow.
See also this question on Pro Webmasters for a similar "discussion" and eventual solution.
UPDATE: ... a site hosted on Network Solutions...
I've just done a bit of digging regarding "Network Solutions" (NS) and it seems this may not be possible!? This I find utterly staggering if true, however, I would think it must still depend on how and what type of SSL cert is installed?
(Still check the HTTP request headers and server/script variables as mentioned above.)
However, the Network Solutions support document on SSL Redirects states:
Network Solutions® uses a proxy SSL this does not allow the use of server-side variables to detect HTTPS (secure). All server-side coding will always detect HTTP (non-secure), and for programs that attempt to redirect non-secure connections (http://
) to a secure connection (https://
) will result in an infinite loop and server error after 30 seconds.
You can use a client-side program (like javascript) to detect if it's secure and redirect if it's not. You can use the below coding to create a redirect. Just modify the code so that it redirects to the correct secure domain and add it into the HTML of any sensitive pages you may have.
<script language="javascript">
if (document.location.protocol != "https:")
{
document.location.href = "https://subdomain.yourdomain.com" +
document.location.pathname;
};
</script>
The "proxy SSL" should identify itself, or at least identify the HTTPS state in the "proxied" request to the application server. However, this implies it does not.
See also the following related question on StackOverflow. However, the "other" solutions presented there don't seem viable IMO. The eventual conclusion would seem to be a reference to the above support doc (and JavaScript solution) from NS.
https://stackoverflow.com/questions/4686668/https-redirect-for-network-solutions