So, lets start with the actual rewriting bit, here’s a rule that should set you in the right direction to start:
RewriteRule ^(.*)/$ /$1 [L,R=301]
After all, what more could you possibly need? That’s it right? Wrong! Turns out that this works with all requests, most importantly please take note that it works with POST requests too. So say you’re submitting a form on your website, and it posts to a path that redirects, it’ll screw it up! You’ll have a bad time, and so will your clients! With an additional line using the Mod_Rewrite variable “%{REQUEST_METHOD}”. You can fix this issue like so:
RewriteCond %{REQUEST_METHOD} =GET
RewriteRule ^(.*)/$ /$1 [L,R=301]
This limits the redirect to only work with GET requests, obviously this rule will now be ignored on POST, so your enquiry forms should now be all ok! The next step is to ignore the backend areas for your CMS, you can do this by ignoring the path to it with another Mod_Rewrite variable “%{REQUEST_URI}”. Here we are saying we don’t want the rule to happen IFthe path starts with “/admin”, this also works with anything that follows after, like this “/admin/tools”:
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{REQUEST_URI} !^/admin(.*)?
RewriteRule ^(.*)/$ /$1 [L,R=301]
Lastly you’ll probably want to ignore files & directories too, you can do this by using %{REQUEST_FILENAME}:
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{REQUEST_URI} !^/admin(.*)?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
Craft CMS
At the time of writing this, craft currently has an option in the config which does half the job:
'addTrailingSlashesToUrls'=>false
If you set this option in the config to true, it adds a trailing slash & it redirects you automatically if you’re not on the trailing slash. But what if you want to remove it? Setting the option to false doesn’t give you the behaviour we desire, it lets you view the same page with & without the slash. So we need to keep the setting as false, so we can redirect it ourselves. Once set to false you can redirect the slash like so:
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{REQUEST_URI} !^/admin(.*)?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)/$ /$1 [L,R=301]
Concrete5
Notice that both “dashboard” & “concrete” are ignored by the rewrite
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{REQUEST_URI} !^/dashboard(.*)?
RewriteCond %{REQUEST_URI} !^/concrete(.*)?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
ExpressionEngine
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteRule ^(.*)/$ $1 [L,R=301]
Lemonstand
Where you see “# All other requests”, in the existing .htaccess file, add in the two lines below it (above the main index.php rewrite rule), positioning this rule in this particular file may need some trial and error (dependant on what you’ve already got setup), though what I’ve suggested should work just fine. Please note, you need to exclude the javascript combine path, otherwise your combined javascript files may not load.
# All other requests
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{REQUEST_URI} !^/ls_javascript_combine
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
Fancy a good ol' chat about the values of marketing to your business?
Drop Us a LinePost by

Having worked with a large range of web apps and technologies, Joe calls on many years' experience in website development. Whether working on an existing site or coding a new one, Joe's passion is in making application performance optimal.
Project