I want to force trailing slashes in folders and not trailing slashes in files. I want a way to avoid possible duplicates.
I found that answer: Htaccess: add/remove trailing slash from URL
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R] # <- for test, for prod use [L,R=301]
I tried in my .htaccess and it seems to work well
But I found in the Apache documentation that a similar code could cause "processing overhead"
http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
I do not know if I understand that objection. Is that applied to that code too? Is it a good practice to put that in the .htaccess to force the right trailing slash when it is necessary? If not what is the best way to do it?
I tried in my
.htaccess
and it works very well
Are you sure? (Maybe it works for your particular case??) But you're not supposed to use those two rule blocks together, they do the opposite. The first one removes a trailing slash (for non-directories) and the second rule appends a trailing slash (for non-files).
For example, if you made a request for /foo/
, where /foo
neither maps to a directory nor a file then you'll get a redirect loop. The trailing slash is removed, then appended, etc. etc.
that forces trailing slashes in folders and not trailing slashes in files
Well, actually, neither of those rules "forces trailing slashes in folders". Providing you have DirectorySlash On
(the default) then mod_dir forces the trailing slash on directories (with a 301 redirect).
could cause "processing overhead"
The processing overhead is the checking for the existence of a directory and/or file on every request (that matches the RewriteRule
pattern). Yes, this is an overhead - however, it is considered marginal, as overheads go. Most CMS use a similar technique with their front controller, for example:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
However, this can be optimised. You can include an exception at the start of the file for "what looks like" static resources (images, CSS, JS, etc.) and prevent the directory/file check for these requests. For example:
RewriteRule .\.(jpe?g|png|gif|css|js)$ - [L]
This simply checks for any requests that end in those file extensions and stops further processing, so no directory/file checks are performed for these requests.
RewriteRule ^(.*[^/])$ /$1/ [L,R] # <- for test, for prod use [L,R=301]
Aside: (Just in case this is in your actual code.) Apache doesn't actually support line-end comments. It will "work" in this case, but future edits could potentially break horribly, so best avoided. See my answer to this other question: https://stackoverflow.com/a/31770372/369434
I want to force trailing slashes in folders and not trailing slashes in files.
UPDATE: I assume we are only dealing with physical files and directories, no virtual URLs being routed with a front controller etc.
In which case, you shouldn't have to do anything to force trailing slashes on directories (as mentioned above). Providing DirectorySlash Off
is not set then you should already be good to go. This enables mod_dir to automatically append a trailing slash (via a 301 redirect) when requesting a directory that doesn't have a trailing slash. (The second rule you posted does the same thing, but is superfluous if mod_dir is doing its thing.)
To remove trailing slashes from files then you would need just the first rule of the two you posted:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R,L]
This removes the trailing slash if it is present on the request and it's not a request for a physical directory. It's difficult to optimise this further. The rule is only processed if there is a trailing slash to begin with - so the number of requests being caught should be minimal. It is, however, important that you are already linking to the canonical (non-trailing slash) URL in your application.
The optimisation mentioned above to exclude static resources is optional. If you have no other mod_rewrite directives in your .htaccess
file then it offers little/no benefit.