2

Is there any way for a ServiceWorker to identify the source or origin of a no-cors/opaque FetchEvent.Request? Or can we explicitly pass identifying information/data from the HTML to the ServiceWorker that could be used to identify origins of FetchEvents?. I hacked together a solution using query string parameters, but I'm looking for something more native or elegant than this:

HTML

<img id="img1" src="image.jpg?imgId=img1" />
<img id="img2" src="image.jpg?imgId=img2" />

Service Worker

self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if(url.pathname.endsWith('/image.jpg')) {
    // get Element ID that initated the FetchEvent
    const imgId = url.searchParams.get('imgId');

    // Notify document that the fetch started
    clients.get(event.clientId)
    .then(client => client.postMessage({imgId}));
  }
})
anthumchris
  • 8,245
  • 2
  • 28
  • 53

1 Answers1

2

First off, from the point of view of the service worker's fetch handler, the fact that the request has a mode of 'no-cors' shouldn't change anything. Opaque responses are a thing in order to prevent information leakage from third-party servers, but when you're talking about a request that originated from your own page being intercepted by your own service worker, there isn't the same concern about information leakage.

So, in general, the question is whether there's a way to get the browser to add in extra identifying information to the requests it implicitly creates for any subresource referenced in your DOM. Taking a look at the fields exposed in the Request object, there really isn't anything other than url that you have control over and could potentially set to something useful for identifying your outgoing requests. (You won't be able to control the headers for the implicitly created requests used for subresources referenced in your DOM.)

If you wanted to prevent the "noise" of using parameters to add in the identifying information to the url, you should be able to get away with using hash fragments, like

<img id="img1" src="image.jpg#img1">
<img id="img2" src="image.jpg#img2">

The service worker specification states that the hash fragment should be included in the request.url that's passed in to your fetch handler, so you can read it from there, but it won't actually be sent to the remote server.

(One of the things that you can get is the destination of a Request object, if you wanted to distinguish between requests which will be used for images, fonts, scripts, etc. But that won't allow you to identify which specific <img> was responsible for a given image request.)

Jeff Posnick
  • 53,580
  • 14
  • 141
  • 167