Invalidating R2 object cache

Is it possible to invalidate an object cache so that when it’s rewritten (e.g. avatar image in the app’s profile gets updated by the user), the latest uploaded object becomes available right away?

Currently, I use SotoS3 to upload the asset, which works great. This is the config I use for now, thinking that 5 mins of cache works, but there’s a small delay until the new asset is available:

        let putObjectRequest = S3.PutObjectRequest(
            body: .data(data),
            bucket: bucket,
            cacheControl: "Cache-Control: public, max-age=300, s-maxage=300",
            contentType: mimeType,
            key: key
        )

Would it be possible to set the cache to say, 3600s but remove the old object/cache the new one when a new asset is uploaded?

Thanks,

– Tito

R2 shouldn’t have it’s own cache - could you clarify for me how you are accessing the object after upload? Is it a custom domain, an r2.dev url or the S3 API?

1 Like

Hello Eria,
I access the object via custom domain. Sample:

The above image is:

https://vl-object.space/15737421-6D1C-4285-8B59-B0D3E8B14628%2Favatar.png

Thanks for sharing!

In that case you would need to purge the cache using the CDN cache purge functions for your zone:

To automate this, you would use the API: https://developers.cloudflare.com/api/operations/zone-purge#purge-cached-content-by-url

Ah! Excellent!

So, in order to do that programmatically, I can use:

POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache

I have a few questions:

  1. The page Purge cache · Cloudflare Cache (CDN) docs lists lists the Purge cache options. Just below, it indicates that URL is a purge option for the Free plan. But then the page ​Purge cache by prefix (URL) · Cloudflare Cache (CDN) docs states it’s for Enterprise only. (?)
  2. Knowing the URL (as shown above), what would the request body look like?:
curl --request POST \
  --url https://api.cloudflare.com/client/v4/zones/zone_id/purge_cache \
  --header 'Content-Type: application/json' \
  --header 'X-Auth-Email: ' \
  --data '{
  "tags": [
    "some-tag",
    "another-tag"
  ]
}

Should I pass the ETag, or CF-RAY perhaps? Or assuming Purge cache by prefix (URL) is available, where would I pass the above URL?

Thanks again!

@erisa-cf could you please include a curl command to illustrate how I could purge cache a given asset URL? It would help a lot. Thank you very much! :pray:

I was able to find the solution after a few minor errors. The following snippet is for Vapor (Swift on Server), but it’s brief and simple enough to adopt in other languages:

private func purgeCloudflareCache(req: Request, zoneID: String, urls: [String]) async throws {
	let uri = URI(string: "https://api.cloudflare.com/client/v4/zones/\(zoneID)/purge_cache")
	
	let body = try JSONEncoder().encode(["files": urls])
	
	let request = ClientRequest(method: .POST, url: uri, headers: [
		"X-Auth-Key": MY_AUTH_KEY,
		"X-Auth-Email": MY_AUTH_EMAIL,
		"Content-Type": "application/json",
	], body: .init(data: body))
	
	let response = try await req.application.client.send(request)
	
	guard response.status.code >= 200, response.status.code <= 299 else {
		throw Abort(.internalServerError, reason: "Failed to purge cache with status: \(response.status): \(urls). Response: \(response)")
	}
}

The takeaway is: include both, X-Auth-Key and X-Auth-Email in the request headers. The X-Auth-Key is the Global API Key and the X-Auth-Email is the email used to open your Cloudflare account.

I hope this helps!

1 Like

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