4

I've read many articles and cannot seem to get ALL of the combined .htaccess Rewrites to work together. I either get re-direct loops or one or a few do not work at all.

To be clear I'm looking for the following 5 to occur if needed:

  • Ensure www on all URLs
  • Ensure HTTPS for all version of site
  • Remove index.php from url
  • Remove all .php extension / Re-direct to url without .php extension
  • Could be in tandem with the previous: add trailing slash

Some examples:

Here is current .htaccess setup:

<IfModule mod_rewrite.c>
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteBase /

# Remove all .php extensions without interfering with .js or .css.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.(?!js|css)([^.]*)$ $1\.php

# Remove index from url.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index?$1 [L,QSA]

RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php [NC]
RewriteRule ^ %1 [R=301,L]

# Ensure www on all URLs.
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

# Ensure we are using HTTPS version of the site.
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Ensure all URLs have a trailing slash.
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ https://www.example.com/$1/ [L,R=301]

</IfModule>

The above .htaccess is ONLY in my root folder and currently does 3 out of the 5 needed: changes to HTTPS, adds www and removes index.php. It does not remove any other .php files extension nor does it add trailing slash.

ToddN
  • 2,901
  • 14
  • 56
  • 96

2 Answers2

1

I see 2 issues:

Redirect rules appearing after rewrite ones Adding .php should only happen after you ensure corresponding .php file exists.

Have it this way:

Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteBase /

# Ensure www on all URLs.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [L,R=302]

# Ensure we are using HTTPS version of the site.
RewriteCond %{HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302]

RewriteCond %{THE_REQUEST} \s/*(.*?)/index\.php [NC]
RewriteRule ^ %1/ [R=302,L]

RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1/ [R=302,L]

# Ensure all URLs have a trailing slash.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^.]*?[^/.]$ %{REQUEST_URI}/ [L,R=302]

# Remove all .php extensions without interfering with .js or .css.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^.]+?)/?$ $1.php [L]

# Remove index from url.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^.]+?)/?$ index.php?$1 [L,QSA]

Make sure to clear your browser cache before testing this.

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • I have tried the above. It still does the exact same thing (cleared cache as well). For the "about-us.php" it still gives the "about-us.php" along with that, it removes index.php but does not add trailing slash. I think you are on right track, perhaps I have order mixed up. – ToddN Sep 23 '15 at 20:51
  • I tried the above. It does re-direct loops. Also the .js is called like this js.php?js=somejs.js, same with css and images inside css and outside of css. Not sure if that makes a difference, but I doubt thats what is causing the loops. – ToddN Sep 24 '15 at 13:11
  • `https://www.example.com` => Redirect loop `https://www.example.com//` I took out Trailing Slash code and it stops loop. When I take that snippet out it works but when I go to `example.com/faq.php` => `https://example.com/faq/` with a trailing slash but no www – ToddN Sep 24 '15 at 13:31
  • It's very hard to test because I keep getting server time outs and have to wait 5 - 10 min or so =p. I can tell you this doesn't work, but I have to figure out what pieces. Question, is there a way to put much of it into one regex and add [L] so it won't keep redirecting? – ToddN Sep 24 '15 at 14:32
  • 1
    No `L` doesn't stop all the rules it just force `mod_rewrite` to run the loop again. Another problem is that you're not providing enough precise information about the problem to get better help. If problem cannot be duplicated on my Apache there are little chance that I can solve it. – anubhava Sep 24 '15 at 14:40
  • Ok after extensive testing it indeed works! The only issue is if one goes to `http://example.com/index.php` it will include `index` like `https://www.example.com/index/` I would ideally need it to be `https://www.example.com/` – ToddN Sep 24 '15 at 16:30
  • I've tried this, but when using the above .htaccess on the index.php, main page it works fine, but any other page it displays a basic version of the php page? With no JS or CSS by the looks of it? – Geoff Dec 05 '16 at 11:49
  • @Geoff: Please post a new question as it is difficult to understand problem from comments. – anubhava Dec 05 '16 at 14:59
  • 1
    @anubhava have done: http://stackoverflow.com/questions/40976710/sections-of-site-not-working-after-modifying-htaccess-file – Geoff Dec 05 '16 at 16:03
0

Try this to avoid the loop:

#non-www. http to www. https
RewriteCond %{ENV:HTTPS} !on
RewriteCond %{HTTP_HOST} ^(www\.)?yourdomain\.com$
RewriteRule (.*) https://www.yourdomain.com/$1 [R=301,L]

#non-www. https to www. https
RewriteCond %{ENV:HTTPS} on
RewriteCond %{HTTP_HOST} ^yourdomain\.com$
RewriteRule (.*) https://www.yourdomain.com/$1 [R=301,L]

RewriteCond %{THE_REQUEST} \s/*(.*?)/index\.php [NC]
RewriteRule ^ %1/ [R=302,L]

RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1/ [R=302,L]

# Ensure all URLs have a trailing slash.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^.]*?[^/.]$ %{REQUEST_URI}/ [L,R=302]

# Remove all .php extensions without interfering with .js or .css.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^.]+?)/?$ $1.php [L]

# Remove index from url.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^.]+?)/?$ index.php?$1 [L,QSA]
Saulo M
  • 173
  • 2
  • 7