Redirect not fully-working in spite of following _redirects documentation

I see a few people with _redirects issues but didn’t find a post that matched my exact situation and didn’t seem fair to hijack related posts.

Based on this reference in the docs—https://docs.netlify.com/routing/redirects/redirect-options/#redirect-by-country-or-language — it worked for me only on Safari but failed in Chrome and Firefox (running MacOS Catalina).

I want to redirect based on visitor’s country first then update the path based on the user’s language setting. The instructions, albeit using Israel and Hebrew in its context, is essentially the blueprint I wanted to succeed. My site, too, structures its URL following domain/country/language/*. My specific testing context is this: I have visitors coming from some African countries and I want them redirected to /southafrica; I also have Canadian and US visitors that I’d like to redirect to /northamerica.

Specifically, I have a _redirects file:

/  /northamerica/  302  Country=ca,us
/northamerica/*  /northamerica/en/:splat  302!  Language=en

/  /southafrica  302  Country=ao,bw,cm,cg,cd,ke,mg,mw,mu,mz,na,za,tz,ug,zm,zw 
/southafrica/*  /southafrica/en/:splat  302!  Language=en

# fallback for other countries?
/  /northamerica/en  301

Although my rules show only English at the moment, I wanted to ensure the way the rules are set up perform correctly so I may add additional language redirects.

Additional background:

  • site I am testing is https://dev--almex-group.netlify.app
  • I have a netlify.toml file but it does not contain any redirect rules
  • I am building my site off a Gatsby foundation
  • the _redirects file is stored in the /static folder in the project as per https://www.gatsbyjs.org/packages/gatsby-plugin-netlify/
  • the rules appear to be deployed correctly, build log shows 5 redirect rules processed. All redirect rules deployed without errors.
  • rules were tested successfully in https://play.netlify.com/redirects although I may have specificity in the wrong order
  • Chrome and Firefox only managed to redirect appropriate Africa-originating users to /southafrica which triggered my 404 error rather than have the second redirect. I thought I might skirt this behaviour by employed the force=true flag (! appended to 302) but to no avail:
  • North American users would appear to get redirected to /northamerica/en but apparently only because of the fallback rule; when I removed that rule, users did not get redirected at all when hitting /.
  • Safari correctly redirected users to /southafrica/en and /northamerica/en based on the user’s origin. Inspector showed 2 redirections were detected based on the screenshot below

Hoping someone can shed some light…

—Victor

Unfortunately, we had to go deploy fixes that work properly. We’ve decided to combine the tweak the first rule slightly into a single and allow the user to make their own language determination upon landing:

/  /northamerica/  302  Country=ca,us
/northamerica/*  /northamerica/en/:splat  302!  Language=en

becomes simply

/  /northamerica/en  302  Country=ca,us
/northamerica/*  /northamerica/en/:splat  302!  Language=en

so if we add French and Spanish, we can add
/northamerica/* /northamerica/fr/:splat 302! Language=fr

but this would not be possible:
/northamerica/ /northamerica/fr 302! Language=en

Hey @vict-r,

I’ll link out to the redirects guide for posterity but I’ll summarise a few key points:

  • Redirects are read from top to bottom. When a rule is met, we stop processing. Therefore, you need to think carefully about what you want from your redirects!
  • Your most specific rules should be at the top of your file
  • You can amalgamate ‘country’ and ‘lang’ redirects together
  • With our redirect system at present, ‘country’ codes are more resilient than ‘lang’ codes.

However, all things considered, what you’re trying to achieve is definitely possible.

Your English speaking NA rule may look like:
/* /en/na/:splat 302! Country=ca,us Language=en

Your English-speaking Africa rule may look like:
/* /en/af/:splat 302! Country=ao,bw,cm,cg,cd,ke,mg,mw,mu,mz,na,za,tz,ug,zm,zw Language=en

And you may want to add a fallback of your choosing.

Hope this helps – happy to discuss further!

Thanks for the reply, @Pie

Your second sentence was key:

When a rule is met, we stop processing.

I incorrectly assumed a waterfall effect, that the rules would continue to check for more specific matches. In the future when I want to redirect English, French, Spanish languages, I would incorporate region & language detection into their own lines:
/* /northamerica/en/:splat 302! Country=ca,us Language=en
/* /northamerica/fr/:splat 302! Country=ca,us Language=fr
/* /northamerica/es/:splat 302! Country=ca,us Language=es

I did that as a matter of recourse but this helps clear things up.

One more question for generic and fallback situations. If visitors don’t fall into those criteria (or detection fails) and North America / English is my default, would it be fair to remove the first rule and instead have the following at the end?

/* /northamerica/en/:splat 301

I won’t lie, when I first began using redirects myself, I was under the same impression! However, it’s still possible to make things work without it (and less compute time).

That fallback rule looks fine, unless you have files within the root of your site. For example, if somebody browses to domain.com/index.html and /index.html exists, that will be served. If you don’t want this, you’ll need to force the rule (301!).

1 Like

Hey, Scott, I don’t mean to belabour the point but based on our discussion and what I experienced would you guys consider adding a caveat to the docs? Currently, it reads:

The system is smart enough to flatten chains of redirect. So in the above case, if a user in Israel with Hebrew language preference visits / , they’ll get redirected directly to /israel/he in one step. Our cache server will cache this redirect for any other users that would match the same country and language rules.

It feels like the flattening is unreliable at best. Developers ought to write their rules to be more encompassing to avoid relying on the underlying Netlify mechanism to do it.

Hey @vict-r,

Absolutely appreciate your response and the feedback. We’d love for devs to ensure that their rules are thorough, I agree!

Processing occurs per redirect so I do believe that flattening still serves a purpose. I think this may be a case of “each to their own”, but you (much like I agree with) have a clear style & preference!

Thanks for the follow-up, @Pie!

Yup, devs definitely ought to be able to choose their approach but my comment was more about the reliability of the flattening. If the /israel and /israel/he example in the docs doesn’t work across the board for all browsers, there should be a flag—a caveat emptor at least—to inform devs.

Right now the encompassing rules that don’t require flattening appear to be working well for me but it feels like the behind-the-scenes flattening could use another look-see by your team to vet that they are bulletproof for all browsers.

I’m sorry that sounds like nit-picking. Just looking out for others that have to tread the same path. Regardless, that Netlify has provided geo-based redirect capability is really fantastic. Normally, one would have to own the back-end to be able to apply even some general geo-ip rules. It should go without saying that I’m appreciative of this ‘freebie’ and that I can sit here and discuss its integration for my site and not be wistful for it.

Hey! Nope, not nit-picking at all. If you’re having a better/worse time doing something versus something else, this is useful feedback for us, and other customers; it’s how a product matures!

This said, we do have associated bugs filed for language and country redirects so you may wish to keep an ear to the ground and see if/how they evolve :smile:.

1 Like