Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append string to user agent within Service Worker

I've been stuck on this problem for a while now. I have researched in depth and have spent a lot of time looking at similar questions on SO - but unsuccessful.

A bit of background. I have a website and an android app which effectively renders the website in a different form with different displays etc... The app knows to do this from incoming requests - as users have a particular string appended to the user agent (let's just say that string is 'MobileAppRequest'). Upon detecting this string in the user agent, the server knows to return a different html file. This allows the user to still go to the website on their browser and use the web version as well as have the app experience from their android app.

Now, upon using a service worker, it defaults to the user's standard user agent without including the appended string from the app. This then returns the web version within the app which messes it all up. I need to know how to set custom headers, or indeed, append a string to the user agent within the service worker. It says the headers are immutable when i try to directly change it but i know a way around this is to make a new request as a response.

Here is my 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);
      })
  );
});

I would appreciate the answers contain either the full sw.js or the whole function you're editing just so i don't make any mistakes integrating back into the code.

like image 950
SkyBlue Avatar asked Nov 14 '18 12:11

SkyBlue


People also ask

What is User Agent string Reduction?

User-Agent Reduction is an effort to reduce passive fingerprinting surfaces by reducing the information in the User-Agent (UA) string to only the browser's brand and significant version, its desktop or mobile distinction, and the platform it's running on.

What is Http_user_agent?

It's just a string that a browser optionally sends to the server. Firefox can let you change the string entirely via the about:config page by modifying/creating the string general. useragent.

Where is the user agent string?

The User-Agent (UA) string is contained in the HTTP headers and is intended to identify devices requesting online content. The User-Agent tells the server what the visiting device is (among many other things) and this information can be used to determine what content to return.

What is userAgent in JS?

Definition and Usage. The userAgent property returns the user-agent header sent by the browser to the server. The userAgent property is read-only. The value returned, contains information about the browser name, version and platform.


1 Answers

As I mentioned in the comments, you can pass the whatever data you want to the Service Worker if you use postMessage().

Below is an example using your script.

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);
      })
  );
});

While browsing SO is great for examples, sometimes it's better to reference the documentation when you have limited options.

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

like image 140
JM-AGMS Avatar answered Oct 12 '22 19:10

JM-AGMS