Geo Ip Redirect and Bypass?

//these countries go to gb

var uk_countries = [‘GB’,‘JE’,‘IM’,‘GG’];
//these go to India
var in_countries = [‘IN’];
//these go to US. Everyone else goes to .com
var us_countries = [‘US’];

addEventListener(‘fetch’, event => {
event.respondWith(Redirect(event.request))
})

function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}

function mapCountry(country_code){
if (inArray(country_code,uk_countries)){
return ‘https://domain.tld/gb’;
}
if (inArray(country_code,in_countries)){
return ‘https://domain.tld/in’;
}
if (inArray(country_code,us_countries)){
return ‘https://domain.tld/us’;
}
//everyone else gets US
return ‘https://domain.tld’;
}

/**

  • Fetch and log a given request object
  • @param {Request} request
    */
    async function Redirect(request) {
    var url = new URL(request.url);

correctHost = mapCountry(request.headers.get(‘CF-IPCountry’));

console.log('redirecting to '+correctHost);
return new Response('', {
    status: 302,
    headers: {
      'Location': correctHost
    }
  })

}

Now the issue is for countries that are not to be directed, do get the correct URL but the error is “Too many redirects”.

Edit. e.g Ip from France get https://domain.tld/ but error of too many redirects.

What is the optimum way to bypass and correct this issue?

The path this code is applied is
https://domain.tld
SSL is FULL
without worker, code domain works fine on https://domain.tld

You have deployed the worker to https://domain.tld, and in the comments you say Everyone else goes to .com/wd, but in the code you say:

//everyone else gets US
return ‘https://domain.tld’;
}

I presume the last return needs to return a different URL.

I apologize, the comments are edited.
We were experimenting if code is working fine,
And if we add /wd in
then it is redirecting correctly to
(https://domain.tld/wd)’;
Then code works fine.

But we need to send all others to https://domain.tld
AKA not redirect but bypass.

So our redirect code is on this route https://domain.tld/ and for other countries we want the URL to remain same and not redirect at all.

Right now your code does a redirect for every request. You want to do a return fetch(request) for the non-matching countries.

There is an example https://developers.cloudflare.com/workers/examples/country-code-redirect that does exactly what you want:

async function redirect(request) {
  const country = request.cf.country

  if (country != null && country in countryMap) {
    const url = countryMap[country]
    return Response.redirect(url)
  }
  else {
    return await fetch(request)
  }
}

const countryMap = {
  GB: "https://domain.tld/gb",
  JE: "https://domain.tld/gb",
  IM: "https://domain.tld/gb",
  GG: "https://domain.tld/gb",
  IN: "https://domain.tld/in",
  US: "https://domain.tld/us",
}

async function handleRequest(request) {
  return redirect(request)
}

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request))
})
1 Like

Okie here is the error for the above example

worker.js:3 Uncaught (in promise) TypeError: Cannot read property ‘country’ of undefined
at redirect (worker.js:3)
at handleRequest (worker.js:24)
at worker.js:28
redirect @ worker.js:3
handleRequest @ worker.js:24
(anonymous) @ worker.js:28
Uncaught (in response) TypeError: Cannot read property ‘country’ of undefined

Edit: Code is working, it seems in console dev this error will come since

DaServaJesus

27d

Where are you editing the worker from? the request.cf object isn’t set in the dashboard editor or cloudflareworkers.com, it’s only set if you use wrangler dev or if the worker is published to the workers.dev subdomain or a custom domain

Edit2: Thank you @michael , I will test more :slight_smile:

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