TLDR; Explains how to use web cache API in Cloudflare workers.
I recently added caching to Easyanalytics with Cloudflare's web cache API and thought of writing about it before it fades from my memory.
Cloudflare offers a range of cache products and services such as CDN (Content Delivery Network), this article will not delve into those aspects. Instead, we will concentrate solely on understanding and utilizing the Web Cache API for caching within Cloudflare Workers. Unlike traditional caching products that rely on basic key-value pairs for caching, Cloudflare takes distinctive approach with its caching mechanism, particularly the utilization of the Web Cache API within Cloudflare Workers. It allows developers to programmatically cache responses directly within their Workers. This article will primarily focus on leveraging the Web Cache API within Cloudflare Workers.
Why Cloudflare cache
Cost: Cloudflare's Web Cache API is included as part of the Cloudflare Workers platform with liberal free tier, making it a cost-effective option for developers looking to optimize performance without incurring additional expenses on third-party cache services.
Latency: For services already using Cloudflare workers, using Cloudflare's cache product would result in lower latencies as compared to external services.
Vendor Lockin: However, it's essential to consider the tradeoffs involved in opting for Cloudflare's caching solutions over third-party products. One notable tradeoff is vendor lock-in, whereby developers become reliant on Cloudflare's ecosystem for their caching needs. This dependence may limit flexibility in adopting alternative solutions in the future.
Web Cache API
The Web Cache API is a standardized web technology that allows developers to cache responses to network requests in the client's browser, thereby improving performance and reducing the need for repeated requests to the server. For a comprehensive understanding of the Web Cache API, developers can refer to the Mozilla Developer Network (MDN) article on Cache API.
Cloudflare implements the Web Cache API within its Workers platform, providing developers with additional tools and features tailored to the Cloudflare ecosystem. To understand how cache works in Cloudflare you can refer to this article . For details about API's supported by Cloudflare You can refer to this article. While Cloudflare's implementation largely adheres to the standard Web Cache API, there are some notable differences.
Cloudflare only supports put, match and delete operations, add/addall/keys etc. are not supported.
Cache API namespaces
Cloudflare cache API offer two main types of cache objects: cache.default and named cache object. The cache.default cache represents the default cache associated with the Worker script and is accessible globally within the Worker environment. It is shared with fetch requests. Named caches, on the other hand, allow developers to create multiple caches instances with custom names, providing more granular control over cached content.
The difference between cache.default and named caches lies in their scope and accessibility. The cache.default cache is shared across all requests. Named caches, on the other hand, are isolated to specific cache instances identified by custom names, allowing developers to organize and manage cached content more efficiently.
For storing private data pertaining to APIs, named caches are better choice since they are not shared, unlike cache.default which is shared with ordinary fetch requests.
Caching data
When using the Web Cache API within Cloudflare Workers, developers can utilize standard cache operations such as fetch and cache.put to interact with the cache. Here's how these operations work:
fetch: This operation allows developers to retrieve a resource from the cache. If resource is not present in the cache, it is fetched from the network. This is useful if you want to cache static resource such as image file which is unlikely to change.
cache.put: This operation stores a response in the cache, associating it with a specific request URL. Developers can use this operation to manually populate the cache with responses or update existing cached entries. This is useful when you want to cache the data from database, such as session data.
Using web cache API
Using the Web Cache API involves the following operations: opening a cache instance, creating a key to identify cached resources, and getting or setting cache values based on the key.
Getting cache instance
There are two types of cache instances: cache.default, which is the default cache available without the need for creation, and named cache, which must be created using cache.open. It's important to note that creating a named cache is an asynchronous operation.
Here is the example of how to use named cache
let cache = await caches.open('named:cache');
and example of using cache.default
let cache = caches.default;
Cache keys
In the Web Cache API, you cannot use a normal string as a cache key because it expects the key to be a valid URL. While cache.put and cache.match accept strings as parameters, they are interpreted as URLs. Therefore, you must first construct a URL request from your actual resource identifier key before using it as a cache key in the Web Cache API.
One simple strategy to construct cache key URLs is to use the URL of the existing request as the base URL and append it with the base64 encoding of the resource identifier. Base64 encoding is employed to ensure that if the resource identifier contains spaces, it does not render the URL invalid.
function constructCacheUrlKey(requestUrl: string, resourceid: string): string {
// Ensure there are no trailing slashes in the requestUrl
const normalizedRequestUrl = requestUrl.endsWith('/') ? requestUrl.slice(0, -1) : requestUrl;
const resourceCacheKey = btoa(resourceid);
const newUrl = `${normalizedRequestUrl}/${resourceCacheKey}`;
return newUrl;
}
// Example usage:
const requestUrl = request.url; //"https://example.com/api"
const resourceid = "your cache resource identifier here";
const newUrl = constructCacheUrlKey(requestUrl, resourceid);
const cacheKey = new Request(newUrl);
When using the Web Cache API, it's crucial to ensure that the URLs used as cache keys are properly formatted and valid. Here are the guideleines for createing proper URL for use as a cache key:
- Use Absolute URLs: Ensure that the URL provided to the cache API is an absolute URL, including the protocol (e.g., "https://") and the hostname (e.g., "example.com"). Relative URLs or incomplete URLs may result in errors when used as cache keys.
- Encode Special Characters: If the URL contains special characters such as spaces, query parameters, or non-ASCII characters, encode them properly. This ensures that the URL is correctly interpreted by the cache API and prevents potential issues with cache key validation.
- Normalize URLs: Normalize the URL to remove any unnecessary components or variations. For example, ensure that URLs with or without trailing slashes are treated as the same cache key to avoid duplication of cached content.
- Consider Query Parameters: If the URL includes query parameters that may vary between requests (e.g., session IDs, timestamps), consider normalizing or removing them from the cache key to ensure consistent caching behavior.
By following these guidelines, developers can create properly formatted URLs that can be safely used as cache keys with the Web Cache API. This helps ensure consistent caching behavior and prevents errors related to invalid URL formats.
Storing key/value
cache.put is used for storing values in cache
cache.put(request, response);
Here is example of how to use it
const cache = await caches.open('named:cache');
// assuming you want to put "data" in cache with duration of sMaxAge
const response = new Response(JSON.stringify(data), {
headers: {
'Cache-Control': `s-maxage=${sMaxAge}`,
},
});
await cache.put(cacheKey, response);
Getting key/value
cache.match is used to get values from cache
cache.match(request, options);
Here is example of how to use it
// Check if the details are in the cache
const cache = await caches.open('named:cache');
const cachedResponse = await cache.match(cacheKey);
if (cachedResponse) {
// Parse the JSON response stored in the cache
const cachedDetails = await cachedResponse.json();
}
// use parsed response
Conclusion
Cloudflare Cache APIs serve as a compelling alternative to other cache products, especially if your product is already leveraging Cloudflare Cache Workers. Unlike other cache solutions, Cloudflare utilizes the Web Cache API standard for caching.