2
votes

A challenge for some altruistic uber htaccess wizard gentleman:

I have been chipping away at a htaccess file for a new site I am working on and just can't crack it. I have each segment working independently - but just cant get them all working together. I am generating the site based on PHP REQUEST_URI. Multiple domains are pointed at the same directory so it has to function for multiple domains. I am trying to accomplish:

  1. multiple domains pointed at same directory,
  2. force non-www,
  3. force trailing slash without extension, and
  4. redirect all non-existent to a specific script

Essentially:

http://www.example.com/dog/cat -> 301 shows as -> http://example.com/dog/cat/ ->but silently redirects to -> http://example.com/script.php

OR

http://www.example.com/dog/cat/pig/bird/walrus -> 301 shows as -> http://example.com/dog/cat/pig/bird/walrus/ -> silently redirects to -> http://example.com/script.php

OR

http://www.example.com/dog/cat.html -> 301 shows as -> http://example.com/dog/cat/ -> silently redirects to -> http://example.com/script.php

OR

http://www.example.com/dog.php -> 301 shows as -> http://example.com/dog/ -> silently redirects to http://example.com/script.php

Thus far I have worked with the following snippets(from memory so forgive me):

Non-www:

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

Strip trailing slash:

RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [L,R=301]

All non-existent to script:

RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*/$ ./script.php [L]

I have had issues with specific parts not functioning at all, to recursive effects, etc. I don't love asking for help, and I have done my best to do my homework, but I just can't figure this one out.

I have found similar questions here, such as:

htaccess add trailing slash and force www with clean urls

Any help is greatly appreciated!

UPDATE:

So I have continued fiddling with the .htaccess file. I added a comment below the question to the effect that I was having trouble with Firefox's "wonderful" address bar search feature redirecting the domain name to search when the domain was non-www and non-trailing slash. Because of this, I changed my scheme to still be consistent (preventing duplicates) but do the opposite: force www and trailing slash.

The following code produces results near what I am looking for:

Options +FollowSymlinks
RewriteEngine On
RewriteBase /

#Redirect Forcing trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ /$0/ [L,R=301]

#Redirect non-www to www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

#Redirect to script
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ script.php [L]

I still need the extension dropped off of non-existent files, i.e.:

www.example.com/cats.html -> www.example.com/cats/

Any advice would mean the world...

1
An interesting development. It seems that when the url is stripped of both www and the trailing slash it sometimes is not recognized in the Mozilla Firefox 16.0.1 address bar as a domain. It automatically forwards to search instead of checking the domain. Based on this, I think the choice of action would be to rewrite to always INCLUDE the slash and always include the WWW.Samantha P

1 Answers

1
votes

You have a problem with your strip trailing slash rule:

RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [L,R=301]

You are matching the same trailing slash again, and adding another one in the redirect. Your target needs to be changed to:

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

This would have definitely caused a redirect loop. Otherwise, the only other problem that may have been an issue is using %{SCRIPT_FILENAME} instead of %{REQUEST_FILENAME}. In most cases, it shouldn't make a difference, but the second one is probably what you really want:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*/$ ./script.php [L]

None of these rules should conflict with each other as long as the 2 redirect rules are before the routing to script.php rule. It's working fine in my blank htaccess file on a vanilla apache install.