Добавить строку в пользовательский агент в Service Worker - PullRequest
0 голосов
/ 14 ноября 2018

Я застрял на этой проблеме некоторое время. Я глубоко изучил и потратил много времени, рассматривая похожие вопросы по SO, но безуспешно.

Немного фона. У меня есть веб-сайт и приложение для Android, которое эффективно отображает веб-сайт в другой форме с разными дисплеями и т. Д. Приложение знает, как делать это по входящим запросам - поскольку у пользователей есть определенная строка, добавленная к пользовательскому агенту (скажем так, строка 'MobileAppRequest'). Обнаружив эту строку в пользовательском агенте, сервер знает, как вернуть другой HTML-файл. Это позволяет пользователю по-прежнему заходить на веб-сайт в своем браузере и использовать веб-версию, а также использовать приложение в своем приложении для Android.

Теперь, при использовании сервисного работника, по умолчанию используется стандартный пользовательский агент пользователя без добавления строки приложения. Затем он возвращает веб-версию в приложении, которая все испортила. Мне нужно знать, как установить пользовательские заголовки, или, действительно, добавить строку к пользовательскому агенту в сервис-работнике. В нем говорится, что заголовки являются неизменяемыми, когда я пытаюсь изменить их напрямую, но я знаю, что способ обойти это - сделать новый запрос в качестве ответа.

Вот мой SW.js

var CACHE_STATIC_NAME = 'static-v10';
var CACHE_DYNAMIC_NAME = 'dynamic-v2';

self.addEventListener('install', function (event) {
  console.log('[Service Worker] Installing Service Worker ...', event);
  event.waitUntil(
    caches.open(CACHE_STATIC_NAME)
      .then(function (cache) {
        console.log('[Service Worker] Precaching App Shell');
        cache.addAll([
          '/',
          '/static/media/next.png',
          '/static/media/previous.png'
        ]);
      })
  )
});

self.addEventListener('activate', function (event) {
  console.log('[Service Worker] Activating Service Worker ....', event);
  event.waitUntil(
    caches.keys()
      .then(function (keyList) {
        return Promise.all(keyList.map(function (key) {
          if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
            console.log('[Service Worker] Removing old cache.', key);
            return caches.delete(key);
          }
        }));
      })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request)
      .then(function(res) {
        return caches.open(CACHE_DYNAMIC_NAME)
                .then(function(cache) {
                  cache.put(event.request.url, res.clone());
                  return res;
                })
      })
      .catch(function(err) {
        return caches.match(event.request);
      })
  );
});

Я был бы признателен, чтобы ответы содержали либо полный sw.js, либо всю функцию, которую вы редактируете, так что я не делаю ошибок при интеграции обратно в код.

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Как я уже упоминал в комментариях, вы можете передать любые данные, которые вы хотите, специалисту по обслуживанию, если вы используете postMessage().

Ниже приведен пример использования вашего скрипта.

webpage.html

<script>
  // creates ServiceWorker
  var worker = new Worker('SW.js');
  // sends the browser's userAgent to the ServiceWorker
  worker.postMessage(window.navigator.userAgent);
</script>

SW.js

var CACHE_STATIC_NAME = 'static-v10';
var CACHE_DYNAMIC_NAME = 'dynamic-v2';
// defines a global variable that will hold the UserAgent
var UA = '';

// listens to incoming postMessage()
self.addEventListener("message", function(event) {
  // update the UA variable with the event.data, which is the browser's UserAgent
  UA = event.data;
  console.log('ServiceWorker now has UA variable defined as ', UA);
}, false);

self.addEventListener('install', function (event) {
  console.log('[Service Worker] Installing Service Worker ...', event);
  event.waitUntil(
    caches.open(CACHE_STATIC_NAME)
      .then(function (cache) {
        console.log('[Service Worker] Precaching App Shell');
        cache.addAll([
          '/',
          '/static/media/next.png',
          '/static/media/previous.png'
        ]);
      })
  )
});

self.addEventListener('activate', function (event) {
  console.log('[Service Worker] Activating Service Worker ....', event);
  event.waitUntil(
    caches.keys()
      .then(function (keyList) {
        return Promise.all(keyList.map(function (key) {
          if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
            console.log('[Service Worker] Removing old cache.', key);
            return caches.delete(key);
          }
        }));
      })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(event) {
  // var myHeader = new Headers(event.request.headers);
  // myHeader.append('CUSTOMHEADER', 'CUSTOMVALUE');
  // you can now make a request using the passed UA
  event.respondWith(
    fetch(event.request, {credentials: 'same-origin', mode: 'cors', redirect: 'follow', userAgent: UA}).then(function(res) {
        return caches.open(CACHE_DYNAMIC_NAME)
                .then(function(cache) {
                  cache.put(event.request.url, res.clone());
                  return res;
                })
      })
      .catch(function(err) {
        return caches.match(event.request);
      })
  );
});

Хотя просмотр SO отлично подходит для примеров, иногда лучше обратиться к документации, если у вас ограниченные возможности.

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

0 голосов
/ 18 ноября 2018

Я отредактировал ваш код, чтобы добавить пользовательский заголовок в запрос на выборку.Вы должны попробовать с ним, Это будет работать.

Для вашего случая использования вы хотите добавить пользовательский заголовок только для вашего запроса домена, поэтому я добавил проверку регулярного выражения, которая будет проверять и добавлять пользовательский заголовок вполучать запросы, относящиеся только к вашему домену.(добавлен localhost для локального тестирования).Для запросов на выборку, относящихся к другому домену, он отправит стандартные заголовки.

Вам нужно передать некоторые дополнительные параметры для получения вызова, который я добавил.В вашем приложении отредактируйте «CUSTOMHEADER», «CUSTOMVALUE» и YOURDOMAIN.com так, как вы хотите.

Подробнее о Header () см. https://developer.mozilla.org/en-US/docs/Web/API/Headers. Если вы хотите изменить useragent, добавьте следующие строкив событии fetch в ответе

  var myHeader = new Headers(event.request.headers);
  myHeader.delete('User-Agent');
  myHeader.set('User-Agent', 'CUSTOM_USERAGENTVALUE');

Обратите внимание: изменение «User-Agent» на данный момент не рекомендуется, так как недавно оно было удалено из списка запрещенных заголовков.Так что поддержка браузера ограничена.

var CACHE_STATIC_NAME = 'static-v10';
var CACHE_DYNAMIC_NAME = 'dynamic-v2';

self.addEventListener('install', function (event) {
  console.log('[Service Worker] Installing Service Worker ...', event);
  event.waitUntil(
    caches.open(CACHE_STATIC_NAME)
      .then(function (cache) {
        console.log('[Service Worker] Precaching App Shell');
        cache.addAll([
          '/',
          '/static/media/next.png',
          '/static/media/previous.png'
        ]);
      })
  )
});

self.addEventListener('activate', function (event) {
  console.log('[Service Worker] Activating Service Worker ....', event);
  event.waitUntil(
    caches.keys()
      .then(function (keyList) {
        return Promise.all(keyList.map(function (key) {
          if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
            console.log('[Service Worker] Removing old cache.', key);
            return caches.delete(key);
          }
        }));
      })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(event) {
    if(/^.*\:\/\/(?:localhost|YOURDOMAIN\.com)\/.*/.test(event.request.url))
    { var myHeader = new Headers(event.request.headers);
      myHeader.append('CUSTOMHEADER', 'CUSTOMVALUE');
      console.log('Custom Fetch Call:'+event.request.url);
      event.respondWith(
        fetch(event.request.url, {credentials: 'same-origin', redirect: 'follow', headers: myHeader}).then(function(res) {
            return caches.open(CACHE_DYNAMIC_NAME)
                    .then(function(cache) {
                      cache.put(event.request.url, res.clone());
                      return res;
                    })
          })
          .catch(function(err) {
            return caches.match(event.request);
          })
      );
      return
    }
    event.respondWith(
      fetch(event.request).then(function(res) {
        return caches.open(CACHE_DYNAMIC_NAME)
                .then(function(cache) {
                  cache.put(event.request.url, res.clone());
                  return res;
                })
      })
      .catch(function(err) {
        return caches.match(event.request);
      })
    );  


});

Вы можете проверить это на сервисе echo $_SERVER['HTTP_CUSTOMHEADER'];, он будет отображаться CUSTOMVALUE.Я перекрестно проверил, работает ли он на стороне сервера и на сетевой панели Chrome.

Чтобы предоставить пользовательскому пользователю Android страницу приложения, вы должны использовать (В PHP):

$INSIDEAPP = (isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'],'CUSTOMUSERAGENT') !== false))? true:false;
$INSIDE_SW = (isset($_SERVER['HTTP_CUSTOMHEADER']))?true:false;

$SERVE_APP_PAGE = $INSIDEAPP || $INSIDE_SW;

if($SERVE_APP_PAGE)
{
//serve request of app page.
}
else
{
// serve normal request through browser
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...