Understanding Service Worker scope
Service workers are basically a proxy between your web application and the internet, so it can intercept calls to the network if so desired.
Scope in this instance refers to the path that the service worker will be able to intercept network calls from. The scope
property can be used explicitly define the scope it will cover. However:
Service workers can only intercept requests originating in the scope of the current directory that the service worker script is located in and its subdirectories. Or as MDN states:
The service worker will only catch requests from clients under the service worker's scope.
The max scope for a service worker is the location of the worker.
As your service worker is located in /static/mod/practice/
, it's not allowed to set its scope to /practice/foopage/
. Requests to other hosts, e.g. https://stackoverflow.com/foo
, can be intercepted in any case.
The easiest way to ensure that your service worker can intercept all the calls it needs to, would be to place it in the root directory of your web app (/
). You can also override the default restrictions using an http header and manually setting the scope (see Ashraf Sabry's answer).
How to register a service worker's scope one directory above where the service_worker.js is located
The max scope for a service worker is where it is located. This means you can not register one service worker located at /sw/
in scope: '/public_html/'
unless you include a special header Service-Worker-Allowed
set to the new max scope for your service worker.
Summarizing, if you can add this header when serving the service worker, set it as follows:
Service-Worker-Allowed: /public_html/
If not, you must place the sw at some location above the scope.
How exactly add Service-Worker-Allowed to register service worker scope in upper folder
Ok... I was a little confused, and even now I guess I have to get deep in the facts and study http headers better...
Anyway as stated in many questions & answer on stackoverflow, it's not possible to alter headers during http request, unless it's not an ajax request (and that's not this case).
now on this post Understanding Service Worker scope for a similar question
@Ashraf Sabry answered he could alter the headers using web.config file of IIS Web Server. --> So finally I understood that the header to add is a response header, but before the response is interpreted by the browser --> As stated here https://learn.microsoft.com/en-us/iis/configuration/system.webserver/httpprotocol/customheaders/
that configuration is for response header.
I guess there is not clear way to control that header to make service worker doing his work in a subfolder using html/javascript... It's a problem that could be solved only with server configurations.
A was doing my tests on Node, for didactical porpouse I tried to write a simple http server to test this issue starting from this tutorial https://ilovecoding.org/lessons/create-a-simple-http-server-with-nodejs
the result is here (a "server.js" file runned on Node):
var http = require('http');
var url = require('url');
var querystring = require('querystring');
var fs = require('fs');
http.createServer(function(request, response){
pathName = url.parse(request.url).pathname;
console.log(pathName);
fs.readFile(__dirname + pathName, function(err, data){
if(err){
response.writeHead(404, {'Content-type':'text/plain'});
response.write('Page Was Not Found');
response.end();
}else{
if(pathName.endsWith(".html")){
//response.writeHead(200, {'Service-Worker-Allowed':'/', 'Content-Type':'text/html'});
response.writeHead(200, {'Content-Type':'text/html'});
console.log("serving html");
}else if(pathName.endsWith(".js")){
response.writeHead(200, {'Service-Worker-Allowed':'/', 'Content-Type':'application/javascript'});
//response.writeHead(200, {'Content-Type':'text/javascript'});
console.log("serving js");
}else if(pathName.endsWith(".css")){
//response.writeHead(200, {'Service-Worker-Allowed':'/', 'Content-Type':'text/css'});
response.writeHead(200, {'Content-Type':'text/css'});
console.log("serving css");
}else{
response.writeHead(200);
console.log("serving other");
}
response.write(data);
response.end();
}
})
}).listen(8080);
Using this js Node Server I could reach the same result stated for settings in IIS in the above link.
Note that after some test with this js, I reached that the file which needs "Service-Worker-Allowed:/" is the app.js file.
Now the application work as wanted returning no error.
As final prove tracing requests on fiddler I can clearly see the initial request for app.js, with "Service-Worker-Allowed: /" in the response;
My conclusion is that not always it is possible to handle server configuration, so putting service worker file on root folder of the app is the best approach.
Hope this could be helpful for some others...
Do the http requests from within a ServiceWorker not come form the scope set when registering?
You can access this scope value from your ServiceWorker by checking the self.registration.scope
value.
From there all you have to do is to convert your assets's relative URLs to absolute ones by using this value.
cache.addAll([
"./main.css",
"./logo.png"
] // make them relative to the SW's scope
.map((url) => new URL(url, registration.scope))
);
Related Topics
How to Show Modal Window in Controller's Action
How to Detect Faces Using Ruby
"Document.Getelementbyclass Is Not a Function"
Why Does "True" == True Show False in JavaScript
JavaScript Parse Float Is Ignoring the Decimals After My Comma
How to Tell If a <Script> Tag Failed to Load
How to Make Regular Expression into Non-Greedy
Wkwebview - Complex Communication Between JavaScript & Native Code
Js Replace Not Working on String
Concerns, Decorators, Presenters, Service Objects, Helpers - Help Me Understand Them
Pdf.Js: Rendering a PDF File Using a Base64 File Source Instead of Url
How to Print Part of a Rendered HTML Page in JavaScript
Prevent Long Running JavaScript from Locking Up Browser