1

I know that I can use a service worker to intercept outgoing fetch operations, and even generate custom responses to them, e.g.

self.addEventListener('fetch', (event) => {                   
  if (/\.jpg$/.test(event.request.url)) {                          
    event.respondWith(
      fetch('/images/anotherimage.jpg'));                               
  }
});

However, what if I want to intercept the response to a given fetch request before that response is passed back to the page? Is this doable?

To be clear, I do not in any way want to modify the request itself - I just want to access the response to it.

csvan
  • 8,782
  • 12
  • 48
  • 91
  • You can use `waitUntil`, see the example here: https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent – kol Aug 03 '21 at 20:24
  • you surely can hijack responses using `respondWith()`, though there's no mention of intercepting responses in MDN docs. – GrafiCode Aug 03 '21 at 20:26
  • This is also interesting: https://stackoverflow.com/a/47378383/600135 – kol Aug 03 '21 at 20:28
  • @GrafiCode If "intercepting the response" means catching and possibly changing it, then yes, it's possible. – kol Aug 03 '21 at 20:30
  • `FetchEvent: It contains information about the fetch, including the request and how the receiver will treat the response.` Where's the response? – GrafiCode Aug 03 '21 at 20:32
  • according to this https://googlechrome.github.io/samples/service-worker/fallback-response you have to fetch event.request from within the service worker. – GrafiCode Aug 03 '21 at 20:47

1 Answers1

1

I'm assuming that you mean you'd like to add logic to a service worker so that it requests a resource, and then modifies the response from the network, resulting in a response that's passed back to the page that is a mix of what you'd get from the network and what the service worker added.

If so, the answer is yes, you can do that for same-origin responses, and for cross-origin responses when CORS is used. (You can't modify opaque responses, which is what you get when making a cross-origin request without using CORS.)

Here's an example of a fetch handler that responds to requests for an hypothetical /api endpoint that returns JSON my making the request to /api, and then adding in an additional field to the API response before returning the response to the page.

async function modifyAPIResponse(request) {
  const apiResponse = await fetch(request);
  const json = await apiResponse.json();
  json.extraField = 'set by fetch handler';

  return new Response(JSON.stringify(json), {
    // Ensure that the Content-Type: and other headers are set.
    headers: apiResponse.headers,
  });
}

self.addEventListener('fetch', (event) => {
  const url = new URL(event.request.url);
  if (url.pathname === '/api') {
    event.respondWith(modifyAPIResponse(event.request));
  }
});
Jeff Posnick
  • 53,580
  • 14
  • 141
  • 167