2

I'm having trouble with my .htaccess redirects.

I need to forward all URLs to the non www version of the URL using HTTPS and also forward any non secure URLs to HTTPS too. In both cases I need to keep the full URL

I currently have these rules which almost work as I want but they seem to redirect any www traffic to the homepage rather than keeping the rest of the URL.

eg:

http://www.example.com/mycat/mypage.php

would goto

https://example.com/mycat/mypage.php

My current code:

RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_METHOD} !=POST
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

I tried the rules off this link but they seem to get stuck in a redirect loop

htaccess redirect non-www to www with SSL/HTTPS

RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}% {REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

With HSTS (double redirect):

RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} 
[L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
3

Try this:

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

RewriteCond %{HTTP_HOST} ^www.example.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
  • Thanks! Thats done the trick, I find it hard to get my head around this htaccess lark. tried to mark your answer as correct but it says I dont have enough reputation – user3914769 Apr 29 at 14:52
  • No problem. Glad to be of help! – Luis Alberto Barandiaran Apr 29 at 15:05
1

You already have your answer, but just to comment on points raised in your question...

RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_METHOD} !=POST
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

This is a "specialised" redirect. You should only be testing the X-Forwarded-Proto HTTP request header, if you know you are behind a front-end proxy that is managing your secure connection. Otherwise your site is susceptible to a MITM that would prevent the connection being redirected to HTTPS.

This also, potentially, allows insecure POST requests. (Probably to prevent them being "lost" over a 301 redirect - but this is not a "secure" practise.)

I tried the rules off this link but they seem to get stuck in a redirect loop

As stated in the title of that question, those rules do the opposite of what you are trying to achieve. They redirect to the www subdomain, not the domain apex - which would appear to be your goal. If your site/CMS itself canonicalises the hostname (like what WordPress does) then you will get a redirect loop.

1

This is what I use to direct to secure www. version:

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

Leading me to think this would work to send you to a secure non-www version:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.([a-z-.]+?)\.?$ [NC]
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [L,R=301]

I am unable to find the rules I wrote for a site when I had it redirecting to non-www as my clients prefer the url with the www.

Give it a try and let me know if it works, failing that solution I can try provide other work arounds.

  • Your last rule that removes the www subdomain would likely result in a redirect loop (on "most" servers) - as it will simply redirect to itself. SERVER_NAME is the same as HTTP_HOST by default, unless UseCanonicalName On is set in the server config (but if it is then these directives become server-specific). – MrWhite May 1 at 0:45
  • Please help me correct my answer – Jason Is My Name May 1 at 8:24
  • To keep your directives "generic" and not hardcode the domain name, it's a little more complex. You can't use HTTP_HOST (or SERVER_NAME on "most" servers) in the substitution as you need to actually remove the www. part from it. You can do this by capturing the hostname less the www. prefix in the preceding condition and using this backreference in the substitution instead. eg. RewriteCond %{HTTP_HOST} ^www\.([a-z-.]+?)\.?$ / RewriteRule ^(.*)$ https://%1/$1 [L,R=301] – MrWhite May 1 at 17:34
  • Makes sense, is this a tested solution? If so I will thank and update my answer for you... Actually if you could explain the %1/$1 in the rule, that would really help me. – Jason Is My Name May 2 at 8:32
  • 1
    Yes, that should work OK. (It also removes an optional trailing dot in the case of a FQDN.) The %1 is a backreference to the captured group in the last matched CondPattern (ie. the domain name, less the www. prefix). And $1 is a backreference to the captured group in the RewriteRule pattern (ie. the URL-path) - the same as you have in your existing rule. – MrWhite May 22 at 11:38

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.