After some digging, there appear to be two ways that avoid hitting the admin and url query strings.
The first, (and apparently better one, as 'if is evil' according to nginx) uses location handlers:
# 301 Redirect for trailing slash
location ~ ^([^.\?]*[^/])$ {
try_files $uri @addslash;
}
# 301 Redirect for trailing slash
location @addslash {
return 301 $uri/$is_args$args;
}
# Root directory location handler
location / {
try_files $uri/index.html $uri $uri/ /index.php?$query_string;
}
The second, more evil one that uses an if statement:
if ($request_uri !~ "^/admin")
{
rewrite ^([^.\?]*[^/])$ $1/$is_args$args permanent;
}
I included the context of the root location handler in the first solution so that you can combine it with your existing root location handling setup. I'm currently leaning on a lot of NYStudio's work (a truly incredible contributor to the open source ecosystem of Craft) with FastCGI, location handlers for foreign languages, etc and both of these solutions work with it.
The first also works with query strings, if a user visits a URL either with or without a trailing slash. For example:
- This: www.domain.com/page?string=234
- Will go to this: www.domain.com/page/?string=234
- And this: www.domain.com/page
- Will go to this: www.domain.com/page/
Interestingly, if you use query_string instead of is_args for the return url, it will rewrite it wrong. Only is_args worked in my experience.