我有一个基本的服务人员,当没有互联网连接时会返回一个脱机页面。网站在任何地方返回302重定向,无论服务处于脱机状态还是在线状态,网站都会因服务人员的利益而中断。
服务人员:
'use strict';
var cache_key = 'offline_cache_v18';
this.addEventListener('install', event => {
event.waitUntil(
caches.open(cache_key).then(function(cache) {
return cache.addAll([
'/offline.html'
]);
})
);
});
this.addEventListener('fetch', event => {
if (event.request.mode === 'navigate' || (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html')) ) {
event.respondWith(
fetch(event.request.url).catch(error => {
return caches.match('/offline.html');
})
);
} else {
event.respondWith(caches.match(event.request).then(function (response) {
return response || fetch(event.request);
}));
}
});
破坏服务人员的页面:
<?php header('Location: /'); ?>
预期结果:页面将照常加载,但脱机时应显示offline.html。
实际结果:该网站无法完全加载响应302重定向的网页,并指出“无法访问此网站”。控制台还报告:“ FetchEvent导致网络错误响应:重定向响应用于其重定向方式不是“跟随”的请求。”
尝试:使用response.status检查响应代码,并尝试将代码切换为使用“工作箱”库。还尝试了{redirect:'follow'}参数,但对于如此简单的操作而言,它现在似乎已经变得相当先进。所有的“离线页面”教程似乎都有相同的错误。
答案 0 :(得分:0)
底层安全限制在https://bugs.chromium.org/p/chromium/issues/detail?id=658249
中有详细说明。这个问题出现在导航请求中,因为这些请求使用None
中的redirect
mode。 (大多数其他类型的请求将具有'manual'
的{{1}}模式,这意味着可以使用重定向的HTTP 30x响应来实现它们。)
您可以通过检查其redirected
属性来检测是否有遵循HTTP 30x重定向生成的redirect
对象。
总而言之:如何使用作为30倍重定向的一部分生成的'follow'
对象来满足导航请求的Response
事件?答案是首先通过创建一个新的(基本上相同)Response
对象来“清理”重定向的响应,但是该对象的fetch
属性将设置为Response
。
redirected
您可以通过检查false
处理程序中是否async function cleanRedirect(response) {
const clonedResponse = response.clone();
return new Response(await clonedResponse.blob(), {
headers: clonedResponse.headers,
status: clonedResponse.status,
statusText: clonedResponse.statusText,
});
}
来使用它。如果是这样,请在致电event.request.redirect === 'manual'
之前检查fetch
是否为event.respondWith(response)
。如果是,则首先将重定向的响应传递到response.redirected
。
(此代码改编自Workbox的implementation。Workbox会自动“清除”预缓存的URL的任何重定向响应,但不会对运行时缓存的URL执行自动清除。)