diff --git a/README.md b/README.md index 0fdeca2..f04df75 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,10 @@ Use images to complement your responses, powered by Brave. ## Caching -- Images are cached for **30 days** +- Images are cached for **90 days** - After expiry, the next request triggers a fresh search - Images are stored in their original format as fetched from source +- A matching R2 lifecycle rule deletes stored objects after 90 days ## Support @@ -169,9 +170,11 @@ Fork this repo, connect to Cloudflare Pages, deploy. **Key:** `` — derived from query, no lookup needed. Stored with original content type from source. +Add an object lifecycle rule in **R2 → direct-img-store → Settings** that applies to all prefixes and deletes uploaded objects after **90 days**. This removes expired objects even when their query is never requested again. + ### KV: `DIRECT_IMG_CACHE` -**Key:** normalized query (lowercase, trimmed, max 200 chars) → **Value:** `{"t":1719000000,"ct":"image/jpeg"}` — **TTL:** 30 days +**Key:** normalized query (lowercase, trimmed, max 200 chars) → **Value:** `{"t":1719000000,"ct":"image/jpeg"}` — **TTL:** 90 days ### Database: `SurrealDB` (Rate Limiting) diff --git a/functions/[[path]].js b/functions/[[path]].js index 3add4d5..a088e63 100644 --- a/functions/[[path]].js +++ b/functions/[[path]].js @@ -1,6 +1,8 @@ import { braveImageSearch } from "./_utils/brave.js"; import { bingImageSearchFallback } from "./_utils/bing.js"; +const TTL_SECONDS = 90 * 24 * 60 * 60; + export async function onRequest(context) { const { request, env, params } = context; const url = new URL(request.url); @@ -28,7 +30,7 @@ export async function onRequest(context) { const obj = await env.R2_IMAGES.get(r2Key); if (obj) { const nowSec = Math.floor(Date.now() / 1000); - const remainingSec = Math.max(0, (cached.t + 5184000) - nowSec); + const remainingSec = Math.max(0, (cached.t + TTL_SECONDS) - nowSec); return new Response(obj.body, { headers: imageHeaders(cached.ct, remainingSec * 1000) }); } } @@ -184,7 +186,6 @@ export async function onRequest(context) { const { buffer: imgBuffer, contentType: finalContentType } = imgResult; await env.R2_IMAGES.put(r2Key, imgBuffer, { httpMetadata: { contentType: finalContentType } }); - const TTL_SECONDS = 5184000; await env.DIRECT_IMG_CACHE.put(cacheKey, JSON.stringify({ t: Math.floor(Date.now() / 1000), ct: finalContentType }), { expirationTtl: TTL_SECONDS }); return new Response(imgBuffer, { headers: imageHeaders(finalContentType, TTL_SECONDS * 1000) });