htaccess redirect non www & HTTP with full URL
As @GeraldSchneider mentioned in comments, your directives are in the wrong order. The external redirects (HTTP to HTTPS and non-www to www) need to go before your front-controller as otherwise they will simply never be processed for anything other than actual file requests. (Your front-controller routes all unknown requests to index.php
and then stops.)
However, your redirects are also incorrect. You are missing the "full URL" from the substitution, so as it stands they will always redirect back to the document root.
So, try something like the following instead:
RewriteEngine On
# Front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
# HTTP to HTTPS redirect
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
# Non-www to www redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) http://www.%{HTTP_HOST}/$1 [R=301,L]
Notes regarding the above directives:
- In the front-controller, there is no need to capture the URL-path (ie
(.*)
) if it is not being used in the substitution. TheQSA
flag is not required here also - the query string from the request is appended by default. - Note the
$1
in theRewriteRule
susbstitution - this is a backreference to the captured URL-path from the request (ie. the "full URL"). This was missing from both your redirects. - You were missing the
[R=301,L]
flags from the HTTP to HTTPS redirect. Without explicitly stating the status code this would have resulted in a temporary 302 redirect and rewriting would have continued. If you intend to implement HSTS later then these redirects need to be separate.
However, if you have access to the server config and you do not intend to implement HSTS then refer to @HBruijn's answer instead.