81

I've got several domains operating under a single .htaccess file, each having an SSL certificate.

I need to force a https prefix on every domain while also ensuring www versions redirect to no-www ones.

Below is my code; it doesn't work:

RewriteCond %{HTTP_HOST} ^www.%{HTTP_HOST}
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI}/$1 [R=301,L]

What I want to achieve is to: redirect something like https://www.example.com to https://example.com.

What am I doing wrong and how can I achieve it?

nyedidikeke
  • 6,899
  • 7
  • 44
  • 59
aegenes
  • 1,051
  • 3
  • 14
  • 16
  • Hope this helps, it also explains which is best for SEO too. https://wpza.net/redirect-wordpress-to-https-using-htaccess-file/ – WPZA Jan 28 '19 at 20:05

9 Answers9

117

www to non www with https

RewriteEngine on

RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
David Morales
  • 17,816
  • 12
  • 77
  • 105
Rajith Ramachandran
  • 1,319
  • 1
  • 9
  • 10
  • 4
    "RewriteRule ^(.*)$ http://%1/$1 [R=301,L]" was changed to "RewriteRule ^(.*)$ https://%1/$1 [R=301,L]" (by @KenVerhaegen) otherwise "it would first redirect to non-http, and then to https... so now we can avoid the possibly triggered second redirect." – alexbt Oct 31 '16 at 02:15
  • Really simple and match, this should also the right answer for [*this question*](https://stackoverflow.com/questions/21467329/htaccess-force-https-and-redirect-www-to-non-www-but-no-other-subdomains) – eQ19 May 01 '18 at 23:55
  • 1
    no matter what i try, it doesnt work for Safari and Firefox. Chrome is ok. any solution would help - i have certificate only for https://example.com - not for https://www.example.com – Kalpesh Popat Sep 08 '18 at 05:11
  • 3
    @KalpeshPopat: This was probably because your browser cache kept the info where to go when you enter the URL. As soon as the DNS/browser cache update, it will work. – Armin Hierstetter Apr 21 '20 at 15:00
  • is this answer working in 2021? I tried but I am getting the error "The page isn’t redirecting properly" in firefox. – user9437856 Apr 22 '21 at 03:14
61

Ref: Apache redirect www to non-www and HTTP to HTTPS

http://example.com

http://www.example.com

https://www.example.com

to

https://example.com

RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]

If instead of example.com you want the default URL to be www.example.com, then simply change the third and the fifth lines:

RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [L,NE,R=301]
Community
  • 1
  • 1
Chanuka Asanka
  • 2,798
  • 3
  • 24
  • 36
  • For redirecting to Non-WWW URL with HTTPS this answer with the first section is absolutely perfect and works fine for me. – Tofiq Quadri Apr 02 '20 at 05:57
  • 1
    After this many years still your answer is charm. – visrey Dec 02 '20 at 18:43
  • This worked. But make sure this is on the top of your .htaccess file and not below, because other code may overwrite it. – Elron Sep 25 '21 at 05:07
  • It won't redirect https://www.example.com to https://example.com – SuperBerry Dec 27 '21 at 04:15
  • Where should i add my domain name in this code : RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]. What is the meaning for %1 and {REQUEST_URI}? – Uma Mar 04 '22 at 06:45
  • not working if domain has some request after .com example https://www.sample.com/products how to make it work for it? – sanjeet bisht Apr 14 '22 at 09:51
  • While this does work for me, it makes two redirects... and for some reason the first of those two is always a 302 redirect. This is considered an error in SEO tools like SEMRush. Does anyone know how to overcome that first 302 redirect that this code seems to trigger? – Eric K Mar 28 '23 at 11:46
23

Your condition will never be true, because its like "if (a == a + b)".

I'd try the following:

RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule ^.*$ https://%1/$1 [R=301,L]

This will capture "google.com" from "www.google.com" into %1, the rest in $1 and after that combining the 2, when HTTP_HOST starts with www (with or without https).

Fabian
  • 13,603
  • 6
  • 31
  • 53
  • Unfortunately this still creates a "Connection is Untrusted" error when someone tries to access https://www.domain.com – aegenes Oct 13 '09 at 14:01
  • 1
    Hmm but it is redirecting properly? If it is it might be a certificate issue. – Fabian Oct 14 '09 at 08:22
  • 2
    See [this](http://stackoverflow.com/a/10726167/372643) for the certificate issue. – Bruno Jul 24 '12 at 23:05
  • 11
    RewriteRule ^.*$ https://%1/$1 [R=301,L] wasn't working for me. if I went to http://www.mysite.com/some/path it was redirecting to just http://mysite.com if you change this to RewriteRule ^(.*)$ https://%1/$1 [R=301,L] (note the brackets) then it redirects as expected to http://mysite.com/some/path – John Sep 23 '13 at 15:39
15

To enforce non-www and https in a single request, you can use the following Rule in your htaccess :

RewriteEngine on

RewriteCond %{HTTP_HOST} ^www\. [OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$
RewriteRule ^ https://%1%{REQUEST_URI} [NE,L,R]

This redirects http://www.example.com/ or https://www.example.com/ to ssl non-www https://example.com/ .

I am using R Temp Redirect flag for testing purpose and to avoid browser caching. If you want to make the redirect permanent , just change the R flag to R=301 .

Amit Verma
  • 40,709
  • 21
  • 93
  • 115
  • 2
    hmm but still when I enter site with www safari says that the page is insecure and opera does not want to redirect any option with or without www to ssl, why? – Hubert Kubasiewicz Dec 11 '17 at 11:19
  • this is giving too many redirects – user151496 Nov 28 '22 at 10:07
  • @user151496 Try clearing your browser cache. – Amit Verma Nov 28 '22 at 13:35
  • of course i did that – user151496 Nov 29 '22 at 10:37
  • @user151496 This code works perfactly fine on apache server. Are you sure you are not using any load balancing or proxy server like Cloudflare? If you are using CloudFlare then this wont work. Please confirm. – Amit Verma Nov 29 '22 at 17:44
  • no, it's a regular apache server on a regular vps, no cloudflares or load balancers. actual server running apache `2.4.38` and the above code gives too many redirects. i have one server where it works and on this one it doesn't. the commands that worked on this particular server were: ` RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ https://%1/$1 [R=301,L] RewriteCond %{HTTP:X-Forwarded-Proto} !=https RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]` – user151496 Dec 01 '22 at 09:30
  • i think your one didn't work because {HTTPS} is not available on all servers, that one supported `%{HTTP:X-Forwarded-Proto}` instead – user151496 Dec 01 '22 at 09:32
  • @user151496 yes, thats because you are using a proxy server. `{HTTP:X-Forwarded-Proto}` is a variable its used to test URL scheme on proxy . – Amit Verma Dec 01 '22 at 17:33
10
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]

This works for me perfectly!

Roga Men
  • 512
  • 6
  • 16
5

Certificate must cover both www and non-www https. Some provider's certs cover both for www.xxxx.yyy, but only one for xxxx.yyy.

Turn on rewrites:

RewriteEngine On

Make all http use https:

RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://xxx.yyy/$1 [L,R=301]

Make only www https use the non-www https:

RewriteCond %{SERVER_PORT} 443
RewriteCond %{HTTP_HOST} ^www[.].+$
RewriteRule ^(.*)$ https://xxxx.yyy/$1 [L,R=301]

Cannot be processing non-www https, otherwise a loop occurs.

In [L,R=301]:

  1. L = If the rule was processed, don't process any more.
  2. R=301 = Tells browser/robot to do a permanent redirect.

More generic

A more generic approach -- not port-dependant -- is:

RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^(.*)$ https://xxxx.yyy/$1 [R=301,QSA]

to make any url with www drop it.

RewriteCond %{HTTPS} !on
RewriteCond %{HTTPS} !1
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP:X-Forwarded-SSL} !on
RewriteRule ^(.*)$ https://xxxx.yyy/$1 [R=301,QSA]

to force any non-https url, even for those system downstream from load-balancers that drop https, use https.

Note that I have not tested the forwarded options, so would appreciate feedback on any issues with them. Those lines could be left out if your system is not behind a load-balancer.

TO HTTP_HOST or not

You can use ${HTTP_HOST} to be part of the URL in the RewriteRule, or you can use your explicit canonical domain name text (xxxx.yyy above).

Specifying the domain name explicitly ensures that no slight-of-hand character-bending means are used in the user-supplied URL to possibly trick your site into doing something it might not be prepared for, or at least ensures that the proper domain name appears in the address bar, regardless of which URL string opened the page.

It might even help convert punycode-encoded domains to show the proper unicode characters in the address bar.

Patanjali
  • 893
  • 13
  • 17
4

This worked for me:

RewriteEngine On
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Mike Gifford
  • 641
  • 1
  • 8
  • 17
3
RewriteEngine On

RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule ^.*$ https://%1/$1 [R=301,L]

RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

This worked for me after much trial and error. Part one is from the user above and will capture www.xxx.yyy and send to https://xxx.yyy

Part 2 looks at entered URL and checks if HTTPS, if not, it sends to HTTPS

Done in this order, it follows logic and no error occurs.

HERE is my FULL version in side htaccess with WordPress:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule ^.*$ https://%1/$1 [R=301,L]

RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]


# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
1

To me was better hardcoding "example.com" as string, so I need less rules, even you can use it to redirect from .org to .com or similar too:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
  RewriteRule ^ https://example.com%{REQUEST_URI} [L,NE,R=301]
</IfModule>