13

У меня есть рабочий, который ловит запросы моей страницы (fetch), и когда URL-адрес соответствует определенному шаблону, он будет извлекать другой URL-адрес и заменять ответ на это новое содержимое. Он отлично работает для текстовых данных (JS, XML ...) или двоичных данных (например, изображений), но когда дело доходит до видео, возникает сбой.Как я могу передать видео с ServiceWorker?

Я использую Chrome 41 на OSX.

Это упрощенный код моего работника:

self.addEventListener('fetch', function(event) { 
    var url = event.request.url; 
    console.log('SW: fetch', url); 
    if (/\.mp4$/.test(url)) { 
    url = 'https://vjs.zencdn.net/v/oceans.mp4'; 
    var options = { 
     credentials: 'include', 
     mode: 'no-cors' 
    }; 
    event.respondWith(fetch(url, options)); 
    } 
}); 

И это упрощенный код в моем HTML страницы:

navigator.serviceWorker.register('sw.js').then(function(reg) { 
    console.info('ServiceWorker registration successful for', reg.scope); 

    var video = document.createElement('video'); 
    video.src = '/video.mp4'; 
    video.controls = true; 
    video.autoplay = true; 
    video.onerror = function(err) { 
    console.error('Video load fail', err); 
    } 
    video.onload = function(data) { 
    console.info('Video load success'); 
    } 
    document.body.appendChild(video); 

}).catch(function(err) { 
    console.error('ServiceWorker registration failed:', err); 
}); 

Первый раз при загрузке страницы, работник устанавливает, поэтому запрос на видео не попадает, что приводит к сбою. Но когда вы перезагружаете страницу (без очистки кеша), она успешно поймается, и рабочий успешно загружает видео (HTTP 200 в своем инспекторе), но по какой-то причине главная страница бросает net::ERR_FAILED.

И я не могу вручную прочитать/поток, потому что она исходит от другого происхождения, в результате чего «непрозрачным» типа реагирования: http://www.w3.org/TR/service-workers/#cross-origin-resources

UPDATE: обновление для Chrome 42, ошибка теперь HTTP 400 Service Worker Fallback Required (from ServiceWorker). Странно то, что the source code (строка 510) указывает, что он должен быть поднят только при отсутствии заголовков CORS, но здесь режим no-cors.

ответ

7

Прежде всего, я бы порекомендовал попробовать в текущем Chrome Canary, который в настоящее время соответствует выпуску 44.0.2371.0. Инструмент разработчика вокруг сервисных работников продолжает улучшаться с каждым новым выпуском Chrome, и он стал намного лучше с версией 43+ в целом.

Это не похоже, что opaque Response объектов может быть использован для src элемента <video>, и я предполагаю, что это преднамеренно. (Непрозрачные Response s может использоваться для определенных целей, и я боюсь, что я не имею полное изложение того, что будет и не будет работать с непрозрачным Response.)

Но в любом случае, вы повезло в том, что vjs.zencdn.net поддерживает CORS, поэтому вы можете уйти от использования по умолчанию, CORS-enabled Request, что даст вам непрозрачный Response.

Одна вещь, которую вы не можете сделать, это использовать credentials: 'include' в ваших CORS Request, потому что это приведет к Fetch API не может загрузить https://vjs.zencdn.net/v/oceans.mp4. Подстановочный знак '*' не может использоваться в заголовке «Access-Control-Allow-Origin», когда флаг учетных данных является истинным. ошибка. Это не похоже на то, что это проблема с вашим конкретным хостом, поскольку учетные данные не требуются.

Когда я переключил ваш код на использование event.respondWith(fetch('https://vjs.zencdn.net/v/oceans.mp4'));, все сработало нормально.

+0

Большое спасибо Джеффу, заголовки CORS действительно были проблемой! – antoine129

+0

Я открыл проблему в Chromium tracker для улучшения отладки: https://code.google.com/p/chromium/issues/detail?id=477685 – antoine129

Смежные вопросы