39

I have the following code in my htaccess file:

# Force Trailing Slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]

That seems to work fine when I go to www.mydomain.com/test it redirects it to /test/. The problem is when I go to www.mydomain.com/test/another it doesn't put the trailing slash on another.

Does anyone know how to modify my code to make the trailing slash work no matter how long the URL is?

Thanks!

Drew
  • 6,736
  • 17
  • 64
  • 96

10 Answers10

72

A slightly more robust answer, based on the answer above:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)([^/])$        /$1$2/ [L,R=301]

The RewriteCond will check to make sure there's no files with that name, and if not, perform the RewriteRule. More future-proof than having a manual list of extensions!

jeffbyrnes
  • 2,182
  • 2
  • 22
  • 33
  • I tried this, but it is adding a trailing slash on files that end in .html – moobot May 30 '13 at 10:42
  • If the URL leads to a real file, it shouldn't be hitting this rule; are you unnecessarily adding `.html` to your "nice" URLs? – jeffbyrnes May 30 '13 at 14:43
  • 1
    Not me, but I guess Magento is! Thanks for the reply, I did however find a redirect which is only adding it to URLs without extensions: http://www.paulund.co.uk/using-htaccess-to-force-trailing-slash – moobot May 31 '13 at 02:33
  • Ah, yeah, Magento does that by default. There's lots of great SEO/usability reasons to change that behavior of Magento's, if you can. – jeffbyrnes May 31 '13 at 13:57
  • 1
    This answer also worked wonders for me. Only problem I ran into was my redirect pointing to a weird server path. I fixed this by adding `RewriteBase /`. This made the redirect work like a charm! – Martie Jun 06 '14 at 08:09
  • 1
    This worked perfectly for me. Thanks! When trying this or any solution, remember to clear your borwser's cache. – Tomas Gonzalez Jul 31 '14 at 15:41
36
RewriteRule ^(.*)([^/])$ http://%{HTTP_HOST}/$1$2/ [L,R=301]

Edit: in the case you want to exclude some requests like for php files:

RewriteCond %{REQUEST_URI}  !\.(php|html?|jpg|gif)$
RewriteRule ^(.*)([^/])$ http://%{HTTP_HOST}/$1$2/ [L,R=301]
undone
  • 7,857
  • 4
  • 44
  • 69
  • 1
    You may also want to include css and js. This is very useful! – Eruant Mar 12 '13 at 12:40
  • @undone Might I ask what the `?` after html stands for, and why you didn't put `php?` with the question mark? – Daniel W. Feb 14 '14 at 14:21
  • 10
    @DanFromGermany question mark in regexp indicates that preceding character (in this case **l**) , may or may not exists in the string. so in can cover both **htm** and **html** extensions! – undone Feb 14 '14 at 20:10
7

While Death's solution works it can be annoying when you forget to add certain file types to the list. You can do this to force trailing slash for all URLs that do not point directly to a file using !-f in the condition.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301]
Community
  • 1
  • 1
Henry Heikkinen
  • 1,058
  • 11
  • 9
  • I tried this, but it is adding a trailing slash on files that end in .html – moobot May 30 '13 at 10:44
  • I tried this as well, but still see trailing slashes added to pages like sitemap.xml. Is it possible that the server settings decide what is viewed as a file to be downloaded and one to be rendered in the browser, and this affects how `!-f` is interpreted? – Mattypants Sep 12 '16 at 06:02
3

The accepted answer didn't work for me. This did, from SEOMoz:

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

Note the RewriteBase / for each rule. At least, when I removed it, it stopped working.

Raunak Gupta
  • 10,412
  • 3
  • 58
  • 97
Henrik Erlandsson
  • 3,797
  • 5
  • 43
  • 63
1

This is working perfectly for me. ( from comment of user Ajax )
The problem with other links was my CSS stopped working after applying the redirect rule but CSS is also working fine with the below rewrite rule

RewriteRule ^((.*)[^/])$ $1/ [L,R=301]

Complete code

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !(.*)/$
    #Force Trailing slash
    RewriteRule ^((.*)[^/])$ $1/ [L,R=301]
</IfModule> 
Abhishek Goel
  • 18,785
  • 11
  • 87
  • 65
0

This works just fine for me and doesn't rely on evaluating to an actual file as some have suggested the '-f' flag:

RewriteCond %{REQUEST_URI} !\.[a-z0-9]+$ [NC]
RewriteRule ^(.*)([^/])$ http://%{HTTP_HOST}/$1$2/ [L,R=301]
Erutan409
  • 730
  • 10
  • 21
0

Above examples didn't work for me thanks to forced slash on the end of rule, e.g. $1$2/ .

For me worked this (I used it for wordpress and redirecting to HTTPS). You have to add the condition and rule lines just behind RewriteEngine and RewriteBase lines:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# I added these two lines for redirect to HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://www.yoursite.com/$1 [R=301,L]

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress`
David Najman
  • 487
  • 4
  • 7
0

To force the trailing slash, you can use :

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]

Note mod-dir module that runs before the mod-rewrite automatically adds a trailing slash when it sees a request for an existant dir ,so we have to exclude directories from the rule otherwise using the rule without RewriteCond %{REQUEST_FILENAME} !-d on some servers, you will end up at /dir// or it can cause problems if you have turned off the directorySlash .

The rule above adds a trailing slash to all requests including files with extension, if you dont want your files with a trailing slash, you can exclude them by adding the following condition above the Rule

RewriteCond %{REQUEST_FILENAME} !-f
Amit Verma
  • 40,709
  • 21
  • 93
  • 115
0
RewriteRule ^(.*)[^/]$ $1/ [L,R=301]

This should work pretty well. It just checks to make sure the trailing character isn't a slash and adds one.

Dan Ambrisco
  • 865
  • 7
  • 13
-3
<rule name="Remove trailing slash" stopProcessing="true">
    <match url="^([^.]+)/$" />

add this rule in your config file and it is working for me

bcsb1001
  • 2,834
  • 3
  • 24
  • 35