Search code examples
javascripttypescriptdatecachingresponse

How to save cache storage date with JavaScript Cache API?


I'm using JavaScript's Cache Web API to store responses from my server to requests made by my client application. Moreover, I need a way to programmatically remove them based on when the request was originally made. Here is the code I use to store the responses:

/** Searches for the corresponding cache for the given request. If found, returns
 *  the cached response. Otherwise, performs the fetch request and adds the response
 *  to cache. Returns the HTTP response.
 */
export async function fetchCachedData(request: Request) {
  const cache = await caches.open(CACHE_NAME);

  // Check if response is already cached
  const cachedResponse = await cache.match(request);
  if (cachedResponse) {
    console.debug("Using cached response for", request.url);
    return cachedResponse.clone();
  }

  // Fetch new response
  console.debug("Fetching", request.url, "...");
  const response = await fetchFromAPI(request);
  const responseDate = new Date().getTime().toString();
  response.headers.set("Date", responseDate);

  // Cache the new response
  if (
    response.ok /*&& response.clone().headers.get("Cache-Control") !== "no-store"*/
  ) {
    await cache.put(request, response.clone());
    console.info("Cached response as", response.url);
  }
  return response.clone();
}

This approach seems to work on browsers like Firefox, however on Chrome I get an error telling me that headers is read-only: TypeError: Failed to execute 'set' on 'Headers': Headers are immutable

I have also tried setting the Date header on the server side, however it appears that not all headers set in the express-based app are honoured when cloning and retrieving them from the cache. This is why I wish to manually set the request date when the response is retrieved on the client side.

I don't necessarily need the date to be stored in the cached response's headers, that's just the way I have my cache filtering code set up. Ideally, the request date should be stored somewhere in the response object so that it is preserved when using clone() and is present in the cache.


Solution

  • I've solved this by using the pragma HTTP header -- it appears to be unused as of the HTTP/1.1 spec, however when set on the server side it is preserved in the headers of the response object obtained after making a request from the fetch() API.

    Server code (Express.js):

    export function headerMiddleware(
      _req: Request,
      res: Response,
      next: NextFunction
    ) {
      const now = new Date().getTime();
      res.setHeader("pragma", now);
      next();
    }
    

    This implementation is probably discouraged since pragma is a deprecated header and its original intention was to signal if no-cache is how the response is to be handled, however when I set its value to a numeric string there appear to be no errors and the solution runs smoothly. Ideally, I'd use the Date header, however if I set that on the server side then the header is removed upon inspection on the client.