Redirect whole site to subfolder except static assets like CSS/JS

Hi!

So we’re currently in the process of making our site multi-lingual. Our plan is to move to sub-folder based language-urls: my-site.com becomes my-site.com/en, my-site.com/cool-stuff becomes my-site.com/en/cool-stuff, etc.

This more or less works if we add language-based redirects to our Netlify config:

/*  /en/:splat Language=en

But now everything gets redirected (incl. CSS and JavaScript files which live in the root of the website and aren’t localized).

Is there a way to get around this?

Thanks in advance.

Flo

Hiya, @flo!

While in theory that would work as you’re intending since /asset.png would be an existing file and you don’t use the syntax to force redirection even when it would shadow a file (cf Redirects and rewrites | Netlify Docs), in practice, language redirects do behave as though they were forced. While this seems to be as designed even though it feels to me like a bug, it makes your use case a bit harder to accomplish

So, you have a few options I can think of:

  1. decouple your assets from your main site (have e.g. a “assets.mysite.com” under which you serve all assets). This could be as simple as a second deploy of your code with a different base directory (/assets) or even just a straight second deploy WITHOUT that redirect to which you could link at the same path (<img src=/asset.png> becomes <img src=https://assets.mysite.com/asset.png>)
  2. duplicate your assets into each language directory. Inelegant, but if you have only a handful, might be simpler.

I am sure there are other options but those are the two I could come up with easily.

I have attached this thread to the feature request to improve the handling of language redirects to NOT always act as forced, so I can follow up here in case that feature changes behavior.

Hi @fool,

Thanks for your response. We went with your second suggestion and it seems to work fine. But just out of curiousity, have you already fixed the shadowing issue? Because I tried it on a test-environment and it seems to work without the work-around.

Best,
Flo

It’s not fixed, but it isn’t consistently broken either in our testing - a lot has to do with whether anyone has already visited the site on a CDN node since last deploy - we’ll often cache the first thing that comes through. If the first request is for https://yourlanguagegatedsite.com/asset.png that will likely work, but if it’s for a path that would require a redirect, that redirect may get cached instead.

The fix you’ve implemented will work either way - whether it happens to work as you’re hoping, or not :slight_smile:

@flo @fool I’ve been seeing the same bug but I’ve worked out another workaround I thought it would be useful to share.

[[redirects]]
from = "/static/*"
to = "/static/:splat"
status = 200
force = true
    
[[redirects]]
from = "/*"
to = "/.netlify/functions/hello/"
status = 200
force = false

If I had just the second redirect it would end up redirecting the static files despite the documentation on shadowing saying it should not. Adding a pointless static -> static folder redirect which should do nothing seems to trick netlify into leaving that folder alone.

thank you for sharing, @dalejefferson_rnf!

As an update to anyone watching this thread or finding it later: language redirects should no longer act as “forced” unless you explicitly configure it (force="true" in netlify.toml or using the ! in _redirects).

Hi,

I tried to follow the trick @dalejefferson_rnf suggested , but it didnt work

[[redirects]]
  from = "/*"
  to = "/build/dokka/html/kotlin-unsigned"
  status = 200

[[redirects]]
  from = "/build/dokka/html/images/*"
  to = "/build/dokka/html/images/:splat"
  status = 200
  force = true

# same for /scripts and /styles

What am I doing wrong?

Hi, @elect86, to answer we need a real URL which should redirect and does not so we can research the issue and find out what is happening. Would you please send us a real URL which should redirect but does not?

@luke

Sure, url is https://unsigned.netlify.app, repo is GitHub - kotlin-graphics/kotlin-unsigned: unsigned support for Kotlin via boxed types and unsigned operators (if you want to check configuration under netlify.toml), but the uploaded file are generated on build, you can find them here

Hi, @elect86. The redirect rule in netlify.toml is this:

[[redirects]]
  from = "/"
  to = "/build/dokka/html/kotlin-unsigned"

I do see this redirect working when I test:

$ curl -svo /dev/null https://unsigned.netlify.app/  2>&1 | egrep '< (HTTP|location)'
< HTTP/2 301
< location: /build/dokka/html/kotlin-unsigned

This is a 301 redirect which is how the rule is currently written (because if no status is defined the rule defaults to a 301 redirect).

Note, the references to some of the other files in the HTML being redirected to are relative paths. They being with ../ which won’t work if you 200 proxy the path / to this page. It would break all those <script> tag src links. With the 301 the path is unchanged so those links work.

    <script type="text/javascript" src="../scripts/navigationLoader.js" async="async"></script>
    <script type="text/javascript" src="../scripts/platformContentHandler.js" async="async"></script>
    <script type="text/javascript" src="../scripts/sourceset_dependencies.js" async="async"></script>
    <script type="text/javascript" src="../scripts/clipboard.js" async="async"></script>

If there are other questions about this, please let us know.

So there is no way to have clean url with relative paths? Have I understood right?

Hi, @elect86. Basically, yes.

If you proxy from https://unsigned.netlify.app/ then the path portion of the URL is just /. If the path is / then the path ../scripts/navigationLoader.js doesn’t exist because ../ means “up one directory” and there is no directory above /.

1 Like

If I replace manually all the relative paths with an absolute one, then I should be ready to go then, or?

Sounds good to me, @elect86!

1 Like