1

What's the best way to redirect to a trailing slash in Nginx with Craft CMS? I've seen some advice for Apache .htaccess, etc, but not Nginx. For those curious, here's why I might want to do this: To slash or not to slash.

NYStudio107 recommendations advise removing the trailing slash, but since we were formerly on Wordpress and had a trailing slash to begin with, I want to be consistent with the past history in Google Analytics.

2

Nginx-Craft has an example setup that does this:

https://github.com/nystudio107/nginx-craft/blob/master/sites-available/somedomain.com.conf#L60

# 301 Redirect URLs with trailing /'s as per https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html
rewrite ^/(.*)/$ /$1 permanent;

This is working on the nystudio107.com site, if you go here:

https://nystudio107.com/blog/

...the redirected URL will be this:

https://nystudio107.com/blog

Or am I missing something?

andrew@kotak ~ $ curl -I https://nystudio107.com/blog/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.13.6
Date: Thu, 15 Feb 2018 19:39:49 GMT
Content-Type: text/html
Location: https://nystudio107.com/blog
Connection: keep-alive
Set-Cookie: abtest=green;Path=/;Max-Age=86400;secure; SameSite=strict
Strict-Transport-Security: max-age=15768000; includeSubDomains; preload
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer-when-downgrade
  • Ah! I totally misread that in the example. I'm trying to add trailing slashes, not remove them. Fast response! I've also amended the question/answer. The one thing I still run into is query strings on slashed paths, ie domain.com/path?query=string has issues, whereas domain.com/path/?query=string is fine. Any insight? – hisnameisjimmy Feb 15 '18 at 19:50
  • Nvm, figured it out! – hisnameisjimmy Feb 15 '18 at 23:29
  • Only heretics add slashes. We remove them 😊 – andrew.welch Feb 15 '18 at 23:56
2

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.

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.