3

When I use these lines in my .htaccess file, everything works well:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://example.com%{REQUEST_URI} [L,R=301]

enter image description here

Then I tried to make it work without manually writing the domain in the URL and tried these lines instead:

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

But now there is an additional redirect when reached from www without https:

enter image description here

I don't understand why, I just replaced the domain with {HTTP_HOST}. When I do that, it redirects from http://www.example.com to http://example.com (since it is my main domain) then http://example.com to https://example.com

If I add this line: RewriteCond %{HTTP_HOST} !^www\. [NC] it does not change anything.

Why does it behave like that and how can I fix the .htaccess file to not having to manually write the URL and directly redirect http://www.example.com to https://example.com?

  • I do not see a "too many redirects" errors in your screenshot. On the contrary all tests end in HTTP code 200 which is what you want. After that it also depends on where your .htaccess file is stored and how your example.com and www.example.com VirtualHost are configured, but you do not show. – Patrick Mevzek Aug 17 '18 at 17:54
  • Sorry if it was not clear, indeed there is not a true error but after that I modified the htaccess there is an additional (and unwanted) redirect. I updated my post to make it more clear. I use a shared hosting from OVH, the .htaccess file and the website files are both stored in /root folder/www/, www. subdomain is just an alias in this case. – imlost Aug 17 '18 at 18:35
1

If you always want to remove the www. from the host name then you should use your first set of rules that contain the domain name. That is because the {HTTP_HOST} variable contains the full host name including any subdomains. So when the site is accessed with http://www.example.com the HTTP_HOST is www.example.com. When you use that variable in the redirect, the www. is included.

If you really object to hard-coding your domain name in that rewrite rule, it might be possible to switch from HTTP_HOST to SERVER_NAME. The server name variable can be made to be your preferred host name as specified in your virtual host configuration, but only if UseCanonicalName on is on there as well. See What is the difference between HTTP_HOST and SERVER_NAME in PHP? Your virtual host configuration would have to be:

<VirtualHost *>
    ServerName example.com
    UseCanonicalName on
    ServerAlias www.example.com
    ...
</VirtualHost>

You may not have such fine grain control over your virtual host directive. Many hosting packages such as cPanal and WHM write the config for you and don't let you modify it. I'd recommend sticking with your hard-coded domain name in your rewrite rule because it is easy to do and it works.

  • Thank you Stephen Ostermiller, that explains why I have not been able to find a solution, you provided a good explanation here. Have a nice day. – imlost Aug 18 '18 at 14:03
1

tl;dr There is something else in your code base that is redirecting. The directives you have posted in the question do not (fully) explain the output you are seeing. In fact, the directives you posted from your .htaccess file may not even be getting processed at all...

(This answer is really in addition to @Stephen's answer and attempts to explain - or question - the results you are seeing.)

When I use these lines in my .htaccess file, everything works well:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://example.com%{REQUEST_URI} [L,R=301]

"everything works well" - Well, these directives can only be responsible for the first two scenarios you mention (ie. from HTTP):

  • http://www.example.com to https://example.com
  • http://example.com to https://example.com

However, these directives won't redirect from https://www (third scenario), as you appear to suggest. They don't canonicalise the www subdomain. Something else is performing this redirection.

I just replaced the domain with {HTTP_HOST}. When I do that, it redirects from http://www.example.com to http://example.com (since it is my main domain) then http://example.com to https://example.com.

Given the directive you posted; this is impossible! Your directive only ever redirects to https, so "something else" must be triggering the first redirect you are seeing to http. (But there should be nothing that occurs before your .htaccess redirect - other than in the main server config, or possibly another .htaccess file, but I assume nothing like that has changed?)

It's possible you are seeing a cached redirect, but you say that you "just replaced the domain with {HTTP_HOST}", so that kind of rules out the cache.

If I add this line: RewriteCond %{HTTP_HOST} !^www\. [NC] it does not change anything.

Well, that should definitely have changed the additional redirect you were seeing above (assuming you added it somewhere before the RewriteRule directive). So, if this didn't do anything then it further suggests that "something else" is performing these redirects and perhaps your directives are not being processed at all!

However, you're suggesting that this additional redirect only started after you "replaced the domain with {HTTP_HOST}" - which appears to be impossible. So, something else must also have changed.


Some of this could be explained with having placed these directives in the wrong order in your .htaccess file. For example, if you were using WordPress (or another CMS that uses a front-controller pattern) and you placed your redirects at the end of the file then for most page requests it won't get processed. But, depending on your config, it might still get processed for your homepage and your static resources.

Any redirects of this nature need to go at the very start of your .htaccess.

And make sure you are not mixing mod_alias Redirect (or RedirectMatch) directives with mod_rewrite RewriteRule. This can result in unexpected conflicts.


...how can I fix the .htaccess file to not having to manually write the URL and directly redirect http://www.example.com to https://example.com?

Aside: If you are intending to implement HSTS then, ironically, you'll need to redirect in two steps (using HTTP_HOST as above). The first redirect goes to HTTPS on the same host, optionally followed by a canonical www/non-www redirect on HTTPS.

To redirect in a single redirect, you don't necessarily need to use the server-config as @Stephen suggests in his answer (although that is a possibility). But if you have access to the server config then there are altogether better ways to do this using mod_alias Redirect and <VirtualHost> containers (quicker and arguably "simpler") - no need for mod_rewrite at all.

However, you can implement this as a single redirect (both HTTP to HTTPS and www to non-www) in .htaccess using something like the following:

RewriteEngine On

RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)\.?$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L]

The above states... for all requests that are either not-HTTPS or where the requested hostname starts www. then redirect to https://<hostname-less-www-prefix>/<URL-path>. This also removes an optional trailing dot in the case of FQDN. The third condition is necessary in order to capture the hostname, less the (optional) www. prefix. This is captured into the %1 backreference.

Note that the above is a 302 (temporary) redirect. Only change this to a 301 (permanent) redirect after you have done your testing and confirmed that it is working OK (to avoid caching issues fogging your tests).

Generalising the directives in this way isn't always the best (or most reliable) solution across systems.

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.