3

I've been researching the best way to handle my htaccess file in order to switch from http requests to https and I've seen everything from basing requests off server ports, using server name requests rather than entering in an actual domain, to editing my apache configuration file and disregarding htaccess completely.

My goal is, of course, the most SEO friendly way to achieve http to https!

Here is my current htaccess rules:

Options +FollowSymLinks 
RewriteEngine on 
RewriteCond %{HTTP_HOST} ^example.com [NC] 
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301]
RewriteRule ^$ /index.html [L]

So what is the most elegant way to make this code force https? This is what I have come up with so far, though untested beyond this tool

Options +FollowSymLinks 
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
RewriteRule ^$ /index.html [L]
4

You do not need rewriting rules for such a simple case, but you can certainly achieve the same goal with them too.

In the specific VirtualHost describing the HTTP host (hence having a :80 at end of address), you just need to have:

RedirectPermanent / https://www.example.com/

See https://httpd.apache.org/docs/2.4/mod/mod_alias.html#redirectpermanent and you have the Temporary version too if you dislike the Permanent one.

Per the documentation, RedirectPermanent X Y is the same as Redirect permanent X Y and permanent is defined as:

Returns a permanent redirect status (301) indicating that the resource has moved permanently.

Also, if you can, indeed editing your Apache configuration and getting rid of .htaccess files is a good direction for many reasons (performances, security, simplicity)

  • Yes- that is what I gathered! The RedirectPermanent will cause a 301 response correct? Which is obviously what I want from an SEO standpoint. Do I add that code to the very top of the server config file? I've yet to mess around with anything in root so I want to be sure I do it right. – Virage May 4 '18 at 20:17
  • @Virage see my edits, the directive must be in the specific HTTP VirtualHost (if you put it outside of any VirtualHost it will apply to all VirtualHost including the HTTPS one and hence creating a fatal redirect loop) – Patrick Mevzek May 4 '18 at 20:26
  • I understand what you mean now- I've never laid eyes on an apache config file so i didn't realize there would be code for different virtual hosts within one file. If I decide to make the change within the config file, I'll still be able to use htaccess for all my specific page redirects? Also, I have some data compression rules for images and css files through mod_deflate in my htaccess- do I need to change these to hours rather than days/weeks so browsers pick up on the new secure content? Sorry for picking your brain, but I really appreciate the help! – Virage May 4 '18 at 20:34
  • 1
    I recommend you make test first on a play server, so that you get used to this new way to configure things. Yes, you are still able to use .htaccess and redirects there (but for other hosts, the one having RedirectPermanent will make other rules disappear normally). I wouldn't mess with your resources caching event if it means people will still query them over HTTP for same time. Make sure they are available through HTTPS too and change the URLs in your webpages to avoid a "mixed unsecure content" error on browsers. – Patrick Mevzek May 4 '18 at 20:37
  • 1
    Your visitors will get the images as written in your HTML files, so if there are img src=https:// in there, then they will access the images over HTTPS and they will not get any error. If they cached the HTTP version previously, it is another URL hence another resource, so it is not taken into account. Double check all your links, including JS, CSS, fonts, etc. besides images. But this is not related anymore to the configuration. RedirectPermanent X Y or RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L] are basically two ways of saying exactly the same thing. – Patrick Mevzek May 4 '18 at 21:02
2

I've seen everything from basing requests off server ports, using server name requests rather than entering in an actual domain, to editing my apache configuration file and disregarding htaccess completely.

Apart from there being "many ways to skin a cat" (because Apache config files are a very flexible/complex beast), the method that is "best" for you can be dependent on many other factors:

  • Your server configuration. (eg. is UseCanonicalName On set?)
  • Do you have access to the main server config or <VirtualHost> container? Or are you restricted to .htaccess (eg. a shared server environment).
  • Are you running your site off non-standard ports?
  • Are you hosting multiple domains off the same vHost?
  • Do you need a generic solution that doesn't explicitly include the hostname? Do you want a solution that can be copy/pasted between hosts? Although a "generic" solution isn't necessarily the best (or "safest") solution for any one host. (Explicitly hardcoding the hostname is often the "safest" solution when anyone is suggesting a method to use, as we don't know how your server is configured.)
  • Are you planning on implementing HSTS? (If so, then you probably don't want to canonicalise the hostname at the time you redirect from HTTP to HTTPS.)
  • How is the security certificate managed for your site? eg. Is the SSL cert installed directly on your application server or are you using an SSL proxy (eg. Cloudflare)? If you are behind an SSL proxy then the HTTPS and SERVER_PORT server variables are probably no good to you. (Some hosts set alternative environment variables to help - but this is server specific.)

So what is the most elegant way to make this code force https?

Well, "elegance" can be subjective.

If you have access to the server config then you shouldn't really be doing this in .htaccess. Instead, you should be using a simple mod_alias Redirect in the relevant <VirtualHost> container - as @PatrickMevzek suggests. This is both "simpler", "safer" and more efficient.

If you later want to implement HSTS (and particularly to get on the HSTS preload list) then this really does become easier to implement in the main server config. To implement this in .htaccess requires additional complexity.

RewriteCond %{HTTPS} off
RewriteRule (.*) https://www.example.com/$1 [R=301,L]

Otherwise, if you only have access to .htaccess then there is really nothing "wrong" with the directive you are suggesting - providing it works. But bear in mind that this won't necessarily work on every server, or be the correct solution in every scenario, and could potentially be (inadvertently) overridden if you have additional .htaccess files in subdirectories.


RewriteRule ^$ /index.html [L]

Aside: This rule should be unnecessary providing you have the DirectoryIndex set correctly? (Unless maybe you have something "special" going on?)

  • Thank you for your thoughtful answer. We have a dedicated host/server not a shared so I do in theory have access to root and the apache config file, but I have never worked in it and have always used .htaccess whenever the need has risen, and it's absolutely what I'm more comfortable with. RewriteRule ^$ /index.html [L] was suggested to me a few years back by another user of this site: webmasters.stackexchange.com/questions/15519/… - granted this was back when we I was on a shared server and I did not have access to the apache config. – Virage May 5 '18 at 20:27
  • Using RewriteRule ^$ /index.html in the context of your other question (to "override" an undesirable redirect) would seem to be a "workaround" for an underlying problem. – MrWhite May 8 '18 at 22:34
1

Another option;

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

You're very close. This is what I use on one of the domains I take care of it and it works flawlessly.

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://www.example.com/$1 [L]
  • Gosh- so close! I'll give this an actual live test this weekend and let you know how it goes, thanks for the help Dave! – Virage May 4 '18 at 20:11
  • "You're very close." - it's the same thing!? (Except this will result in an implicit temporary redirect (not recommended). It should be an explicit permanent redirect as on the OP's original directive, ie. R=301. So, the OPs directive is "more" correct!) – MrWhite May 5 '18 at 11:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.