basyliq 🌿

Implementing Geo-Specific Caching in Cloudflare Workers

Configure Cloudflare Workers to cache responses based on user location, ensuring content is served correctly to users from different countries or regions. This guide covers how to implement caching that distinguishes between users in the US and Canada (region-level caching) and users from other countries (country-level caching).


Problem Overview

By default, Cloudflare may cache content based on the first user’s location, causing users from different regions to see content intended for others. This can be problematic for sites needing geo-specific content delivery.

Solution: Custom Cache Keys and the Vary Header

To handle geo-specific caching, use a custom cache key and the Vary header in Cloudflare Workers.

Implementation Steps

  1. Create or Edit a Cloudflare Worker:

    • Ensure your Worker is set up in the Cloudflare dashboard or deployed via Wrangler.
  2. Add the following code:

     1addEventListener('fetch', event => {
     2  event.respondWith(handleRequest(event.request, event));
     3});
     4
     5async function handleRequest(request, event) {
     6  let headers = new Headers(request.headers);
     7
     8  const countryCode = request.cf && request.cf.country ? request.cf.country : 'unknown';
     9  const regionCode = request.cf && request.cf.regionCode ? request.cf.regionCode : '';
    10
    11  // Define cache key: region-level for US/CA, country-level for others
    12  let cacheKey;
    13  if (countryCode === 'US' || countryCode === 'CA') {
    14    cacheKey = new Request(`${request.url}?geo=${countryCode}-${regionCode}`, request);
    15  } else {
    16    cacheKey = new Request(`${request.url}?geo=${countryCode}`, request);
    17  }
    18
    19  const cache = caches.default;
    20  let response = await cache.match(cacheKey);
    21
    22  if (!response) {
    23    response = await fetch(request, { headers: headers });
    24    response = new Response(response.body, response);
    25
    26    response.headers.set('Cache-Control', 'public, max-age=300');
    27    response.headers.set('Vary', 'cf-ipcountry');
    28    if (countryCode === 'US' || countryCode === 'CA') {
    29      response.headers.append('Vary', 'cf-regioncode');
    30    }
    31
    32    event.waitUntil(cache.put(cacheKey, response.clone()));
    33  } else {
    34    response = new Response(response.body, response);
    35    response.headers.set("cf-region", request.cf.region || 'unknown');
    36    response.headers.set("cf-regioncode", regionCode);
    37  }
    38
    39  return response;
    40}

Key Points

Testing

  1. Check Response Headers:

    • Use browser dev tools or curl to confirm the CF-Cache-Status header (HIT or MISS).

    • Verify the presence of Vary: cf-ipcountry and Vary: cf-regioncode (if applicable).

      Example:

      1curl -I https://yourdomain.com/path/to/resource
  2. Simulate Geo-Access:

    • Use a VPN to test access from different locations.
    • Ensure content served matches the expected geo-specific version.

#servers #cache #cloudflare #geo