I tried to combine these rules
It looks like you are literally trying to combine these rules into a single rule?! These are two very different things:
- Canonicalise the URL (ie. remove the www and redirect to HTTPS). (Although you stated you wanted to "leave www" - your examples and directives suggest the opposite.)
- Internally rewrite the request.
As such these should be kept as two separate rules. In which case, the rules you currently have should be working OK as they are? Although you have specified p=
in your URLs, whereas your directive uses pg=
?
In other words:
RewriteEngine On
# Canonicalise the URL - remove www and redirect to HTTPS
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
# Internally rewrite the "pretty" URL
RewriteRule ^([\w-]+)/?$ index.php?p=$1 [L,QSA]
However, you should be consistent: do your URLs end in a slash or not? The above directive currently allows both - which is potentially duplicate content.
http://www.example.com/index.php?p=home
http://example.com/index.php?p=home
The next (optional) step is to redirect any direct requests to a URL of the form /index.php?p=home
(both HTTP and HTTPS, www and non-www) to the "pretty" version /home
. This is, again, a separate task and requires a separate rule.
To clarify... you must already be linking to the correct canonical URL in your HTML source. ie. your links already show /home
and not /index.php?p=home
.
The additional complexity here is that we only want to redirect direct requests and not rewritten requests by the later rewrite.
The following needs to go before the above directives (after the RewriteEngine
directive):
# Redirect "old" URLs to new "pretty" URLs
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^p=([\w-]+)
RewriteRule ^index\.php$ /%1 [QSD,R=302,L]
The QSD
flag (Apache 2.4+) is necessary to remove the query string from the redirected URL. (Or can your old URLs contain additional URL parameters that need to be passed?)
The condition that checks against the REDIRECT_STATUS
environment variable is necessary to prevent a redirect loop.
Change the 302 (temporary) redirect to 301 (permanent) - assuming that is the intention - only when you are sure this is working OK - to avoid caching issues. You will need to clear your browser cache before testing.
In summary:
RewriteEngine On
# Redirect "old" URLs to new "pretty" URLs
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^p=([\w-]+)
RewriteRule ^index\.php$ /%1 [QSD,R=302,L]
# Canonicalise the URL - remove www and redirect to HTTPS
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
# Internally rewrite the "pretty" URL
RewriteRule ^([\w-]+)/?$ index.php?p=$1 [L,QSA]
www
subdomain - but you said you wanted to "leave www"? (However, looking at your examples later it looks like you do want to strip the www, not "leave" it?) "I tried to combine these rules" - if by "combine" you mean combine into a single rule, then you can't do that. These rules need to be kept entirely separate - they do entirely different things.