ui: handle cache for opaque requests

This commit is contained in:
undefined committed 2022-10-20 10:57:13 +08:00
1 parent 63f3202241
commit fc7e57cb8c
2 files changed
+26 -11

No files matched your search

+5
View File
@@ -165,6 +165,11 @@ class SWConfigHandler extends ResourceHandler {
async get() { async get() {
this.response.body = { this.response.body = {
preload: SystemModel.get('ui-default.preload'), preload: SystemModel.get('ui-default.preload'),
hosts: [
`${this.request.method}://${this.request.host}`,
SystemModel.get('server.url'),
SystemModel.get('server.cdn'),
],
}; };
} }
} }
+21 -11
View File
@@ -34,6 +34,7 @@ function shouldPreCache(name: string) {
interface ServiceWorkerConfig { interface ServiceWorkerConfig {
base?: string; base?: string;
hosts?: string[];
targets?: string[]; targets?: string[];
preload?: string; preload?: string;
} }
@@ -72,32 +73,41 @@ self.addEventListener('install', (event) => event.waitUntil((async () => {
self.addEventListener('activate', (event) => { self.addEventListener('activate', (event) => {
const valid = [PRECACHE]; const valid = [PRECACHE];
event.waitUntil( event.waitUntil((async () => {
caches.keys() const [names, cfg] = await Promise.all([
.then((names) => Promise.all( caches.keys(),
names.filter((name) => !valid.includes(name)).map((p) => caches.delete(p)), fetch('/sw-config').then((res) => res.json()),
)).then(() => self.clients.claim()), ]);
); config = cfg;
await Promise.all(names.filter((name) => !valid.includes(name)).map((p) => caches.delete(p)));
self.clients.claim();
})());
}); });
self.addEventListener('fetch', (event: FetchEvent) => { self.addEventListener('fetch', (event: FetchEvent) => {
if (!['get', 'head'].includes(event.request.method.toLowerCase())) return; if (!['get', 'head'].includes(event.request.method.toLowerCase())) return;
if (!event.request.url.startsWith('http')) return;
if (!shouldCache(event.request.url) && config?.base && config?.targets?.length) { if (!shouldCache(event.request.url) && config?.base && config?.targets?.length) {
if (new URL(event.request.url).origin !== location.origin) return; if (new URL(event.request.url).origin !== location.origin) return;
event.respondWith(get(event.request.url)); event.respondWith(get(event.request.url));
return; return;
} }
// Only handle whitelisted origins;
if (!config?.hosts?.some((i) => event.request.url.startsWith(i))) return;
if (process.env.NODE_ENV !== 'production' || !shouldCache(event.request.url)) return; if (process.env.NODE_ENV !== 'production' || !shouldCache(event.request.url)) return;
event.respondWith((async () => { event.respondWith((async () => {
const cachedResponse = await caches.match(event.request); const cachedResponse = await caches.match(event.request.url);
if (cachedResponse) return cachedResponse; if (cachedResponse) return cachedResponse;
console.log(`Caching ${event.request.url}`); console.log(`Caching ${event.request.url}`);
const [cache, response] = await Promise.all([ const [cache, response] = await Promise.all([
caches.open(PRECACHE), caches.open(PRECACHE),
fetch(event.request), fetch(event.request.url), // Fetch from url to prevent opaque response
]); ]);
if (response.ok) await cache.put(event.request, response.clone()); if (response.ok) {
return response; cache.put(event.request.url, response.clone());
return response;
}
// If response fails, re-fetch the original request to prevent
// errors caused by different headers and do not cache them
return fetch(event.request);
})()); })());
}); });