Verify response is not html when pre-caching in install event
This commit is contained in:
parent
e21bac3d70
commit
bbeafab1ef
1 changed files with 27 additions and 8 deletions
35
src/sw.js
35
src/sw.js
|
|
@ -105,11 +105,35 @@ const isNotMedia = req => {
|
||||||
return !url.pathname.startsWith('/media/')
|
return !url.pathname.startsWith('/media/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSuccessful = (resp) => {
|
||||||
|
if (!resp.ok) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ((new URL(resp.url)).pathname === '/index.html') {
|
||||||
|
// For index.html itself, there is no fallback possible.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const type = resp.headers.get('Content-Type')
|
||||||
|
// Backend will revert to index.html if the file does not exist, so text/html for emojis and assets is a failure
|
||||||
|
return type && !type.includes('text/html')
|
||||||
|
}
|
||||||
|
|
||||||
self.addEventListener('install', async (event) => {
|
self.addEventListener('install', async (event) => {
|
||||||
if (shouldCache) {
|
if (shouldCache) {
|
||||||
event.waitUntil((async () => {
|
event.waitUntil((async () => {
|
||||||
const cache = await caches.open(cacheKey)
|
const cache = await caches.open(cacheKey)
|
||||||
await cache.addAll(cacheFiles)
|
await Promise.allSettled(cacheFiles.map(async (route) => {
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Cache/add
|
||||||
|
// originally we used addAll() but it will raise a problem in one edge case:
|
||||||
|
// when the file for the route is not found, backend will return index.html with code 200
|
||||||
|
// but it's wrong, and it's cached, so we end up with a bad cache.
|
||||||
|
// this can happen when you refresh when you are in the process of upgrading
|
||||||
|
// the frontend.
|
||||||
|
const resp = await fetch(route)
|
||||||
|
if (isSuccessful(resp)) {
|
||||||
|
await cache.put(route, resp)
|
||||||
|
}
|
||||||
|
}))
|
||||||
})())
|
})())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -191,22 +215,17 @@ self.addEventListener('notificationclick', (event) => {
|
||||||
self.addEventListener('fetch', (event) => {
|
self.addEventListener('fetch', (event) => {
|
||||||
// Do not mess up with remote things
|
// Do not mess up with remote things
|
||||||
const isSameOrigin = (new URL(event.request.url)).origin === self.location.origin
|
const isSameOrigin = (new URL(event.request.url)).origin === self.location.origin
|
||||||
const isEmojiSuccessful = (resp) => {
|
|
||||||
const type = resp.headers.get('Content-Type')
|
|
||||||
// Backend will revert to index.html if the file does not exist, so text/html for emojis is a failure
|
|
||||||
return type && !type.includes('text/html')
|
|
||||||
}
|
|
||||||
if (shouldCache && event.request.method === 'GET' && isSameOrigin && isNotMedia(event.request)) {
|
if (shouldCache && event.request.method === 'GET' && isSameOrigin && isNotMedia(event.request)) {
|
||||||
event.respondWith((async () => {
|
event.respondWith((async () => {
|
||||||
const r = await caches.match(event.request)
|
const r = await caches.match(event.request)
|
||||||
|
|
||||||
if (r && (isEmojiSuccessful(r) || !isEmoji(event.request))) {
|
if (r && (isSuccessful(r) || !isEmoji(event.request))) {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(event.request)
|
const response = await fetch(event.request)
|
||||||
if (response.ok && isEmojiSuccessful(response) && isEmoji(event.request)) {
|
if (response.ok && isSuccessful(response) && isEmoji(event.request)) {
|
||||||
const cache = await caches.open(emojiCacheKey)
|
const cache = await caches.open(emojiCacheKey)
|
||||||
await cache.put(event.request.clone(), response.clone())
|
await cache.put(event.request.clone(), response.clone())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue