htaccess turn on https and www BUT only when live, not locally - apache

I would like to have .htaccess code that adds https and www to my URLs – but only when my site is live, not when I am developing locally on my computer.
I have the following
RewriteCond %{HTTP_HOST} !^localhost(?::\d+)?$ [NC]
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L,NE]
But this doesn't appear to be adding the www when my site is live. So for example https://example.com doesn't have the www and all the links are broken. For example https://example.com/about just gets a 404 Not Found error message.
Thanks for any help. I don't understand .htaccess files/code.
EDIT / UPDATE
Comparing the code to other code, should it be the following?
RewriteCond %{HTTP_HOST} !^localhost(?::\d+)?$ [NC]
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} !on
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

Comparing the code to other code, should it be the following?
RewriteCond %{HTTP_HOST} !^localhost(?::\d+)?$ [NC]
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} !on
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]
Yes.
Your original rule explicitly removed the www subdomain. If you had requested http://www.example.com/ (note HTTP), you would have been redirected to https://example.com/ (HTTPS + non-www). But nothing would happen if requesting https://www.example.com/ - the canonical URL (the rule is skipped because the 2nd and 3rd conditions fail).
The %1 backreference contains the match from the first capturing group in the preceding CondPattern. eg. Given the CondPattern ^(?:www\.)?(.+)$ then %1 contains whatever is matched by (.+) (the first capturing group), ie. the hostname, less the optional www. prefix.
There is no difference between testing %{HTTPS} off or %{HTTPS} !on - the result is the same.
Test first with 302 (temporary) redirects to avoid potential caching issues. You will need to clear your browser cache before testing since the erroneous redirect will have been cached by the browser.
RewriteCond %{HTTP_HOST} !^localhost(?::\d+)?$ [NC]
Checking for a port number would seem to be unnecessary here. This will fail if you are using localhost on the standard port (80 or 443) since the port number will be omitted from the Host header. Something like !^localhost would suffice, or perhaps !^localhost($|:) if you happen to using a domain name that starts localhost!

Related

Dynamic domain redirection to HTTPS and non-www

I have two domains at the moment: example.pl and example.com.
I'm trying to make sure they all go to https://example.pl or http://example.com respectively but I have a problem (or my browser also remembers old state).
I have this code at the moment:
RewriteCond %{ENV:HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^example.pl [NC]
RewriteRule ^ https://example.pl%{REQUEST_URI} [L,NE,R=301]
RewriteCond %{ENV:HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [L,NE,R=301]
But I'm not sure if it's working correctly (http://example.com redirects somehow to https://example.pl) and also whether this can be done in one block of code?
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^example.com [NC]
Both these conditions cannot be successful, so the rule will ultimately fail (do nothing) if requesting the www subdomain over HTTPS.
If it's just two domains then you need to modify the 3rd condition to allow an optional www subdomain and use regex alternation to match the two domains.
For example:
RewriteCond %{ENV:HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(example\.com|example\.pl) [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
The %1 backreference matches the captured subpattern in the last matched RewriteCond directive, ie. either example.com or example.pl. The important point is that the 3rd condition is always successful, since the only purpose of this 3rd condition is to capture the domain name.
You will need to clear your browser cache since any (erroneous) 301 (permanent) redirects will have been cached by the browser.
But I'm not sure if it's working correctly (http://example.com redirects somehow to https://example.pl) and also whether this can be done in one block of code?
That's not possible with the rules you've posted. It's possible you are seeing a cached redirect from an earlier (erroneous) 301 permanent redirect.
See my earlier answer for an any domain solution.

301 Redirect: New Domain and URL Structure

I need to set up redirects from an old domain to a new one. The URL structure will also be different since we'll be using a different CMS. I need to force HTTPS and non-www.
Is the code below correct for that case scenario?
# Needed before any rewriting
RewriteEngine On
# Force HTTPS and non-WWW
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^ https://www.newdomain.com%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.newdomain.com%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
## 301 Redirects
# Page to Page
RewriteCond %{HTTP_HOST} ^olddomain\.com$ [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{HTTPS} =on
RewriteRule ^collections/product/product-1$ https://newdomain.com/product/product-1? [R=301,NE,NC,L]
RewriteRule ^collections/product/product-2$ https://newdomain.com/product/product-2? [R=301,NE,NC,L]
What's the difference between the code above and a
Redirect 301 /collections/product/product-1 https://www.newdomain.com/product/product-1
Is one preferred over the other?
Have it your .htaccess file in following way.
1st way: Fixing OP's attempts here.
# Needed before any rewriting
RewriteEngine On
# Force HTTPS and WWW to non-www/www URLs.
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^ https://www.newdomain.com%{REQUEST_URI} [L,NE,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301]
## 301 Redirects
# Page to Page
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{HTTPS} =on
RewriteRule ^collections/product/product-1$ https://newdomain.com/product/product-1? [R=301,NE,NC,L]
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{HTTPS} =on
RewriteRule ^collections/product/product-2$ https://newdomain.com/product/product-2? [R=301,NE,NC,L]
2nd way: Using trick here to convert them into single rule if in case you have only collections/product/product-1 AND collections/product/product-2 rules only then try following and save one more condition/rules :)
# Needed before any rewriting
RewriteEngine On
# Force HTTPS and WWW to non-www/www URLs.
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^ https://www.newdomain.com%{REQUEST_URI} [L,NE,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301]
## 301 Redirects
# Page to Page
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{HTTPS} =on
RewriteRule ^collections/product/product-([12])$ https://newdomain.com/product/product-$1? [R=301,NE,NC,L]
Important points related to OP's question:
I have removed your 2nd set of htaccess rules as follows ones. Why because your 1st ruleset itself takes care of www OR non-www both redirection to www URL, so you don't need to keep following ones.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.newdomain.com%{REQUEST_URI} [L,R=301]
Now coming on one more point, I have added NE flag into your Rules for keeping urls in same format(not to convert them hexa form).
Now coming on your question of Redirect rule Redirect 301 /collections/product/product-1 https://www.newdomain.com/product/product-1 its simple, if you keep only this 1 line then your https and www will NOT be implemented in case URLs are NOT https or www, so it completely depends on your requirement, if you need to implement https and www then keep htaccess shown above(edited on from your shown attempts). But you need to still have redirect Rule because you are going to new domain, so have it in above shown way only.
Also have put this in regex (www\.)? to match in case www is there(which will be there since we had done redirect previous rules) in condition under your comment ## 301 Redirects.
NOTE: Either use 1st rules OR 2nd rules one at a time, 2nd one is preferred(if it meets my mentioned suggestion where you are having urls product-1 OR product-2)

HTACCESS 301 Redirect Rule to point all URL Variations to the Live URL

I am trying to achieve something which is working 99%, but there is a tiny issue.
Let's say my live URL is https://www.example.com/sample-page/
I want all the following URL variations to redirect to the live URL with a 301 status.
http://example.com/sample-page/
http://www.example.com/sample-page/
https://example.com/sample-page/
All of the above should redirect to https://www.example.com/sample-page/
I managed to get this working by using the htaccess rule displayed below.
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The problem with the above rule is this: http://example.com/sample-page/ does a double redirect.
http://eyeacademy.com/expert-eye-examination/
301 Moved Permanently
https://eyeacademy.com/expert-eye-examination/
301 Moved Permanently
https://www.eyeacademy.com/expert-eye-examination/
200 OK
As you can see, http redirects to https and then https non-www redirects to https www. I have been trying a few tweaks to this rule and reading up, but I am sure someone here would have a quicker and more robust solution?
You can use this single rule to redirect http -> https and add www and there is no need to hardcode host name in the rule:
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [L,R=301,NE]
You can also reorder your existing rules and avoid multiple redirects like this:
# first add www and make sure it is https://
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# http -> https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
Use an or flag in your RewriteCond directive. Replace everything with the following:
RewriteCond %{HTTPS} off [NC,OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]

Can't get htaccess rule to work: force SSL on all pages, force non-SSL on two specific pages

I am no htaccess expert, but after Googling for two hours I gave up. Maybe you can help me?
I have my entire site on SSL. However, I have two pages that reference non-secure dynamic content from elsewhere. I need these to be on http instead of https.
The first part of my rules work. All the site is forced to SSL except for those two pages. However, the last part doesn't: force those two pages to non-SSL. It is probably very stupid but does anyone see where I go wrong?
#add www. if missing WORKS
RewriteEngine on
RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [L,R=301]
#force SSL/https WORKS
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} !^/webshop2/localize\.php
RewriteCond %{REQUEST_URI} !^/webshop2/layoutstripper\.php
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#force http DOES NOT WORK
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} ^/webshop2/localize\.php [NC]
RewriteCond %{REQUEST_URI} ^/webshop2/layoutstripper\.php [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
You need an [OR] flag in your second SSL rule. The 2 conditions you have essentially say:
the request must be HTTPS
the URI must start with: /webshop2/localize.php
the URI must start with: /webshop2/layoutstripper.php
As you can see, the last 2 conditions will always fail, as the request can't be BOTH at the same time. If you add an [OR] flag in there, it makes it true if the URI is one or the other:
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} ^/webshop2/localize\.php [NC,OR]
RewriteCond %{REQUEST_URI} ^/webshop2/layoutstripper\.php [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

htaccess to strip www and force SSL

I have what I believe to be a rather well crafted .htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L,NE]
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
This says to me "strip the www. off the url and force https." And it works fine except for those people who happen to type in https://www.somedomain.com/. Those people are presented with a warning that there is a problem with the site certificate. It seems that the www is not getting stripped in this particular case.
You can actually combine both rules into one:
RewriteCond %{HTTP_HOST} ^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L,NE]
Then make sure to clear your browser cache to test this.
However just remember that certificate negotiation between web server and browser happens before mod_rewrite is invoked.