3

My goals:

1. http://example.com/page/index.php -> https://example.com/page/
2. http://example.com/page/ -> https://example.com/page/
3. http://www.example.com/page/ -> https://example.com/page/
4. Any nonexistent file or directory requests -> index.php?&q=$1 for further processing.

The following rules work fine, but only after a redirect in the browser URL instead of a clean URL. For example, if I request:

https://example.com/page/

I see

https://example.com/index.php?&q=page/

How do I hide index.php?&q=page and show https://example.com/page/ in the URL instead? Before I added HTTPS redirect it worked fine for HTTP. I tried 2 solutions with the same result.

RewriteEngine on
RewriteBase /

Solution 1:

#1 solution:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/ [NC]
RewriteRule ^index\.php$ https://%{HTTP_HOST}/ [L,NE,R=301]

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

RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) index.php?&q=$1 [QSA]

Solution 2:

#2 solution:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/ [NC]
RewriteRule ^index\.php$ https://%{HTTP_HOST}/ [L,NE,R=301]

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

RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301]

RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) index.php?&q=$1 [QSA]
  • Is your .htaccess file located in the document root? Do you have any other directives in your .htaccess file? Any other .htaccess files in subdirectories? Just to confirm... you didn't try both solutions at the same time? Make sure you've cleared your browser cache. – MrWhite Jul 21 '18 at 8:27
  • 1. .htaccess is in the document root 2. No other htaccess in subdirectories 3. Only one solution at time 4. Cache was cleared htaccess contents Options All -Indexes -Includes -MultiViews +FollowSymLinks Header set X-Content-Type-Options "nosniff" Header unset X-Powered-By Header unset ETag FileETag None – Yury Osipenko Jul 21 '18 at 11:44
  • For all first three points, look at the Redirect directive: far enough to handle all simple redirection needs, no need to use the more powerful (hence more complicated) mod_rewrite module. – Patrick Mevzek Jul 23 '18 at 14:18
1

How do I hide index.php?&q=page and show https://example.com/page/ in the URL instead? Before I added HTTPS redirect it worked fine for HTTP.

The code you posted should not result in such a "redirect". And neither should adding the "HTTPS redirect" have affected this.

Unless... you initially added the "HTTPS redirect" at the end of your .htaccess file, after the internal rewrite to index.php?&q=$1. In which case, you would have expected a request for either http://example.com/page/ or https://www.example.com/page/ or http://www.example.com/page/ to have resulted in such an external redirect (as opposed to an internal rewrite) to https://example.com/index.php?&q=page/. HOWEVER, you have stated that requesting https://example.com/page/ (already HTTPS and non-www) results in such a redirect - that would not happen under this scenario.

It's still possible that an earlier (erroneous) redirect has been cached (301's are persistently cached by the browser) and this is what you are seeing here. However, you've stated (in comments) that the (browser? and all intermediary?) cache(s) has been cleared. So, that just leaves "something else" (ie. something else external to the directives you've posted that sets a 3xx HTTP status)?


Additional notes, not directly related to your main problem:

  1. http://example.com/page/index.php -> https://example.com/page/

    RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/ [NC]
    RewriteRule ^index\.php$ https://%{HTTP_HOST}/ [L,NE,R=301]
    

Condition #1 is not satisfied by any of the directives you've posted. The directives you've posted above would only redirect a request for /index.php in the document root, not /page/index.php as you've stated. To redirect /page/index.php, you would naturally need to include the /page path segment when matching the requested URL (and pass this through to the substitution). For example:

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /page/index\.php\ HTTP/ [NC]
RewriteRule ^(page/)index\.php$ https://%{HTTP_HOST}/$1 [L,NE,R=301]

However, I suspect an "any directory" solution would be required. In which case you could do something like the following:

RewriteCond %{THE_REQUEST} /index\.php\ HTTP/ [NC]
RewriteRule (.*)index\.php$ https://%{HTTP_HOST}/$1 [L,NE,R=301]

RewriteRule (.*) index.php?&q=$1 [QSA]

You should probably include the L (last) flag on this directive, in case you add any more directives later in the file. (This would have prevented an erroneous redirect if you had added the HTTPS redirect at the end by mistake.)

And, unless you have a specific requirement, you should be rewriting to index.php?q=$1 (no & after the ?). For example:

RewriteRule (.*) index.php?q=$1 [QSA,L]

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.