GeoIP redirection worker


#1

So, I’ve been tooling around with the worker playground and have come up with the following… Just sharing in case anyone wants to a) use this or b) pick holes in it :slight_smile:

//these countries go to .co.uk
var uk_countries = ['GB','JE','IM','GG'];
//these go to .ie
var ie_countries = ['IE'];
//these go to .eu.  Everyone else goes to .com
var eu_countries = ['AM','BH','CY','EG','IR','IQ','IL','IT','JO','KW','LB','OM','PS','YD','QA','SA','SY','TR','AE','YE'];
//these IP addresses don't get redirected
var bypass_ip = ['213.48.246.113'];
//user agents containing any of these strings don't get redirected
var bypass_ua = ['googlebot','bing'];


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 byPass(request){
  if (inArray(request.headers.get('CF-Connecting-IP'),bypass_ip)){
    return true;
  }
  var length = bypass_ua.length;
  for(var i = 0; i < length; i++) {
        if(request.headers.get('user-agent').includes(bypass_ua[i]))
        return true;
    }
  return false;

}

function mapCountry(country_code){
  if (inArray(country_code,uk_countries)){
    return 'www.website.co.uk';
  }
  if (inArray(country_code,ie_countries)){
    return 'www.website.ie';
  }
  if (inArray(country_code,eu_countries)){
    return 'www.website.eu';
  }
  //everyone else gets US
  return 'www.website.com';
}


/**
 * 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'));
  if (byPass(request)){
    correctHost = url.hostname;
  }
  if (correctHost !== url.hostname){
    url.hostname = correctHost;
    console.log('redirecting to '+url.href);
    return new Response('', {
        status: 301,
        headers: {
          'Location': url.href
        }
      })
  }

  console.log('no redirect');
  const response = await fetch(request)
  return response
}

Block all countries except USA
Ability to switch off a specific node in a specific country?
#2

Very nice! I’ve got a similar problem to solve and this helps a lot.


#3

Thank you so much for your code! I tried to modify the above code to fit my site needs (actually a simpler implementation), but got a “worker re-directed too many times” error when I tried to preview it. If anyone has a suggestion as to how to resolve this it would be greatly appreciated; below is the code I tried (websiteurl used for site url below, I have a 2 link limit that prevents me from using actual url).

Thanks!

//these countries go to us.websiteurl
var us_countries = [‘US’,‘GU’,‘PR’,‘UM’,‘VI’];
//these IP addresses don’t get redirected
var bypass_ip = [‘1.1.1.1’];
//user agents containing any of these strings don’t get redirected
var bypass_ua = [‘googlebot’,‘bing’];

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 byPass(request){
if (inArray(request.headers.get(‘CF-Connecting-IP’),bypass_ip)){
return true;
}
var length = bypass_ua.length;
for(var i = 0; i < length; i++) {
if(request.headers.get(‘user-agent’).includes(bypass_ua[i]))
return true;
}
return false;

}

function mapCountry(country_code){
if (inArray(country_code,us_countries)){
return ‘us.websiteurl’;
}
//everyone else gets vantage.network
return ‘websiteurl’;
}

/**

  • 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’));
if (byPass(request)){
correctHost = url.hostname;
}
if (correctHost !== url.hostname){
url.hostname = correctHost;
console.log(‘redirecting to ‘+url.href);
return new Response(’’, {
status: 301,
headers: {
‘Location’: url.href
}
})
}

console.log(‘no redirect’);
const response = await fetch(request)
return response
}