I have this in my htaccess but can't figure out what its for. Because of the nature of rule, searching doesn't help either.

RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301]

Can anyone please explain what its for?

  • If the request part (the part of the URL after ".com") doesn't end with a / and it doesn't contain a ".", then redirect the request by appending it with a /. The probable intention of this rule is to handle automatic directory indexing. – peterh Mar 19 at 12:08

All this rule does is to add a trailing / to your URLS if there is none and if there is no . in the URI, so https://example.org/test will be redirected to https://example.org/test/, but https://example.org/test.html will not be rewritten to https://example.org/test.html/ (but note: https://example.org/test.case/folder will also not be redirected to https://example.org/test.case/folder/ as it contains a . in the URI).

## Do the following if the URI does not end with `/` or  does not contain an `.`: 
## the . is relevant for file names like test.html, which should n 
RewriteCond %{REQUEST_URI} !(/$|\.)

## Redirect it to the original URI with an added `/` and mark this as permanent:
RewriteRule (.*) %{REQUEST_URI}/ [R=301]
  • "/test.case/folder will also not be redirected" - Minor point, but if "folder" is a filesystem directory, then mod_dir will (by default) issue a 301 redirect to append a trailing slash. It's only an issue if it's /test.case/some-other-virtual-url that should have a trailing slash. – MrWhite Feb 25 at 9:31

Without validating, but using my experience in Apache rewriting, this configuration seems to:

  1. Match on the 'path' part of the URI (not the server, port, or query parameters), for example '/my/location/file.html'.
  2. Match if this part does not end on a '/' (forward-slash) character, -or- does not include a '.' (dot) character.
  3. Use the full path part of the URI and append a forward-slash to it.
  4. Send a HTTP 301 (permanent) redirect to direct the browser to this new URI.

This will result in the following test cases

/ -> / /test -> /test/ /my/resource -> /my/resource/ /my/resource.type -> /my/resource.type /edge.case/resource -> /edge.case/resource

So I think the rule has a purpose of adding slashes to resources that do not seem to be a file, but it seems to have an edge-case.

If not adding a slash to a resource with '.' (dot) character in the non-file part of the path the regular expression should be changed to:

# match paths which do not end with a slash, or do not resemble a file with an extension
RewriteCond %{REQUEST_URI} !(/$|\.[^/]+$)
# redirect permanently to the same uri with a slash
RewriteRule (.*) %{REQUEST_URI}/ [R=301]
  • !(\/$|\.[^\/]*) - Your updated regex is really no different. You need an end-of-string anchor on the 2nd part (that matches the extension) as well. Perhaps something like: !(/|\.[a-zA-Z]+)$ (no need to escape the slashes). – MrWhite Feb 23 at 13:00
  • @MrWhite Good catch! I updated my answer! – Joffrey Feb 23 at 20:39

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.