How to use [OR] or substitute in an .htaccess file?

Summary The [OR] flag isn't working consistently across different servers. Details and question below.

I have a website hosted on Godaddy and I wrote this code for an .htaccess file to redirect users to the https version of my site. It works great.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off [OR]
    RewriteCond %{HTTP_HOST} !^www\. [NC]   
    RewriteRule ^(.*)$ https://www\.firstsite\.com%{REQUEST_URI} [R=301,L]
</IfModule>

I used the same .htaccess file for a different site hosted on Network Solutions and it crashed the site. It produced this error.

This page isn’t working
www.secondsite.com redirected you too many times.
ERR_TOO_MANY_REDIRECTS

I removed the [OR] flag for the network solutions site and the site loaded without the error. This is the updated code.

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTPS} off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^(.*)$ https://www\.secondsite\.com%{REQUEST_URI} [R=301,L]
</IfModule>

Unfortunately without the [OR] it doesn't redirect based on the first condition, RewriteCond %{HTTPS} off. However it still redirects based on the second condition RewriteCond %{HTTP_HOST} !^www\. [NC]

I'm not sure how to fix this. I need the [OR] but I can't use it. Is there a way to use [OR] differently or is there a substitute for situations like this? Thanks so much!


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.

  1. 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.)

  2. 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.)

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