Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Response whose "body" is locked cannot be used to respond to a request

I was just trying service workers in google chrome. I stumbled upon an error. Googling the error gives one single result at the moment which seems to be in the google chrome sourcecode.

I am not convinced that the error is bug. When I try in firefox, I get Corrupted Content Error screen. It occurs when I handling fetch event for the project root:

self.addEventListener('fetch', function(event) {
  // Nice url
  var requestURL = new URL(event.request.url);
  console.log("Request for: ", requestURL.href);
  // Network, then cache, then fallback
  event.respondWith(
    // Try to download
    fetch(event.request)
      .then(function(x) {
        console.log("    "+requestURL.href+" >> ",x);
        // If failed the x will not be ok
        if(x && x.ok) {
          // If result was ok save it to cache
          cache.put(event.request, x);
          return x;
        }
        else
          // Try to fetch cached version if request failed
          return cache.match(event.request);
      })
      // In case of error return something like 404 page
      .catch(function(error) {
        console.warn("    "+requestURL.href+" >> UNAVAILABLE: ",error);
        return cache.match('/page/content-not-available-offline');
      })
  );
});

I'm not sure what the body locked error means, so I don't even know what code is relevant.

like image 553
Tomáš Zato - Reinstate Monica Avatar asked Jun 10 '16 11:06

Tomáš Zato - Reinstate Monica


1 Answers

The problem is that body of the response (the actual content, such as HTML or JavaScript) can be only used once for certain purposes, such as saving into cache or using as actual response.

To solve this, Response.prototype.clone() method exists.

In fact, the main reason clone() exists is to allow multiple uses of Body objects (when they are one-use only.)

In this case, the problem was storing the response in cache and then returning it. Correct approach is:

if(x && x.ok) {
  // If result was ok save it to cache
  cache.put(event.request, x.clone());
  return x;
}
like image 190
Tomáš Zato - Reinstate Monica Avatar answered Sep 27 '22 00:09

Tomáš Zato - Reinstate Monica