fix(gateway-ui): refresh service worker and static cache headers
This commit is contained in:
@@ -295,6 +295,7 @@ describe('GatewayServer integration', () => {
|
|||||||
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/`);
|
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/`);
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
expect(res.headers.get('content-type')).toBe('text/html');
|
expect(res.headers.get('content-type')).toBe('text/html');
|
||||||
|
expect(res.headers.get('cache-control')).toBe('no-cache');
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
expect(body).toContain('Flynn');
|
expect(body).toContain('Flynn');
|
||||||
});
|
});
|
||||||
@@ -308,6 +309,16 @@ describe('GatewayServer integration', () => {
|
|||||||
expect(res.headers.get('content-type')).toBe('text/css');
|
expect(res.headers.get('content-type')).toBe('text/css');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('serves sw.js with no-store cache policy', async () => {
|
||||||
|
if (!LISTEN_ALLOWED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/sw.js`);
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.headers.get('content-type')).toBe('application/javascript');
|
||||||
|
expect(res.headers.get('cache-control')).toBe('no-store');
|
||||||
|
});
|
||||||
|
|
||||||
it('returns 404 for unknown HTTP path', async () => {
|
it('returns 404 for unknown HTTP path', async () => {
|
||||||
if (!LISTEN_ALLOWED) {
|
if (!LISTEN_ALLOWED) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -71,7 +71,13 @@ export async function serveStatic(
|
|||||||
// Try to read and serve the file
|
// Try to read and serve the file
|
||||||
try {
|
try {
|
||||||
const content = await readFile(filePath);
|
const content = await readFile(filePath);
|
||||||
res.writeHead(200, { 'Content-Type': contentType });
|
const headers: Record<string, string> = { 'Content-Type': contentType };
|
||||||
|
if (pathname === '/sw.js') {
|
||||||
|
headers['Cache-Control'] = 'no-store';
|
||||||
|
} else if (pathname === '/index.html') {
|
||||||
|
headers['Cache-Control'] = 'no-cache';
|
||||||
|
}
|
||||||
|
res.writeHead(200, headers);
|
||||||
res.end(content);
|
res.end(content);
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ export async function registerPwaServiceWorker() {
|
|||||||
if (!('serviceWorker' in navigator)) {
|
if (!('serviceWorker' in navigator)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return navigator.serviceWorker.register(withToken('/sw.js'));
|
const registration = await navigator.serviceWorker.register(withToken('/sw.js'));
|
||||||
|
// Ask the browser to check for a newer worker on app load.
|
||||||
|
void registration.update().catch(() => undefined);
|
||||||
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPushStatus() {
|
export async function getPushStatus() {
|
||||||
|
|||||||
+30
-9
@@ -1,4 +1,4 @@
|
|||||||
const CACHE_NAME = 'flynn-webchat-v1';
|
const CACHE_NAME = 'flynn-webchat-v2';
|
||||||
const token = new URL(self.location.href).searchParams.get('token');
|
const token = new URL(self.location.href).searchParams.get('token');
|
||||||
const withToken = (path) => {
|
const withToken = (path) => {
|
||||||
if (!token) {
|
if (!token) {
|
||||||
@@ -34,17 +34,38 @@ self.addEventListener('fetch', (event) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.respondWith((async () => {
|
const requestUrl = new URL(event.request.url);
|
||||||
const cached = await caches.match(event.request, { ignoreSearch: true });
|
const isNavigation = event.request.mode === 'navigate';
|
||||||
if (cached) {
|
const isStaticAsset = requestUrl.origin === self.location.origin
|
||||||
return cached;
|
&& (requestUrl.pathname.startsWith('/lib/')
|
||||||
}
|
|| requestUrl.pathname.startsWith('/pages/')
|
||||||
|
|| requestUrl.pathname === '/app.js'
|
||||||
|
|| requestUrl.pathname === '/style.css'
|
||||||
|
|| requestUrl.pathname === '/index.html'
|
||||||
|
|| requestUrl.pathname === '/manifest.webmanifest');
|
||||||
|
|
||||||
|
event.respondWith((async () => {
|
||||||
try {
|
try {
|
||||||
return await fetch(event.request);
|
const networkResponse = await fetch(event.request);
|
||||||
|
if (isNavigation || isStaticAsset) {
|
||||||
|
const cache = await caches.open(CACHE_NAME);
|
||||||
|
await cache.put(event.request, networkResponse.clone());
|
||||||
|
}
|
||||||
|
return networkResponse;
|
||||||
} catch {
|
} catch {
|
||||||
const fallback = await caches.match('/index.html', { ignoreSearch: true });
|
const cached = await caches.match(event.request, { ignoreSearch: true });
|
||||||
return fallback || new Response('Offline', { status: 503 });
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNavigation) {
|
||||||
|
const fallback = await caches.match('/index.html', { ignoreSearch: true });
|
||||||
|
if (fallback) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response('Offline', { status: 503 });
|
||||||
}
|
}
|
||||||
})());
|
})());
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user