Country Specific Redirect

Hi, I am struggling a bit with something and some help would be greatly appreciated!

I am trying to do country specific redirects (so bascially if the user is visiting from South African, I want to to append /en-za/ to the request, and then adding any path following it.

I found this bit of code on StackOverflow and I have adapted it for my needs.

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
})


async function handleRequest(request) {
    const country = request.headers.get('cf-ipcountry')

    const countryMap = new Map([
        ["ZA", 'en-za/']
    ])
    
    //Get value from key
    const countryCode = countryMap.get(country)

    // Redirect to language subdomain for custom countries set
    if (countryCode) {
        const root = "thenerdnetwork.co.za/"
        const url = new URL(request.url)
        const path = url.pathname
        const protocol = url.protocol
        const destinationDomain = protocol + "//" + root + countryCode + path
        return Response.redirect(destinationDomain, 301)
    }        
    
    // Redirect to english domain for any other country
    else {
        const root = "thenerdnetwork.co.za/"
        const url = new URL(request.url)
        const path = url.pathname;
        const protocol = url.protocol
        const destinationDomain = protocol + "//" + root + path
        return Response.redirect(destinationDomain, 301)
    }

    // Process request and return response
    const response = await fetch(request)
    return response
}

but what keeps happening, is it adds is loops with the redirect, resulting in this mess:

https://thenerdnetwork.co.za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/en-za/

I am not too sure what I am do to prevent this, I have searched stack and these forums but with no success.
I have setup the worker route like this:

any help would be greatly appreciated!

You don’t have anything in your code to not add the prefix!

You could add a route for example.com/en-za/ with the Worker set to “None”. This will stop running the worker if the URL already contains the language-country prefix. But this probably will not scale beyond a small number of countries.

Or you could modify the worker to look for the prefix, and make whatever change you need to make (either verify the country is correct and fetch, or change the country and redirect)

Also, the logic as shown above will result in an infinite 301 loop for everybody, not just South African visitors, and the fetch will never be reached.

2 Likes

Hi @michael

Thank you so much, your solution works perfectly. It is perfect for now as we only wanted the south african redirect, but later down the line once we add more countries I will have to relook at things.

I appreciate the response!

Depending on what you want the user experience to be, Transform Rules might also be an option. The docs have some examples that might help. Essentially you could leave the user facing URL alone, but modify the Origin/Cache fetch URL for users in particular countries to have the prefix included.

1 Like
3 Likes

Not that difficult.

You could use switch with (path) with a case to match ther URL. Very simple.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.