服务工作者FetchEvent不喜欢HTTP 302重定向

时间:2019-07-05 12:45:46

标签: service-worker progressive-web-apps

我有一个基本的服务人员,当没有互联网连接时会返回一个脱机页面。网站在任何地方返回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'}参数,但对于如此简单的操作而言,它现在似乎已经变得相当先进。所有的“离线页面”教程似乎都有相同的错误。

1 个答案:

答案 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执行自动清除。)