Подтвердить что ты не робот

Как я могу передать видео с 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.

4b9b3361

Ответ 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'));, все работало нормально.