1

First of all, I would like to leave remove www and redirect all request to HTTPS like this:

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

Furthermore, I have to make this URL friendly:

RewriteRule ^([\w-]+)/?$ index.php?pg=$1 [L,QSA]

I tried to combine these rules:

RewriteRule ^/?([\w]+) https://%1/index.php?pg=$1 [END,QSA]

But it does not work.

For example, I want these URLs to be redirected:

  • http://www.example.com/index.php?p=home
  • http://example.com/index.php?p=home
  • http://www.example.com/home
  • http://example.com/home

to https://example.com/home (so the user only uses/sees this URL)

  • If by any chance you are using wordpress, you have to change http to https in the relevant section of wp-config file. – deolcarsolutions Jun 29 at 14:52
  • "leave www and redirect all request to https like this" - "like this"? Those directives strip the 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. – MrWhite Jun 29 at 19:14
  • @deolcarsolutions Thanks, but I don't use any CMS System. – Adam Jun 30 at 8:57
  • @MrWhite Thank you, it's useful to know how it work. Can you show me an example to solve? – Adam Jun 30 at 8:58
1

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:

  1. 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.)
  2. 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]
  • Thanks a lot! Do you have any idea why page returns ERR_TOO_MANY_REDIRECTS? In that case I remove line: RewriteCond %{HTTPS} off [OR] page doesn't returns any error (but the rewrite doesn't works well for sure). – Adam Jul 1 at 14:49
  • I changed it to RewriteCond %{HTTP:X-Forwarded-Proto} !http. – Adam Jul 1 at 15:02
  • If testing against HTTPS results in a redirect loop, which is fixed by checking against HTTP:X-Forwarded-Proto instead, then that suggests there is a front-end proxy that is handling the secure connection to the client. The SSL cert is not installed directly on your application server and you are serving plain HTTP to the proxy. – MrWhite Jul 1 at 15:25

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.