Merge "ui: small fixes to service worker / offline support"
diff --git a/ui/src/service_worker/service_worker.ts b/ui/src/service_worker/service_worker.ts
index 4226a8a..3289352 100644
--- a/ui/src/service_worker/service_worker.ts
+++ b/ui/src/service_worker/service_worker.ts
@@ -51,9 +51,23 @@
const CACHE_NAME = 'dist-' + UI_DIST_MAP.hex_digest.substr(0, 16);
const LOG_TAG = `ServiceWorker[${UI_DIST_MAP.hex_digest.substr(0, 16)}]: `;
-async function handleHttpRequest(req: Request): Promise<Response> {
- let fetchReason = 'N/A';
+
+function shouldHandleHttpRequest(req: Request): boolean {
+ // Suppress warning: 'only-if-cached' can be set only with 'same-origin' mode.
+ // This seems to be a chromium bug. An internal code search suggests this is a
+ // socially acceptable workaround.
+ if (req.cache === 'only-if-cached' && req.mode !== 'same-origin') {
+ return false;
+ }
+
const url = new URL(req.url);
+ return req.method === 'GET' && url.origin === self.location.origin;
+}
+
+async function handleHttpRequest(req: Request): Promise<Response> {
+ if (!shouldHandleHttpRequest(req)) {
+ throw new Error(LOG_TAG + `${req.url} shouldn't have been handled`);
+ }
// We serve from the cache even if req.cache == 'no-cache'. It's a bit
// contra-intuitive but it's the most consistent option. If the user hits the
@@ -65,28 +79,21 @@
// resources, which is undesirable.
// * Only Ctrl+R. Ctrl+Shift+R will always bypass service-worker for all the
// requests (index.html and the rest) made in that tab.
- const cacheable = req.method === 'GET' && url.origin === self.location.origin;
- if (cacheable) {
- try {
- const cacheOps = {cacheName: CACHE_NAME} as CacheQueryOptions;
- const cachedRes = await caches.match(req, cacheOps);
- if (cachedRes) {
- console.debug(LOG_TAG + `serving ${req.url} from cache`);
- return cachedRes;
- }
- console.warn(LOG_TAG + `cache miss on ${req.url}`);
- fetchReason = 'cache miss';
- } catch (exc) {
- console.error(LOG_TAG + `Fetch failed for ${req.url}`, exc);
- fetchReason = 'fetch failed';
+ try {
+ const cacheOps = {cacheName: CACHE_NAME} as CacheQueryOptions;
+ const cachedRes = await caches.match(req, cacheOps);
+ if (cachedRes) {
+ console.debug(LOG_TAG + `serving ${req.url} from cache`);
+ return cachedRes;
}
- } else {
- fetchReason = `not cacheable (${req.method}, ${req.cache}, ${url.origin})`;
+ console.warn(LOG_TAG + `cache miss on ${req.url}`);
+ } catch (exc) {
+ console.error(LOG_TAG + `Cache request failed for ${req.url}`, exc);
}
// In any other case, just propagate the fetch on the network, which is the
// safe behavior.
- console.debug(LOG_TAG + `serving ${req.url} from network: ${fetchReason}`);
+ console.debug(LOG_TAG + `falling back on network fetch() for ${req.url}`);
return fetch(req);
}
@@ -106,16 +113,14 @@
const cache = await caches.open(CACHE_NAME);
const urlsToCache: RequestInfo[] = [];
for (const [file, integrity] of Object.entries(UI_DIST_MAP.files)) {
- const reqOpts: RequestInit = {cache: 'reload', integrity};
+ const reqOpts:
+ RequestInit = {cache: 'reload', mode: 'same-origin', integrity};
urlsToCache.push(new Request(file, reqOpts));
- if (file === 'index.html') {
- const indexPage = location.href.split('service_worker.js')[0];
- // Disable cachinig of '/' for cases where the UI is hosted in a
- // subdirectory, because the ci-artifacts GCS bucket doesn't support
- // auto indexes (it has a fallback 404 page that fails the check).
- if (indexPage === '/') {
- urlsToCache.push(new Request(indexPage, reqOpts));
- }
+ if (file === 'index.html' && location.host !== 'storage.googleapis.com') {
+ // Disable cachinig of '/' for cases where the UI is hosted on GCS.
+ // GCS doesn't support auto indexes. GCS returns a 404 page on / that
+ // fails the integrity check.
+ urlsToCache.push(new Request('/', reqOpts));
}
}
await cache.addAll(urlsToCache);
@@ -150,5 +155,12 @@
});
self.addEventListener('fetch', event => {
+ // The early return here will cause the browser to fall back on standard
+ // network-based fetch.
+ if (!shouldHandleHttpRequest(event.request)) {
+ console.debug(LOG_TAG + `serving ${event.request.url} from network`);
+ return;
+ }
+
event.respondWith(handleHttpRequest(event.request));
});