Не удается получить доступ к arrayBuffer в RangeRequest - PullRequest
0 голосов
/ 11 января 2019

Попытка решить проблему, указанную в этой статье: https://philna.sh/blog/2018/10/23/service-workers-beware-safaris-range-request/ и здесь: PWA - кэшированное видео не будет воспроизводиться в Mobile Safari (11,4)

Основная проблема в том, что мы не можем показывать видео в Safari. В статье говорится, что она имеет решение этой проблемы, но, похоже, вызывает еще одну проблему в Chrome. Разница в нашем решении заключается в том, что мы не используем кэширование. В настоящее время мы просто хотим передать запрос нашему сервисному работнику. Реализация выглядит так:

self.addEventListener('fetch', function (event){
    if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
        return;
    }

    if (event.request.headers.get('range')) {
        event.respondWith(returnRangeRequest(event.request));
    } else {
        event.respondWith(fetch(event.request));
    }
});

function returnRangeRequest(request) {
return fetch(request)
    .then(res => {
        return res.arrayBuffer();
    })
    .then(function(arrayBuffer) {
        var bytes = /^bytes\=(\d+)\-(\d+)?$/g.exec(
            request.headers.get('range')
        );
        if (bytes) {
            var  start = Number(bytes[1]);
            var end = Number(bytes[2]) || arrayBuffer.byteLength - 1;
            return new Response(arrayBuffer.slice(start, end + 1), {
                status: 206,
                statusText: 'Partial Content',
                headers: [
                    ['Content-Range', `bytes ${start}-${end}/${arrayBuffer.byteLength}`]
                ]
            });
        } else {
            return new Response(null, {
                status: 416,
                statusText: 'Range Not Satisfiable',
                headers: [['Content-Range', `*/${arrayBuffer.byteLength}`]]
            });
        }
    });
}

Мы получаем буфер массива, возвращаемый при выборке запроса диапазона, но он имеет нулевую длину в байтах и ​​кажется пустым. Заголовок диапазона фактически содержит «bytes = 0-», а последующие запросы имеют начальное значение, но не имеют конечного значения.

Может быть, есть какая-то функция обнаружения, которую мы можем сделать, чтобы определить, что это хром, и мы можем просто регулярно вызывать fetch? Я предпочел бы иметь решение, которое работает везде, хотя. Также res показывает тип: "непрозрачный", так что, может быть, это как-то связано с этим? Не совсем уверен, на что смотреть дальше. Если мы не можем решить проблему с Chrome, мне может понадобиться другое решение для Safari.

1 Ответ

0 голосов
/ 16 января 2019

Кажется, это был непрозрачный ответ. Я не осознавал, что fetch по умолчанию был nocors. Добавление режима 'cors' и перезапись заголовка диапазона, похоже, позволили перезаписи работать на chrome. К сожалению, он все еще не работает в Safari, но я смог получить доступ к arrayBuffer после правильной установки значений cors.

Вот изменение, которое я должен был сделать:

var myHeaders = {};
return fetch(request, { headers: myHeaders, mode: 'cors', credentials: 'omit' })
    .then(res => {
        return res.arrayBuffer();
    })

Важно, чтобы сервер отвечал разрешенными заголовками. например,

access-control-allow-methods: GET
access-control-allow-origin: *
...