nitrojs / nitrojs/nitro

Clearing nitro cache from handlers doesn't work as intended

Open
#2,738 3 comments 9 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug v2
Dominant language
TypeScript
Stars
11.2k
Forks
899
Avg merge
2d 24m
Merged PRs (30d)
40

Description

Environment
  • Operating System: MacOS Darwin
  • Node Version: v22.7.0
  • Nuxt Version: 3.13.0
  • CLI Version: 3.13.0
  • Nitro Version: 2.9.7
  • Package Manager: pnpm@9.9.0
Reproduction
  1. create api endpoint with defineCachedEventHandler
  2. set basic parameters like maxAge, name, getKey (optional for debugging)
  3. remove the cache files manually or by running:
  const storage = useStorage("cache");
  try {
    // Fetch keys for both nitro:handlers and nitro:functions
    const handlerKeys = await storage.getKeys("nitro:handlers");
    const functionKeys = await storage.getKeys("nitro:functions");

    // Combine both sets of keys
    const cacheKeys = [...handlerKeys, ...functionKeys];

    // Remove all cache items concurrently
    await Promise.all(cacheKeys.map((element) => storage.removeItem(element)));

    return { success: true };
  } catch (error: any) {
    console.error("Error invalidating cache:", error);
    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message || "Failed to invalidate cache",
    });
  }
  1. observe that files get removed from disk
  2. Api endpoint is still returning the cached response (network tab size - "(disk cache)") - the response was cached on the client browser
Describe the bug

When creating api endpoint with defineCachedEventHandler or cachedEventHandler even after clearing the cache in nitro it still returns cached responses due to client browser caching the functions.
Using:

    shouldBypassCache,
    shouldInvalidateCache

runs them only when the response isn't cached in the browser making it impossible to bypass or invalidate it in the endpoint itself without clearing browser cache beforehand.

Additional context

Current workarounds I've found:

Adding belows code to the definedefineCachedEventHandler ensures that clients browser won't cache the function which ensures we now have full control over the cache and can invalidate it manually. We can even use the shouldBypassCache or shouldInvalidateCache. and bypass the cache on will which wasn't previously possible due to browser cache.

    event.node.res.setHeader(
      "Cache-Control",
      "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"
    );
    event.node.res.setHeader("Pragma", "no-cache");
    event.node.res.setHeader("Expires", "0");
    event.node.res.setHeader("Surrogate-Control", "no-store");

    const uniqueId = Date.now().toString();
    event.node.res.setHeader("X-Response-ID", uniqueId);

Second workaround:

Creating a defineCachedFunction and then using it in defineEventHandler makes it possible to clear cache manually. This approach ensures that the client browser doesn't cache the response so we don't need to create unique headers for each request.

Note:
If this is intended behaviour please do let me know. It seems odd that it isn't mentioned in the nitro documentation (or I just haven't look for it good enough). Regardless if it is in the docs I think it might be good to mention it here: nitro cache docs.

Logs

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the defineCachedEventHandler endpoint described in the issue, clearing the nitro:handlers and nitro:functions storage keys, and observing the browser's disk cache behavior. Read the Nitro cache documentation and the cache-handler behavior around shouldBypassCache and shouldInvalidateCache; done requires either correcting the interaction or documenting the intended client-cache behavior and supported invalidation path.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, nuxt, typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.