Respect cache-control in guest API cache

This commit is contained in:
Codex Agent
2026-01-30 13:00:19 +01:00
parent 19425c0f62
commit 8aba034344
3 changed files with 48 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ import { ExpirationPlugin } from 'workbox-expiration';
import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching'; import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing'; import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies'; import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { shouldCacheResponse } from './lib/cachePolicy';
declare const self: ServiceWorkerGlobalScope & { declare const self: ServiceWorkerGlobalScope & {
__WB_MANIFEST: Array<any>; __WB_MANIFEST: Array<any>;
@@ -63,6 +64,9 @@ registerRoute(
cacheName: 'guest-api', cacheName: 'guest-api',
networkTimeoutSeconds: 6, networkTimeoutSeconds: 6,
plugins: [ plugins: [
{
cacheWillUpdate: async ({ response }) => (shouldCacheResponse(response) ? response : null),
},
new CacheableResponsePlugin({ statuses: [0, 200] }), new CacheableResponsePlugin({ statuses: [0, 200] }),
new ExpirationPlugin({ maxEntries: 80, maxAgeSeconds: 60 * 60 * 24 }), new ExpirationPlugin({ maxEntries: 80, maxAgeSeconds: 60 * 60 * 24 }),
], ],

View File

@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest';
import { shouldCacheResponse } from '../cachePolicy';
describe('shouldCacheResponse', () => {
it('returns false when Cache-Control is no-store', () => {
const response = new Response('ok', { headers: { 'Cache-Control': 'no-store' } });
expect(shouldCacheResponse(response)).toBe(false);
});
it('returns false when Cache-Control is private', () => {
const response = new Response('ok', { headers: { 'Cache-Control': 'private, max-age=0' } });
expect(shouldCacheResponse(response)).toBe(false);
});
it('returns false when Pragma is no-cache', () => {
const response = new Response('ok', { headers: { Pragma: 'no-cache' } });
expect(shouldCacheResponse(response)).toBe(false);
});
it('returns true for cacheable responses', () => {
const response = new Response('ok', { headers: { 'Cache-Control': 'public, max-age=60' } });
expect(shouldCacheResponse(response)).toBe(true);
});
});

View File

@@ -0,0 +1,20 @@
export function shouldCacheResponse(response: Response | null): boolean {
if (!response) {
return false;
}
const cacheControl = response.headers.get('Cache-Control') ?? '';
const pragma = response.headers.get('Pragma') ?? '';
const normalizedCacheControl = cacheControl.toLowerCase();
const normalizedPragma = pragma.toLowerCase();
if (normalizedCacheControl.includes('no-store') || normalizedCacheControl.includes('private')) {
return false;
}
if (normalizedPragma.includes('no-cache')) {
return false;
}
return true;
}