Single Hop http to https for non-www or www Domain with .htaccess

In the performance world we generally like to avoid doing unnecessary things because they add overhead. This includes unnecessary redirects, wastes of bandwidth and more. This post will show you multiple ways to force Apache or LiteSpeed to redirect your primary domains from http to https in one single hop to avoid unnecessary redirects. For SEO reasons you should be forcing https once it is implemented, now you can do it even more efficiently.

Please note that OpenLiteSpeed does not support .htaccess files at the time of this writing

Since Google Chrome started warning users about non-https sites that have failed to use SSL, the warning of ‘avoid unnecessary redirects' has become more common. It has also become more common for sites to drop the www in their domain which complicates the unnecessary redirects issue further.

If you use Cloudflare please see this post as a complement to this tutorial

Why are Unnecessary Redirects a Problem?

If you started your WordPress website many years ago when http was the norm, your domain could be something like http://www.example.com. Let's hope by now you have switched to https using SSL certificates to encrypt the connection so your address is now https://www.example.com. Let's imagine you have a visitor who knows your domain and they put in just example.com inthe browser. Here is what happens if you have a generic https redirect:

  1. http://example.com redirects to https://example.com
  2. Your application will change https://example.com to https://www.example.com

You can see how this is pretty inefficient. Ideally we want to redirect the user to the right address as early as possible. The goal is to have the user redirected to your primary domain no matter which variation of your domain your visitor chooses to enter. This yields the following behavior if your primary domain is https://www.example.com:

  1. http://example.com gets redirected to https://www.example.com in one hop
  2. https://example.com gets redirected to https://www.example.com in a single hop
  3. http://www.example.com gets redirected to https://www.example.com in one hop

The following instructions show you how to accomplish this with Apache or LiteSpeed Enterprise with a few lines in .htaccess which you can typically find in your public_html folder.

Single Hop http to http for non-www or www Domains in .htaccess

Final destination https://www.example.com

#BEGIN force https from https://guides.wp-bullet.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTP_HOST} ^(www\.)?hammerpedia\.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
</IfModule>
#END force https

Final destination: https://example.com

#BEGIN force https from https://guides.wp-bullet.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTP_HOST} ^(www\.)?hammerpedia\.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
</IfModule>
#END force https

Instead of detecting the port (80 in the example above) you may need to use RewriteCond %{HTTPS} off to make sure the redirect works.

Final destination: https://www.example.com

#BEGIN force https from https://guides.wp-bullet.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?hammerpedia\.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
</IfModule>
#END force https

Final destination: https://example.com

#BEGIN force https from https://guides.wp-bullet.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?hammerpedia\.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
</IfModule>
#END force https

If you are behind a reverse proxy like Cloudflare or nginx this condition can help make sure the redirect is triggered RewriteCond %{HTTP:X-Forwarded-Proto} !https

Final destination: https://www.example.com

#BEGIN force https from https://guides.wp-bullet.com
<IfModule mod_rewrite.c>
RewriteEngine On 
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP_HOST} ^(www\.)?hammerpedia\.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
</IfModule>
#END force https

Final destination: https://example.com

#BEGIN force https from https://guides.wp-bullet.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP_HOST} ^(www\.)?hammerpedia\.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
</IfModule>
#END force https

These examples should complete the one hop http to https rule for non-www to www!

Now let's test the redirects to make sure they are working 🙂

Testing the Single Hop Redirects

This is an important step to make sure you did the redirects correctly so please do not skip testing!

Linux or Mac Terminal

cURL is by far the simplest method which you can use via the command line in Linux or Mac (in Windows you can use git-bash), I usually add a query string here ?wpbullet at the end to bypass any cache.

No www in Primary Domain

Desired final destination: https://example.com

curl -I http://example.com/?wpbullet

Here is the output, look at the Location header.

HTTP/1.1 301 Moved Permanently
Date: Sat, 06 Apr 2019 21:34:03 GMT
Server: Apache
Location: https://example.com/?wpbullet
Cache-Control: max-age=3600
Expires: Sat, 06 Apr 2019 22:34:03 GMT
Content-Type: text/html; charset=iso-8859-1

Next we try http://www.example.com

curl -I http://www.example.com/?wpbullet

Here is the output, look at the Location header.

HTTP/1.1 301 Moved Permanently
Date: Sat, 06 Apr 2019 21:34:03 GMT
Server: Apache
Location: https://example.com/?wpbullet
Cache-Control: max-age=3600
Expires: Sat, 06 Apr 2019 22:34:03 GMT
Content-Type: text/html; charset=iso-8859-1

Lastly we try https://www.example.com

curl -I https://www.example.com/?wpbullet

Here is the output, look at the Location header.

HTTP/1.1 301 Moved Permanently
Date: Sat, 06 Apr 2019 21:34:03 GMT
Server: Apache
Location: https://example.com/?wpbullet
Cache-Control: max-age=3600
Expires: Sat, 06 Apr 2019 22:34:03 GMT
Content-Type: text/html; charset=iso-8859-1
www in Primary Domain

Desired final destination: https://www.example.com

curl -I http://example.com/?wpbullet

Here is the output, look at the Location header.

HTTP/1.1 301 Moved Permanently
Date: Sat, 06 Apr 2019 21:35:13 GMT
Server: Apache
Location: https://www.example.com/?wpbullet
Cache-Control: max-age=3600
Expires: Sat, 06 Apr 2019 22:34:03 GMT
Content-Type: text/html; charset=iso-8859-1

Next we try http://www.example.com

curl -I http://www.example.com/?wpbullet

Here is the output, look at the Location header.

HTTP/1.1 301 Moved Permanently
Date: Sat, 06 Apr 2019 21:37:17 GMT
Server: Apache
Location: https://www.example.com/?wpbullet
Cache-Control: max-age=3600
Expires: Sat, 06 Apr 2019 22:34:03 GMT
Content-Type: text/html; charset=iso-8859-1

Lastly we try https://example.com

curl -I https://example.com/?wpbullet

Here is the output, look at the Location header.

HTTP/1.1 301 Moved Permanently
Date: Sat, 06 Apr 2019 21:38:35 GMT
Server: Apache
Location: https://example.com/?wpbullet
Cache-Control: max-age=3600
Expires: Sat, 06 Apr 2019 22:34:03 GMT
Content-Type: text/html; charset=iso-8859-1

Testing complete!

Sources

Cloudways What Can I do with htaccess?
For https in cPanel
Forcing https behind Proxy
Inmotion Force https