htaccess remove trailing slash causes redirect loop - .htaccess

I am amending my htaccess file to achieve non-www to www (this is working) plus removing the trailing slash at the end of the URL, e.g.:
www.domain.bc.ca/club/ ---> www.domain.bc.ca/club
www.domain.bc.ca/club/index.html/ ---> www.domain.bc.ca/club/index.html
The portion of the htaccess file is below - the Force www bit is working; the Remove trailing slash bit is not. Help! Many thanks, Amanda.
# Force www.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^domain\.bc\.ca$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#
# Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.+)/$ /$1 [R=301,L]

I'm going to go out on a limb and guess that you're trying to access a directory when this happens. In your example, the "club" seems to be a directory and when you redirect /club/ to /club, a module called mod_dir will redirect it back to having the trailing slash again. There's a really good reason for this, because if the trailing slash is missing for a directory, the directory's contents will be displayed instead of the index file. That means if you were able to go to www.domain.com/club (without the trailing slash), you'd see all the contents of the club directory instead of the club/index.html file.
If that's ok with you, then you can turn off mod_dir by adding this to your htaccess file:
DirectorySlash Off
But then you'd need to internally add the slash back in:
DirectorySlash Off
# Force www.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^domain\.bc\.ca$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#
# Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.+)/$ /$1 [R=301,L]
# Add the slash back
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])$ /$1/ [L]

Related

Remove trailing slash using .htaccess for a particular page

I've modified my .htaccess file to force trailing slashes on all the pages but I'm wondering how to remove the trailing slash in a particular url page? Need help. For example:
abc.com/test successfully redirects to abc.com/test/
But I want to remove that force trailing slash in a particular url of the site,
abc.com/demo/ should redirect to abc.com/demo
Here what I have done so far:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/demo/
RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]
Update:
To remove trailing slashes for multiple urls what would be the code, eg abc.com/demo2/ abc.com/demo3/ abc.com/demo4/ etc.. Any suggestions?
Try :
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/demo/ [NC]
RewriteRule ^demo/$ /demo [L,R]
RewriteCond %{REQUEST_URI} !^/demo [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]

.htaccess Config causing Google Analytics conversions to fail

I have setup my .htaccess to add a trailing slash to each URL, but having done this I can see that my Google Analytics conversions (goal type is 'Destination') do not work.
The page I'm trying to track is:
/thank-you/contact/
And the trailing slash gets added by .htaccess if not already there. In GA I have told it to track 'Begins with' /thank-you/contact, 'Equals /thank-you/contact/' etc. Nothing works.
If I comment out the .htaccess rule that adds the trailing slash the conversion tracking immediately starts working again. Have I got some kind of bad config in my .htaccess?
RewriteEngine On
# add trailing slash
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !index.php
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://mydomain.co.uk/$1/ [L,R=301]
#remove www
RewriteCond %{HTTP_HOST} ^www.mydomain.co.uk$ [NC]
RewriteRule ^(.*)$ http://mydomain.co.uk/$1 [R=301,L]
#remove index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
Try regular expression condition with goal settings
thank-you\/contact.*
trailing .* would match or zero and unlimited characters

How to write a subdomain with htaccess?

I am trying to make a subdomain forward through the htaccess document. The below instructions will forward http://sub.domain.com to the internal structure Root > subfolder > index.php. This all works well.
# REWRITE DEFAULTS
# ====================================================================================================
RewriteEngine On
RewriteBase /
# SUBDOMAIN FORWARD
# ====================================================================================================
RewriteCond %{HTTP_HOST} ^sub.domain.com$
RewriteRule ^(/)?$ subfolder/index.php [L]
RewriteCond %{HTTP_HOST} ^sub.domain.com$
RewriteCond %{REQUEST_URI} !^/subfolder/
RewriteRule ^(.*)$ /subfolder/$1
There is only one (big) downfall with this method. When you try to reach a folder within the subfolder such as Root > subfolder > images by going to http://sub.domain.com/images/ then all works well again, however when you don't end it with a slash http://sub.domain.com/images the url in the address bar will become http://sub.domain.com/subfolder/images/ which is clearly not what I want.
So what if I would add a slash if a slash was forgotten?
RewriteCond %{HTTP_HOST} ^(.*).domain.com$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_FILENAME} !(.*)/$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ http://%1.domain.com/$1/ [L,R=301]
This all works when you have a normal URL (http://www.domain.com/images), because it will detect it is a directory and adds a slash and if it's a file it will omit the slash. However this does not work for our http://sub.domain.com/images example.
Does anyone have an idea how you can make subdomains work properly using htaccess?
That is happening because /subfolder/images is a real directory and mod_dir module adds a trailing slash to all directories by doing a 301 redirect.
You can use it like this:
RewriteEngine On
# add a trailing slash if /subfolder/images is a directory
RewriteCond %{HTTP_HOST} ^sub\.domain\.com$ [NC]
RewriteCond %{DOCUMENT_ROOT}/subfolder/$1/ -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,NE,R=302]
RewriteCond %{HTTP_HOST} ^sub\.domain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/subfolder/
RewriteRule ^(.*)$ /subfolder/$1 [L]

.htaccess force "www." on everything but subdomains and remove trailing slashes

Here's what I have so far:
#Force www.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.*)$
RewriteRule ^(.+)/$ http://www.domain.com/$1 [R=301,L]
However, this messes up all subdomains doing the following redirect:
sub.domain.com -> www.sub.domain.com
And also, its dependant on the domain written on the remove trailing slash bit.
So... two questions.
How do I rewrite the rule on the "remove trailing slash" bit to exclude writing the domain on it?
How do I make a rewritecond to exclude subdomains, without explicitly writing them down, on the "force www." bit?
Examples of desired results -
sub.domain.com/something/ -> sub.domain.com/something
domain.com/something/ -> www.domain.com/something
www.domain.com/ -> www.domain.com
sub.domain.com -> sub.domain.com
Thanks!
Change the www to check for the actual domain:
#Force www.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Or, if you're hosting a bunch of domains, you can check for a name before the TLD:
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^([^.]+)\.([a-z]{2,4})$ [NC]
RewriteRule ^ http://www.%1.%2%{REQUEST_URI} [L,R=301]
As for the trailing slash, you have to be careful that the request isn't made for a directory. Because if it is, and you have DirectorySlash turned on (by default it is on), then you'll cause a redirect loop.
To exclude subdomains, we assume that the first rule redirected the browser to ensure that it started with "www", and since subdomains aren't being redirected to start with "www", we can just check for that:
#Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.+)/$ /$1 [R=301,L]

Remove index.php AND trailing slashes from URL

I've got the following rewrite rules in my .htaccess, the first 4 lines are supposed to deal with allowing to access the site without index.php, and works fine, until I add the last bit which I'm trying to use to remove trailing slashes from the sites URLs.
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1 !^(uploads|cache|themes|default|admin\.php|favicon\.ico|robots\.txt|index\.php) [NC]
RewriteRule ^(.*)$ /index.php/$1
# Remove trailing slashes
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
When I add the last line, and I visit the root of my site, the index.php part gets appended to the URL, why is this?
When I add the last line, and I visit the root of my site, the index.php part gets appended to the URL, why is this?
This is because the rules are applied sequentially. You want the redirect to happen before you route stuff to /index.php. Just swap those rules around:
# Remove trailing slashes
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1 !^(uploads|cache|themes|default|admin\.php|favicon\.ico|robots\.txt|index\.php) [NC]
RewriteRule ^(.*)$ /index.php/$1 [L]
Following rules are work for me.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
#Removing trailing slash
RewriteRule ^(.*)/$ /$1 [L,R]
#Removing index.php
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=302,NE,L]

Resources