diff --git a/docs/content/docs/2.features/cache.md b/docs/content/docs/2.features/cache.md index 125df2ce..0f99f88c 100644 --- a/docs/content/docs/2.features/cache.md +++ b/docs/content/docs/2.features/cache.md @@ -152,6 +152,51 @@ await useStorage('cache').clear('nitro:handlers') Read more about Nitro Cache. :: +### Normalizing Cache Keys + +::important +**Cache keys are automatically normalized** using an internal utility that removes non-alphanumeric characters such as `/` and `-`. This behavior helps ensure compatibility across various storage backends (e.g., `file systems`, `key-value` stores) that might have restrictions on characters in `keys`, and also prevents potential path traversal vulnerabilities. +:: + +For example: + +```ts +getKey: () => '/api/products/sale-items' +``` + +Would generate a key like: + +```ts +api/productssaleitems.json +``` + +This behavior may result in keys that look different from the original route or identifier. + +::tip +To manually reproduce the same normalized key pattern used by Nitro (e.g., when invalidating cache entries), you can use the `escapeKey` utility function provided below: +:: + +```ts +function escapeKey(key: string | string[]) { + return String(key).replace(/\W/g, ""); +} +``` + +It's recommended to use `escapeKey()` when invalidating manually using route paths or identifiers to ensure consistency with Nitro's internal key generation. + +For example, if your `getKey` function is: + +```ts +getKey: (id: string) => `product/${id}/details` +``` + +And you want to invalidate `product/123/details`, you would do: + +```ts +const normalizedKey = escapeKey('product/123/details') +await useStorage('cache').removeItem(`nitro:functions:getProductDetails:${normalizedKey}.json`) +``` + ## Cache Expiration As NuxtHub leverages Cloudflare Workers KV to store your cache entries, we leverage the [`expiration` property](https://developers.cloudflare.com/kv/api/write-key-value-pairs/#expiring-keys) of the KV binding to handle the cache expiration.