Can't purge Cloudflare Workers cache using API

I am using Cloudflare Workers to be the CDN for my DigitalOcean Spaces. I prefix all of my files with a lowercase x and use the route https://x6f.cc/x* for scripts enabled. The script below is fairly simple and works really well.

I only use one version of my site and that’s https://DOMAIN.com, I don’t use www or http.

In the Cache API Example it uses the entire request as the key for the cache. I believe that makes it impossible to use the main Cloudflare API to purge a single file. I modified mine to use the URL of the request. However, I am still having issues purging the cache of an individual file. I am using the Cloudflare SDK to call the cachePurge method on a Zones object.

If I purge everything from the web interface, the cached file goes away. I’ve disabled all page rules. My caching level is set to standard. The browser expiration is at 4 hours. I’m using curl to get the headers of the response to help me determine if the file was deleted.

It seems like the only way to purge files created by the Workers Cache API is to purge everything in your zone.

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

/**
 * Fetch and log a request
 * @param {Request} request
 */
async function handleRequest(event, request) {

  let response;
  let cache = caches.default;

  const parts = request.url.split("/")
  const file = parts.pop();

  // Don't use CDN. When we delete a file from Spaces, we don't want
  // it cached on two CDNs. Then we'd have to clear the cache for 
  // DO and CF.
  const requestUrl = 'https://SPACES_NAME.nyc3.digitaloceanspaces.com/' + file;

  response = await cache.match(event.request.url);
  
  if(response) {
    response = new Response(response.body, response);
    response.headers.set('x6-cache', 'hit');
  }

  if(!response) {
    response = await fetch(requestUrl);
    response = new Response(response.body, response);
    response.headers.set('x6-cache', 'miss');
    event.waitUntil(cache.put(event.request.url, response.clone()));
  }

  return response;
}

Cache API is per datacenter. Enterprise customer can purge per tag.
Have you tried KV to do this?

I use ?sync on the url to sync from server to kv.

I think I read somewhere that with Argo the Cache API isn’t per data-center. I’ll see if I can find where I saw that.

Unfortunately, KV only offers values up to 64 kB and that isn’t enough for me. I really like your idea of ?sync. Maybe I could use a query like that to purge the file from the cache that way with a Worker.

Here is where I read about Argo’s cache with Workers: Cloudflare Workers Beta Feedback

Support just informed me this is a known issue and they’re working with DigitalOcean to resolve it.

When calling the ?sync my worker does a fetch to Cloudflare API, purging the cache for URL but without the “?sync”

https://api.cloudflare.com/#zone-purge-files-by-url

The worker fetches DigitalOcean like this:

let response    
const cache_time = 900
    response = await fetch("https://SPACE.nyc3.digitaloceanspaces.com/static/" + path, {
        cf: {
          cacheTtlByStatus: {
            "200-299": cache_time,
            404: 1,
            "500-599": -1
          },
          apps: false,
          minify: {
            javascript: true,
            css: true,
            html: true
          }
        }
      })

I’m using the Workers Cache API, so I think it works differently.

Unfortunately, I have the same issue, I can’t purge a single file using the Cloudflare API if I use the Workers Cache API.

@levi.durfee did you find a workaround for that issue?

1 Like

on your domain or worker.dev?

On my domain

Hi @chreble, I’m not entirely sure I understand. You’re trying to use Cloudflare’s REST API to purge a file that was previously cached using the Workers Cache API? Could you provide an example sequence of events?

Harris

Hi @harris,

Yes that’s it, I’m using a very simple worker to cache the contents of a JSON api at edge.

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

async function handleRequest(event) {
  const cache = caches.default
  const cacheControl = event.request.headers.get('Cache-Control')
  const noCache = cacheControl && cacheControl.indexOf('no-cache') !== -1

  let response = await cache.match(event.request.url)
  if (noCache || !response) {
    response = await fetch(event.request)
    if (!noCache) {
      event.waitUntil(cache.put(event.request.url, response.clone()))
    }
  }

  return response
}

Nothing fancy, this works perfectly, it gets the response from origin if there’s no entry in the cache for a given URL. The issue I encounter is when I want to purge the URL associated to the API call (I’m using request URL as a cache key) from either Cloudflare console or through the REST API, it doesn’t clear the cache, I have to purge everything in order to make it work.

As a workaround, I’m using Workers KV to store a cache version globally and my worker is able to compare the cache version compared to what is stored in the cache, that’s how I can purge from edge nodes but it looks overly complicated from my perspective. Workers KV also adds additional latency to the thing, that makes me believe that there’s surely a better way.

Hope it helps!
Chris.

So you are saying cache.match() returns a response even after that particular file was cleared from the cache?

No, I’m saying that you cannot purge files with the REST API or console if you stored them with the Workers Cache library in the worker.

So you are saying clearing the caching itself throws an error?

@sandro
I found a workaround using Page Rules and it works perfectly.
For the Worker see my reply to @harris.

I am afraid the reply is not very clear.

What exactly does not work in this scenario? Which of the two examples I provided is it?

Hi @chreble I don’t see the @harris reply you mention, can you describe your solution?

Cheers

Hello Sir, any suggestions on how to reduce the ping time of my website [ https://www.sarkarijobfy.com (Indian Job Portal). When I trace the IP of my site, its showing location in the US. Is any option my India visitors can be routed to the Mumbai DC.