Как я могу передать видео с ServiceWorker?
У меня есть сотрудник службы, который ловит мои запросы на страницу (fetch
event), и когда URL-адрес соответствует определенному шаблону, он будет извлекать другой URL-адрес и заменять ответ на это новое содержимое.
Он отлично работает для текстовых данных (JS, XML...) или двоичных данных (например, изображений), но когда дело доходит до видео, происходит сбой.
Я использую 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)
. Странно то, что исходный код (строка 510) указывает, что он должен быть поднят только при отсутствии заголовков CORS, но здесь режим no-cors
.
Ответы
Ответ 1
Во-первых, я рекомендую попробовать в текущем Chrome Canary, который в настоящее время соответствует выпуску 44.0.2371.0. Инструмент разработчика вокруг сервисных работников продолжает улучшаться с каждым новым выпуском Chrome, и он стал намного лучше с версией 43+ в целом.
Это не похоже на opaque Response
объекты могут быть использованы для src
элемента <video>
, и я предполагаю, что преднамеренное, (Opaque Response
может использоваться для определенных целей, и я боюсь, что у меня нет полного изложения того, что будет и не будет работать с непрозрачным Response
.)
Но в любом случае вам повезло, что vjs.zencdn.net
поддерживает CORS, поэтому вы можете уйти с использованием стандартного CORS-включенного Request
, который даст вам непрозрачный Response
.
Одна вещь, которую вы не можете сделать, это использовать credentials: 'include'
в CORS Request
, потому что это приведет к тому, что API-интерфейс Fetch не сможет загрузить https://vjs.zencdn.net/v/oceans.mp4., Подстановочный знак '*' не может использоваться в заголовке "Access-Control-Allow-Origin", когда флаг учетных данных является истинным. ошибка. Это не похоже на проблему с вашим конкретным хостом, поскольку учетные данные не требуются.
Когда я переключил ваш код на использование event.respondWith(fetch('https://vjs.zencdn.net/v/oceans.mp4'));
, все работало нормально.