0

I need to implement serviceworker file caching, but using a no-cors flag. This is because I get a CORS error on my webserver for below code. The code is from the standard Ionic 2 starter template (inside serviceworker.js). I can't use the standard code because for some reason the requests trigger an authentication flow in which there is a redirect to some URL, which fails because of a CORS error.

How would I do that in the nicest (cq. easiest) way?

// TODO: Implement this without CORS (set no-cors flag)
self.toolbox.precache(
  [
    // './build/main.js',
    // './build/vendor.js',
    // './build/main.css',
    // './build/polyfills.js',
   // 'index.html',
   // 'manifest.json'
  ]
);

EDIT: It's not really an authentication error that happens, the user is definitely already authenticated. But because of the redirect during the authentication the request for the files above goes wrong. I found this article: What is an opaque request, and what it serves for? which indicates settings the no cors flag would be the solution. The error I get, like on that page is: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://abc' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

JurgenW
  • 307
  • 2
  • 4
  • 18
  • Surely, if you set the no-cors flag, then you'll still hit the authentication error and everything will stop. – Quentin Nov 30 '17 at 14:02

1 Answers1

0

Solved it myself like below. The install event is what triggers the app to store files locally.

/**
 * Check out https://googlechromelabs.github.io/sw-toolbox/ for
 * more info on how to use sw-toolbox to custom configure your service worker.
 */


'use strict';
importScripts('./build/sw-toolbox.js');

self.toolbox.options.cache = {
  name: 'ionic-cache'
};

// pre-cache our key assets
// TODO: Implemente this without using CORS (set no-cors flag)
/*
self.toolbox.precache(
  [
    './build/main.js',
    './build/vendor.js',
    './build/main.css',
    './build/polyfills.js',
    'index.html',
    'manifest.json'
  ]
);
*/

// MANUAL precaching in order to evade CORS error on SharePoint

var aFilesToCache = [
  './assets/json/propertyLUT.js',
  './assets/json/propertyvalues.js',
  './build/main.js',
  './build/vendor.js',
  './build/main.css',
  './build/polyfills.js',
  'index.html',
  'manifest.json'
];

self.addEventListener('fetch', function(event) {
  console.log('Handling fetch event for', event.request.url);

  event.respondWith(

    // Opens Cache objects that start with 'font'.
    caches.open('pwa_').then(function(cache) {
      return cache.match(event.request).then(function(response) {
        if (response) {
          console.log('Found response in cache:', response);

          return response;
        } 
      }).catch(function(error) {

        // Handles exceptions that arise from match() or fetch().
        console.error('Error in fetch handler:', error);

        throw error;
      });
    })
  );
});

self.addEventListener('install', event => {
  function onInstall(event, filesToCache) {
    console.log('Hit event INSTALL');
    return Promise.all(filesToCache.map(function(aUrl) 
    {
      return caches.open('pwa_').then(function(cache) 
      {
        debugger;
        aUrl = resolveURL(aUrl, self.location.href);
        return fetch(aUrl, { mode: 'no-cors' })
            .then(function(response) 
            {
              return cache.put(aUrl, response.clone());
            });

      })
    }))
  }

  event.waitUntil(
    onInstall(event, aFilesToCache).then( () => self.skipWaiting() )
  );
});

function resolveURL(relative, base) {
  var stack = base.split("/"),
      parts = relative.split("/");
  stack.pop(); // remove current file name (or empty string)
               // (omit if "base" is the current folder without trailing slash)
  for (var i=0; i<parts.length; i++) {
      if (parts[i] == ".")
          continue;
      if (parts[i] == "..")
          stack.pop();
      else
          stack.push(parts[i]);
  }
  return stack.join("/");
}
/*
foreach(aUrl in aFilesToCache)
{
  var corsRequest = new Request(url, {mode: 'no-cors'});
  fetch(corsRequest).then(response => {
    return cache.put("pwa_" + url, response);
  }); // response won't be opaque.
}
*/

// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.fastest);

// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;
JurgenW
  • 307
  • 2
  • 4
  • 18