Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable preflight cache-control headers for Angular service-worker (when calling event stream)?

Update 2: See my answer below. The 504 error is fixed

UPDATE: It appears this is NOT due to the cache-control headers, despite the error. If I disable the service worker, the headers are still present. Instead, this is due to the service worker causing 504 (Gateway Timeout) on the API. Any idea how to fix this?

I've built a full MEAN-stack app and it works great until I use service workers.

The main error I get is

Failed to load ${apiUrl} Request header field Cache-Control is not allowed by Access-Control-Allow-Headers in preflight response.

I get this when trying to access an external API (api.particle.io), where I have no control over their CORS settings.

I've tried adjusting my ngsw-config.json by adding the API url to dataGroups, but so far, that just adds an additional error:

Uncaught (in promise) TypeError: Failed to fetch ngsw-worker.js

This only happens when trying to fetch an event stream using:

watchStatus(url: string): Observable<eventResponse> {
        return new Observable<eventResponse>(obs => {
            const source = new EventSource(url);
            source.addEventListener('status', (event) => {
                obs.next(JSON.parse(event.data).data);
            });
            return () => source.close();
        });
    }

Is there a way to call this with an observable? I couldn't get Server-Sent Events working without EventSource, but maybe I'm doing it wrong.

My ngsw-config.json:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }, {
    "name": "fonts",
    "resources": {
      "urls": [
        "https://fonts.googleapis.com/**",
        "https://fonts.gstatic.com/**"
      ]
    }
}],
  "dataGroups": [
      {
          "name": "photon-api",
          "urls": [
              "http://api.particle.io/**",
              "https://api.particle.io/**"
          ],
          "cacheConfig" : {
              "strategy": "freshness",
              "maxSize": 0,
              "maxAge": "0u"
          }
      }
  ]
}

Is it possible to disable the preflight Cache-Control header changing my ngsw-config.json?


1 Answers

Got it!

I fixed it based off a github issue answer found here.

Basically, the service worker catches everything with onFetch. To whitelist my API URLs, I opened ngsw-worker.js and changed onFetch(event) to:

onFetch(event) {
    const req = event.request;
    // List of words in request URL to whitelist/bypass the service worker
    const whitelist = ['api', 'otherWhitelistWords...']
    // Check to see if request url contains any whitelisted words and skip the rest of onFetch if it does
    if (whitelist.some(word => req.url.toLowerCase().includes(word.toLowerCase()))) {
                return
    }
   ...
}

You can automate fixing of ng build:prod by creating a fix-sw.sh:

#!/bin/bash
sed -i "/onFetch(event) {/,/const req = event.request;/c onFetch(event){const req=event.request;const whitelist=['api','otherWhitelistWords...'];if(whitelist.some(word=>req.url.toLowerCase().includes(word.toLowerCase()))){return}" ./dist/${PROJECTNAME}/ngsw-worker.js

then, in package.json, change your build:prod to:

"build:prod": "ng build --prod && bash ./fix-sw.sh",

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!