Redirect path with trailing slash to one without

I would like to have a path with a trailing slash redirect to a path without, so there is no duplicate content (which I believe is better for SEO) using something like this:

get "/posts", PostsController, :index
get "/posts/", Redirect, to: "/posts"

(where Redirect is a simple plug that just redirects to the to: parameter)

However this does not work as both /posts/ and also /posts match the first rule.

The only other way I can think to do it is with a plug that intercepts specific paths and performs a redirect, however this is a bit ugly as it means I have to define these paths outside of router.ex so it’s not clear looking in one place what all the routes are, also this solution won’t cope with paths defined within a scope block.

Is there a better way to do this?

(which I believe is better for SEO)

As a counter-point, the Google claims that “Many sites have duplicate content. Our indexing process often handles this case for webmasters and users. While it’s not totally optimal behavior, it’s perfectly legitimate and a-okay.” – To slash or not to slash

That said, what you are trying to achieve seems reasonable. However, even if doubling up the routes as in your example is possible, it does not seem desirable. It would be better to handle the redirect in one place for all routes.

I don’t believe that Plug normalizes away the trailing slash, so as you suggest you could have a plug that checks the request_path and redirects any trailing slashes. However, it sounds like from your post you only want a subset of paths to have the redirect?

Is there a better way to do this?

If you’re using a reverse proxy like Nginx you can do the redirects there instead of in your app.

Or you can just be careful to generate your URLs consistently (without the trailing slash), and ignore the issue (like many of us do).