Best htaccess method to force site-wide https

Jonathan Greenberg
Jonathan Greenberg used Ask the Experts™
on
Is one way better than another for forcing site-wide https with the htaccess file? Here are a few methods suggested on different websites:

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

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

RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [L,R=301]

Does it make any difference which RewriteCond I use? It looks to me like all three RewriteConds are saying the same thing. Are they essentially interchangeable in achieving my purpose?

Also, the last two RewriteRules differ from the first. I'm assuming the syntax on the first ( ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} ) is correct for my purpose. Is this true?

Thanks!

Regards,
Jonathan
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
nociSoftware Engineer
Distinguished Expert 2018

Commented:
SERVER_NAME & HTTP_HOST might not be the same on shared hosting (or hosting of multiple domains...)
HTTP_HOST is preferred.

The RewriteCond is essential all the same as port 80 isbound to HTTP ...
the first does  an anchored  search to a whole string ^ = begin, $ is end .* = 0 or more any character.

without ^ & $  just an unanchored searched.

and the last is ^ (begin)   and optional /?   followed by some characters...  
.?    match one optional character  would match also (arguably  faster... as * does try to match as mutch as possible, walking the whole string.

Only the last one atualy uses the match results  ($1 in redirect URL).

I don't use apache myself,  you might miss the query string on the first 2 rules.....  so except for the SERVER_NAME the 3rd would be preferred i think.

Author

Commented:
Thak you, noci, for the time you took to answer, but I'm afraid most of what you wrote is incomprehensible to me. My knowledge is limited, and I'm having a problem with your wording and punctuation.

You wrote "The RewriteCond is essential all the same as port 80 isbound to HTTP ...". I don't know what this means. I'm aware that port 80 is for http traffic, while port 443 is for https traffic. The first of the three rules deals specifically with port 80 traffic. Are you making a point that pertains to this fact?

Thanks,
Jonathan
Software Engineer
Distinguished Expert 2018
Commented:
RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTPS} off
are equivalent   as is checking "off" or "!= on"  are equivalent  in a true/false sense.....
They are 3 different ways to express the same.  The Best test (as it expresses what you want most direct way  is)
For rewriteRule {MATCH} {REPLACE} {OPTIONS} ..... the best match is in the last rule
^/?(.*)      will match a / only or any other string as well.... but NOT introduce an extra / on the replacement.
The last rule won't work with shared hosting or hosting on a server with multiple domains... so that needs fixing:
The first 2 rules forget about an optional query string... so they may miss some URL's
So the best set (IMHO) would be:

RewriteCond %{HTTPS} off
RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [L,R=301]
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

Olaf DoschkeSoftware Developer
Commented:
I just have this and it works fine for me:

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

Open in new window


Bye, Olaf.
nociSoftware Engineer
Distinguished Expert 2018

Commented:
Hi Olaf,
that means you will never get the part in an URL after ?xxxxxxxxx
so an URL like:    http://example.com/index.php?query_string

Will match & discard the query string.... no problem if Query string isn't used,  but otherwise there are missing parts.
and return this:    http://example.com/index.php
Dave BaldwinFixer of Problems
Most Valuable Expert 2014
Commented:
I am using this on 4 different sites.  All of them provide both HTTP_HOST and SERVER_NAME variables.  No problems with query strings.
RewriteEngine On 
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]

Open in new window

Olaf DoschkeSoftware Developer

Commented:
I have more rules when %{HTTPS} is on bringing back %{QUERY_STRING}, so this is kept with 301 redirects.

But good point, if you want all in one your rule would take anything of the rest of the URI after the first dash as $1, you might also add %{QUERY_STRING} to my rule to get that part and perhaps even wrap it in ?query=%{QUERY_STRING} for your routing to take it in as $_GET['query'] (or similar), as in

RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}?query=%{QUERY_STRING} [R=301,L]

Open in new window


It just renders all requests for normal files (images etc.) quite useless, therefore I'd relay this to further rules.

Bye, Olaf.
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
Just add QSA to your Flags to ensure the Query String is retained
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,QSA,L]

Open in new window

Olaf DoschkeSoftware Developer

Commented:
Quote from https://httpd.apache.org/docs/2.4/rewrite/flags.html

When the replacement URI contains a query string, the default behavior of RewriteRule is to discard the existing query string, and replace it with the newly generated one.
Which means you only need this QSA flag, when you want to merge query strings.

By the way, the rewrite rule I used was given in my hosters FAQ. Your mileage can vary, as there are options in the servers main configuration that can make the one or other solution preferable. For example about the usage of %{HTTP_HOST} vs. %{SERVER_NAME} see https://stackoverflow.com/questions/2297403/what-is-the-difference-between-http-host-and-server-name-in-php

(The whole discussion is worth reading, not just the best answer. You'll see depending on apache version and configuration one or the other can be better.)

One more tip: Test your rewrite rules by making raw http requests with a tool like cURL and see how your server reacts, preferably with rules applied to a subdomain like test.yourdomain.com and/or on localhost, first.

Bye, Olaf.

Author

Commented:
Thanks to all, and apologies to the three participants without awarded points. I tried to award points to all by using what EE seems to be calling the "Classic View," but the "Assisted Solution" buttons cannot be selected - at least I cannot select them in Firefox on my Mac.

Author

Commented:
Yes, thank you, Julian. But it looked to me like there was a problem with the interface. I'm in Firefox on a Mac (although I doubt it was a browser- or platform-dependent issue), and I was not able to assign points by clicking the Assisted Solution button. The buttons APPEARED functional, in that mouseovers had a visual affect, yet they produced no result.

So, yes, I WOULD like to spread the points a bit, but I'm not sure I'll be able even if you reopen the question.
Olaf DoschkeSoftware Developer

Commented:
Maybe the new system works better with Firefox. As far as I followed other threads about the new system you mark all answers you want to be assists as helpful before picking the main answer.

Bye, Olaf.
nociSoftware Engineer
Distinguished Expert 2018

Commented:
I found that assists could only be selected if the mail solution has been selected. Quite a bummer is they are on opposite ends of a long list and one first has to scroll the whole list and then again the other way.

Author

Commented:
Julian, it worked this time. I think the reason for this is that, as someone just pointed out (sorry, I'm in a popup that's hiding the page, and I can't see who it was), there's a need to select the Assisted Solutions before the Best Solution, and I initially tried this in reverse order.

Thanks again to all who participated!

Author

Commented:
One last thing to all who are interested. I've been using one or the other of these two configurations, and both seem to handle redirection, including query strings, without issue.

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

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

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start Today