Redirect all trailing slashes globally in express

The answer by Tolga Akyüz is inspiring but doesn’t work if there is any characters after the slash. For example http://example.com/api/?q=a is redirected to http://example.com/api instead of http://example.com/api?q=a.

Here is an improved version of the proposed middleware that fixes the problem by adding the original query to the end of the redirect destination URL. The version also has a few safety features described in the update notes.

app.use((req, res, next) => {
  if (req.path.substr(-1) === "https://stackoverflow.com/" && req.path.length > 1) {
    const query = req.url.slice(req.path.length)
    const safepath = req.path.slice(0, -1).replace(/\/+/g, "https://stackoverflow.com/")
    res.redirect(301, safepath + query)
  } else {
    next()
  }
})

Update 2016: As noted by jamesk and stated in RFC 1738, the trailing slash can only be omitted when there is nothing after the domain. Therefore, http://example.com?q=a is an invalid URL where http://example.com/?q=a is a valid one. In such case, no redirection should be done. Fortunately, the expression req.path.length > 1 takes care of that. For example, given the URL http://example.com/?q=a, the path req.path equals to / and thus the redirection is avoided.

Update 2021: As discovered by Matt, a double slash // in the beginning of the path causes a dangerous redirection. For example the URL http://example.com//evil.example/ creates a redirect to //evil.example that is interpreted as http://evil.example or https://evil.example by the victim’s browser. Also, noted by Van Quyet, there can be multiple trailing slashes that should be handled gracefully. Due to these findings, I added a line that safeguards the path by replacing all consequent slashes by a single /. I trust the performance overhead caused by the safeguard to be negligible because the regexp literals are only compiled once. Additionally, the code syntax was updated to ES6.

Leave a Comment