The rules below are accomplishing what I want, i.e., www to non-www and http to https, however, I have two remaining issues:
Trailing slash should be added to all pages (except pages that end with any type of modifier, e.g., /page#foo, page/foo.jpg, etc.
Here are the current rules in my .htaccess file
RewriteEngine On
RewriteCond %{HTTP_HOST} !=localhost
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
CodePudding user response:
The rules below are accomplishing what I want, i.e., www to non-www and http to https
The rule you posted does not specifically redirect HTTP to HTTPS, since it won't redirect http://example.com/
(HTTP non-www) requests. If you are seeing this redirect then something else is doing it.
RewriteCond %{HTTP_HOST} !=localhost RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Incidentally, the first condition that checks that the Host
header is not localhost
is entirely superfluous since that must be true if the second condition is true. The two conditions are mutually exclusive.
Trailing slash should be added to all pages (except pages that end with any type of modifier, e.g.,
/page#foo
,page/foo.jpg
, etc.)
It's impossible to detect fragment identifiers (aka hash) (ie. the foo
in /page#foo
) in .htaccess
since this part of the URL (ie. #foo
) is not sent to the server as part of the HTTP request. The #foo
part of the URL is only used by client-side code/JavaScript. As far as the server is concerned, there is no difference between /page#foo
and /page
. If this is an issue for you then you can't force the trailing slash in .htaccess
. However, the trailing slash would be added after /page
not after /page#foo
(if that is what you were thinking), ie. /page#foo
would be redirected to /page/#foo
, so this shouldn't be an issue.
You can add the following rule before your existing rule, just after the RewriteEngine
directive:
# Append trailing slash to URL-path if omitted unless it looks like an actual file
RewriteCond $1 !\.\w{2,4}$
RewriteCond %{HTTP_HOST} ^(?:www\.)?(. ?)\.?$ [NC]
RewriteRule ^(.*[^/])$ https://%1/$1/ [R=301,L]
The RewriteRule
pattern ^(.*[^/])$
matches any URL-path that does not already end with a slash. The URL-path is then captured in the $1
backreference. The first condition (RewriteCond
directive) then checks that the URL-path does not end with what looks-like a file extension (ie. a dot followed by between 2 and 4 alphanumeric upper/lowercase characters). The second condition then just captures the domain name less any optional www.
prefix, saving this in the %1
backreference.
This also redirects to HTTPS and non-www domain name, so it avoids a potential second redirect by the rule that follows.
Test first with a 302 (temporary) redirect to avoid potential caching issues.
If you are testing on localhost and localhost does not support HTTPS then modify the rule as follows in order to preserve HTTP on localhost only. For example:
RewriteCond $1 !\.\w{2,4}$
RewriteCond %{HTTP_HOST} ^()(localhost)$ [OR]
RewriteCond s%{HTTP_HOST} ^(s)(?:www\.)?(. ?)\.?$ [NC]
RewriteRule ^(.*[^/])$ http%1://%2/$1/ [R=301,L]