I have been struggling with a silly issue, and I am sure someone has already asked this but I could not locate the correct response here or elsewhere. So here I go. I've set my .htaccess file to redirect all http request to https. Re-writing is also enabled. Everything seems to work fine, however, when I specify a segment with http, the site redirects to https://example.com/index.php. Say for example:

example.com -> redirects correctly to https://example.com
http://example.com -> redirects correctly
example.com/subdirectory -> redirects to https://example.com/index.php
http://example.com/subdirectory -> redirects to https://example.com/index.php
https://example.com/subdirectory -> redirects correctly

If I used navigation links after https://exmaple.com loads, everything is all good.

My rewrite and redirect rules are as follows:

RewriteEngine On
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} (.+)/$    
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ %1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]

RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

What am I doing wrong? Thanks for your time and appreciate any help. Apologies if this is a duplicate and will appreciate a nudge towards the correct direction. Thank you.


Let's go through it:

  • Your first rule essentially sets HTTP:Authorization, which is something strange peculiar for your setup but not unusual...importantly, there is no [L]
  • Second rule says that when you REQUEST_URI that ends in a / but which is not a directory, you grab just that file. IF it matches though, you redirect externally, and we're back to the first rule - the second time we meet this, we should pass it.
  • Third rule says if the request isn't a file, and the request isn't a directory, internally the path should go to index.php and no other rules should match nothing else
  • Finally, your rule which catches all http:// and redirects externally to https:// losing the query string in the process

I can't quite make sense of what's happening and why it's failing, but moving the last rule to be the first rule should fix it.

You may also want to consider switching REQUEST_URI as you would lose any query strings after the path. Instead replace the last line with the following:

RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]

This ensures:

  • http://example.com without a forward slash goes to https://example.com
  • any character (.) after / repeated zero or more times (*) is put in group number 1
  • $1 is added to the end of the URL with the HTTPS protocol
  • Hi, thanks for this. As advised, I've checked by replacing the last line with your suggestion, but it's still the same. Exactly same as before.
    – Avi
    Sep 15 '19 at 1:13
  • @Avi put a very quick answer edit on, will write more thoroughly now
    – LTPCGO
    Sep 15 '19 at 1:40
  • Hey, thank you so much for taking the time to help. Unfortunately, this did not work for me. I must not have followed correctly, I removed lines 7,8,9 and removed "L" from line 6. Last line changed as suggested. The site broke. However, I think moving the https redirection to the top solved my problem. Everything seems to be working. However, when I force the url to use index.php, it does not remove index.php so I followed another example found on SO to fix it. I think I will post as an answer. Again, thanks so much.
    – Avi
    Sep 15 '19 at 2:34
  • @Avi just as a warning, moving it to the top, with the [L] flag, will mean your other rules aren't followed if it is invoked. One of the other rules is interfering, I think it must be RewriteRule ^ %1 [L,R=301] based on your comment (which is actually what I thought when I made my first edit!) ps if it's useful please upvote so that others can recognise it
    – LTPCGO
    Sep 15 '19 at 2:37
  • thank you for the warning, but I do have a little understanding of the L flag. I maybe wrong, but I think in this case, because https rule is a redirect, the parsing engine will hit the .htaccess file again and execute the rules below the second time. Also, I can't seem to upvote because I do not have enough reputation points.
    – Avi
    Sep 15 '19 at 3:09

For reasons I do not understand, moving http to https redirection worked for me. So my file now looks like this.

RewriteEngine On
#Redirect from http to https
RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
#as @LTPCGO suggested, I think I will change the above line to the one below. but i've included to show that it works for now.
#RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]

However, I noticed that if I specify index.php in the url, for example, https://example.com/index.php/subdirectory, index.php is not removed. So I followed @Frédéric Klee's answer (Symfony 2's way of doing it) found here https://stackoverflow.com/questions/9608366/remove-index-php-from-url-with-htaccess. So my rules look like this now,

RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

# Sets the HTTP_AUTHORIZATION header removed by apache
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteRule ^index\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

RewriteRule .? %{ENV:BASE}/index.php [L]

Thank you @LTPCGO for the responses, appreciate it very much.

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.