0

Good afternoon,

We're working with an opensource CMS. Last version we upgraded, it comes with a new feature which is a javascript serviceworker implementation to handle all the requests made.

This CMS have some workflow forms where users interact (designed by us). On design time, you can add some custom html on them as an special snippet elements, which can hold all the JS, HTML and CSS code you desire.

We created a button which on click, made a $.get() to a Python Flask server we have online/active on the same machine-instance (https://localhost:5000/).

With previous CMS version before upgrade (no serviceworker was present on it), if we stopped the Flask server, on a button click $.get() we received an error as expected (404/500), so we could handle it with ".fail()" jQuery part. But if Flask was active, we handle it on ".done()" part.

Now, it happens that EVERYTHING falls on ".done()", because even when it should fail (because Flask is offline), serviceworker "middle-catches" it and resolves with an OK (200):

enter image description here enter image description here

When in reality server is down:

enter image description here

So, how can we avoid serviceworker to catch the ajax call, knowing that we cannot alter the serviceworker code in any way? Can we extend it somehow, to add on the "fetch" listener a validation against "/api" url to just "return;"?

This is the catching point as Chrome says to:

enter image description here

And piece of function code:

self.addEventListener('fetch', function (event) {
//https://stackoverflow.com/questions/48463483/what-causes-a-failed-to-execute-fetch-on-serviceworkerglobalscope-only-if
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
    return;
}

var fetchRequest = event.request.clone();

event.respondWith(
    fetch(fetchRequest)
    .then(function (response) {
        //redirect links eg. /jw/home, userview root url, are of response.type 'opaqueredirect', and possibly response.status != 200
        //it is generally not a good idea to cache redirection because the content (target of redirection) might be changed
        //https://medium.com/@boopathi/service-workers-gotchas-44bec65eab3f
        //but without this the top-right home button (/jw/home) will never be cached and will always show offline page when being accessed offline
        //if (!response || response.status !== 200 || response.type !== 'basic' || event.request.method !== 'GET') {
        if (!response || event.request.method !== 'GET') {
            return response;

        } else {
            if(fetchRequest.url.indexOf('/web/json/workflow/currentUsername') === -1 
                    && fetchRequest.url.indexOf('/images/v3/cj.gif') === -1
                    && fetchRequest.url.indexOf('/images/favicon_uv.ico?m=testconnection') === -1){
                var responseToCache = response.clone();
                caches.open(cache)
                    .then(function (cache) {
                        cache.put(event.request, responseToCache);
                    });
            }
        }
        
        return response;
    })
    .catch(function () {
        if(event.request.method === 'POST' && formData !== null){
            console.log('form POST failed, saving to indexedDB');

            savePostRequest(event.request.clone().url, formUserviewAppId, formPageTitle, formData, formUsername);

            //redirect instead
            var response = Response.redirect(self.registration.scope + '/_/pwaoffline', 302);
            return response;

        }else{

            if(fetchRequest.url.indexOf('/images/favicon_uv.ico?m=testconnection') > -1){
                //var response = new Response(new Blob(), { "status" : 404 });
                return null;
            }

            return new Promise(function(resolve, reject) {
                caches.match(event.request).then(function(response){
                    if(response === undefined){
                        var offlineResponse = Response.redirect(self.registration.scope + '/_/offline', 302);
                        resolve(offlineResponse);
                    }else{
                        resolve(response);
                    }
                })
            });                

        }
    })
);

});

Thanks alot and regards.

Lightworker
  • 533
  • 1
  • 5
  • 16

1 Answers1

0

Well, no answers. Ok.

So if anyone is interested I explain how I've solved it. Basically, with a "rodeo":

  • There is no way to alter the serviceworker functionality (as it is a 3rd party SW, which I cannot edit).
  • So the only way is to "avoid cache" every time, with "cache: false" on every ajax call.
  • This way SW cannot serve an "offline" version of the page, and I do not receive the real page (cached, but real) every time even if online.
  • So instead on recalling to .done() and .fail(), everything goes to "done()" (as all is 200 OK), but I check response content in there, like in the old days... This way if server is online, it resolves a real 200 OK with the correct expected response. But if it is offline, as I use the "cache: false" parameter, even with the SW OK 200, the response doesn't comes with the real expects response text. So conditional fails and I can consider it as a real 404.

Simple, but that's it.

marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
Lightworker
  • 533
  • 1
  • 5
  • 16