Bug in non-trailing slash rewrite

Sounds like with all your constraints, it may not be possible to host your site in its current form on netlify. Sorry we don’t have better news for you!

Thanks for the reply.

The workaround I’ll use for now is to handle the redirection with a short snippet of JavaScript in my <head>.

I wrote a method that checks if the current url is in the form of site.com/foo and redirects it to site.com/foo/ (keeping any query string or hash unchanged). I packaged it as an npm module if anyone else wants to use it.

The README even includes a copy-pastable minified version of the code if you just need a quick fix without requiring modules.


Just wanted to chime in and say I have the exact same issue. I have a few reverse proxies of the following form:

/projectname/* https://build-server-example.com/projectname/:splat 200

If one reads the rule literally, it shouldn’t touch the /projectname url, only the /projectname/* urls. However, it tries to reverse-proxy the /projectname url and all my relative urls, styles and scripts break.

If you visit /projectname without the slash, you would expect it to 404, but it breaks instead.

Like pixelastic, I am planning to add a javascript redirect to my HTML pages - however, because I proxy several projects like this, I will have to add this code to several repositories, so it’s not an ideal solution.

1 Like

Hi @maxlaumeister,

Thanks for that additional context. As fool mentioned, there is an enhancement request for the issue described in this thread and we’ll update here if and when it get implemented.

Sorry for jumping in.

I came across a similar issue. My 404 custom page does not display the correct css whenever the url ends with a trailing slash.

Any thoughts on how solving this issue?

Thank you.

I suspect you are loading the css with relative paths (something like a href=file.css or a href=../file.css). Try using absolute paths like a href=/path/to/file.css instead.

I’m also experiencing the same issue. I have a _redirects file containing:

/blog/*  https://my-blog-app.netlify.com/:splat 200

Before Netlify, I was using GitHub pages for deployment of static pages, and if a user would navigate to /blog, they would be redirected to /blog/ so all the relative paths to assets like CSS and JavaScript are correct.

On Netlify this does not happen. The user stays on /blog, and all the relative URLs are now broken rendering the page without CSS and JavaScript.

After reading everything about redirects and trailing slashes (https://docs.netlify.com/routing/redirects/redirect-options/#trailing-slash) on netlify I came across the “Pretty URL” feature which promises: “Rewrite link URLs to pretty URLs (/about.html -> /about, /about/index.html -> /about/)”. This does nothing unfortunately. Why is this mentioned in the redirect docs if it does nothing for redirects?

What this means, to repeat what @brianzelip said earlier:

This means that Netlify cannot be used as a replacement for what GitHub Pages provides in this matter. Using GH Pages, I had the base custom domain (zelip.me) set from my brianzelip.github.io repo, and any other repo I set to be published via Pages, was available at zelip.me/*. In that GH Pages case, no matter if there was a trailing slash or not, EVERYTHING WORKED as expected.

Hopefully there is an ongoing feature request for this already, but I would like to be able to enable “redirect to trailing slash” feature for redirects. The same way GitHub pages/CDN behaves.

There are also a bunch of people using Gatsby that are having issues with this, you can follow the discussion over at their GitHub repo: https://github.com/gatsbyjs/gatsby/issues/9207


Edit: Upon further investigation I realised the “Pretty URL” does help for the rest of the page: eg /about does indeed redirect to /about/ (if about is a directory containing a index.html file), now if only the same could apply for redirects!

1 Like

Hi @danielstocks, welcome to the Netlify Community!

A great many people (including me) have migrated their GitHub Pages projects to Netlify successfully, so I suspect we can get your setup working, too. It’s hard to help, though, when we can’t try things out. Could you share a link to the site(s) you’re working on?

Hi, Thank you, but I can assure you that this is not working as many people in this thread has described the exact same problem.

https://webcloud-main.netlify.com/ (main page)
https://webcloud-main.netlify.com/Assortment => 200 redirects to => https://webcloud-assortment.netlify.com/

_redirects file:

/Assortment/*  https://webcloud-assortment.netlify.com/:splat 200

As you can see visiting: https://webcloud-main.netlify.com/Assortment is a broken page, visiting https://webcloud-main.netlify.com/Assortment/ everything works as expected. GitHub pages will always redirect to a trailing slash. You can test this with my existing setup here:


^ these are two different repositories on GitHub and two separate GitHub Pages builds.

With that being said: Migrating a single page from GitHub Pages isn’t the issue. It’s trying to migrate the multi-repo one-site/domain setup.

To follow up on this: the only way to get around this now is to inject a JavaScript hack like this at the top of the page.

if(!window.location.pathname.endsWith("/")) {
  window.location = window.location + "/"

This is far from ideal though, Google will still treat my-domain.com/page and my-domain.com/page/ as two seperate URL’s serving duplicate content.

I think the limitation boils down to this https://docs.netlify.com/routing/redirects/redirect-options/#trailing-slash

If it had been possible to do a rewrite rule like this, everything would have been fine:

/Assortment/*  https://webcloud-assortment.netlify.com/:splat 200
/Assortment /Assortment/ 301!

The issue is worse than I thought.

I just found out that:

1.1. If an unknown url ends with a trailing slash (https://www.mywebsite.com/unknownpage/) not only my custom 404 css page is broken but any existing link that’s supposed to take me to one of website page (https://www.mywebsite.com/existingpage) in fact redirects me to another 404 instead (https://www.mywebsite.com/unknownpage/existingpage).
1.2. On the other hand, if an unknown url does not end with a trailing slash (https://www.mywebsite.com/unknowpage) then my custom 404 page css is displayed correctly and any clicked link redirects me to the proper url of an existing page (https://www.mywebsite.com/existingpage).
2. I tried using absolute paths like /css/style.css and it does solve my css issues. However, the problem described in 1.1 still occurs.

Ah, right, @danielstocks I missed that you were requiring a 200 proxy rewrite in your setup. Most folks I know migrating from GitHub Pages use 301 redirects, like:

/Assortment/*   https://assortment.webcloud.se/:splat  301

With that scheme, all links to webcloud.se/Assortment should redirect and display properly, but of course it does change their URL in the address bar. (Incidentally, it does not, however, hurt SEO.)

Personally, I prefer the subdomain pattern (subproject.maindomain.com) over the subdirectory one (maindomain.com/subproject) because I think it signals more clearly that it’s a different site (not just some folder on the main site), and it’s significantly more portable. I totally understand that this isn’t the right choice for everyone, though.

Hi, @tattooseoul. Would you please send us the an actual URL where these issues occur so we can research what is happening?

You can private message (PM) that to one of our support staff if you don’t want to share it publicly. I’ve confirmed that PMs are enabled for your community login. Note, that only one person can see the PM and this will likely mean a slower reply than posting the information publicly. Please feel free to reply to however you prefer though.

Hi @luke. I sent you a PM. Thank you.

Jumping on the train to say I’m running in to the same problem. It looks like the REWRITES are not working with the relative paths. In my example, my rewrite is the following.

/test-site/* https://my-other-netlify-site.netlify.app/test-site/:splat 200!

All of the urls in https://my-other-netlify-site.netlify.app.test-site:splat are relative urls but when the browser is looking for them, they’re searching in / as opposed to /test-site/ .

Hi Drew,

Could you tell us your real site and a URL that shows the problem, so we can look into this and get you the best advice?

Sent you the appropriate links via dm.

Im running into the same issue on docs.mun-lang.org/v0.2

I have a website with a production branch and a deploy branch that I want to serve in the /v0.2/ subdirectory. Both branches use relative urls everywhere.

I have the following redirect rule in place which works just fine.

  from = "/v0.2/*"
  to = "https://release-v0-2.docs.mun-lang.org/:splat"
  status = 200

However, when someone visits https://docs.mun-lang.org/v0.2 without the trailing slash I have to forward them to the same url with a trailing slash otherwise non of my relative urls work.

As stated in the above comments if I could have made a rewrite rule:

/v0.2 /v0.2/ 301!

everything would be just fine.

Hey @baszalmstra et al,

We still have an open feature request for this. If/when this is implemented, or a similar/alternate solution, we will respond to this post. Thanks for your input!

1 Like

As @danielstocks pointed out correctly, there is no obvious way to add a server-side redirect to add a trailing slash due to URL normalization in the Netlify CDN.

In my case, it would have been tedious to add the client-side JavaScript redirect in multiple projects, so I came up with a server-side workaround instead.

The idea: In order to handle my-domain.com/page and my-domain.com/page/ differently, we call a netlify function for both of them, which can distinguish the two and act accordingly:

  • For /page return a redirect to /page/
  • For /page/ return the page root

Assuming that the content for /page/ is hosted at https://separately-deployed-subpage.netlify.app, we can setup the following rules in _redirects:

# Due to URL normalization, this rule actually matches /page and /page/
/page/   /.netlify/functions/addSlash  200

# This matches all other URLs that start with /page/
/page/*  https://separately-deployed-subpage.netlify.app/:splat  200

And the implementation of the netlify function in /.netlify/functions/addSlash.js (note that you will also need to add a package.json file with node-fetch as a dependency:

const fetch = require("node-fetch");

exports.handler = function (event, context, callback) {
  if (event.path.endsWith("/")) {
    // Return the page root
      .then((response) => response.text())
      .then((body) => {
        callback(null, {
          statusCode: 200,
  } else {
    // Return a redirect to /page/
    const location = event.path + "/";
    callback(null, {
      statusCode: 301,
      headers: { location },

This can also be extended to handle different subpages, since the path of the subpage is available in event.path.