@@ -9,28 +9,31 @@ const logger = createLogger('InlineImageServe')
99
1010/**
1111 * A `fileId=` embed (or a shared/revocable audience) must never serve stale bytes from its fixed inline
12- * URL, so it revalidates on each request. See `immutable` below for the cacheable case.
12+ * URL, so it revalidates on each request. See the content-addressed constant below for the cacheable case.
1313 */
1414const INLINE_CACHE_CONTROL = 'private, no-cache, must-revalidate'
1515
1616/**
17- * A `key=` embed addresses a CONTENT-ADDRESSED, immutable storage key (a re-upload mints a new key), so
18- * its bytes never change — safe to cache hard in the (private) browser cache, avoiding a re-download of
19- * every embedded image on each doc re-open/re-render. NEVER use this for the public-share route (a share
20- * can be revoked) or a `fileId=` embed (the underlying key can change under a stable fileId).
17+ * A `key=` embed addresses a CONTENT-ADDRESSED storage key (a re-upload mints a new key), so its bytes
18+ * never change — safe to reuse briefly from the (private) browser cache, avoiding a re-download of every
19+ * embedded image on each doc re-open/re-render. A SHORT window (not `immutable`): the bytes are stable but
20+ * the file can still be DELETED or its access REVOKED, and each revalidation re-runs that server-side
21+ * check, so a short max-age bounds how long a deleted/revoked image can linger in a client's cache. NEVER
22+ * use this for a `fileId=` embed (the underlying key can change under a stable fileId → stale bytes).
2123 */
22- const INLINE_IMMUTABLE_CACHE_CONTROL = 'private, max-age=31536000, immutable '
24+ const INLINE_CONTENT_ADDRESSED_CACHE_CONTROL = 'private, max-age=300, must-revalidate '
2325
2426/**
2527 * Download and respond with an already-workspace-scoped inline image — the single serving tail for both
2628 * the in-app and public inline routes. When `sniff` is set (public shares, a less-trusted audience), the
2729 * served content type is derived from the bytes and non-raster content is refused with 404; otherwise the
28- * stored content type is served, matching the in-app serve route. `immutable` opts a content-addressed
29- * (`key=`) in-app embed into a long private cache; leave it false for `fileId=` embeds and public shares.
30+ * stored content type is served, matching the in-app serve route. `contentAddressed` opts a
31+ * content-addressed (`key=`) in-app embed into a short private cache; leave it false for `fileId=` embeds
32+ * and public shares.
3033 */
3134export async function serveInlineImage (
3235 image : ResolvedInlineImage ,
33- { sniff, immutable = false } : { sniff : boolean ; immutable ?: boolean }
36+ { sniff, contentAddressed = false } : { sniff : boolean ; contentAddressed ?: boolean }
3437) : Promise < NextResponse > {
3538 const buffer = await downloadFile ( { key : image . key , context : 'workspace' } )
3639
@@ -48,6 +51,6 @@ export async function serveInlineImage(
4851 buffer,
4952 contentType,
5053 filename : image . filename ,
51- cacheControl : immutable ? INLINE_IMMUTABLE_CACHE_CONTROL : INLINE_CACHE_CONTROL ,
54+ cacheControl : contentAddressed ? INLINE_CONTENT_ADDRESSED_CACHE_CONTROL : INLINE_CACHE_CONTROL ,
5255 } )
5356}
0 commit comments