* Load a particular asset from the network, accounting for hash validation.
(req: Request)
| 387 | * Load a particular asset from the network, accounting for hash validation. |
| 388 | */ |
| 389 | protected async cacheBustedFetchFromNetwork(req: Request): Promise<Response> { |
| 390 | const url = this.adapter.normalizeUrl(req.url); |
| 391 | |
| 392 | // If a hash is available for this resource, then compare the fetched version with the |
| 393 | // canonical hash. Otherwise, the network version will have to be trusted. |
| 394 | if (this.hashes.has(url)) { |
| 395 | // It turns out this resource does have a hash. Look it up. Unless the fetched version |
| 396 | // matches this hash, it's invalid and the whole manifest may need to be thrown out. |
| 397 | const canonicalHash = this.hashes.get(url)!; |
| 398 | |
| 399 | // Ideally, the resource would be requested with cache-busting to guarantee the SW gets |
| 400 | // the freshest version. However, doing this would eliminate any chance of the response |
| 401 | // being in the HTTP cache. Given that the browser has recently actively loaded the page, |
| 402 | // it's likely that many of the responses the SW needs to cache are in the HTTP cache and |
| 403 | // are fresh enough to use. In the future, this could be done by setting cacheMode to |
| 404 | // *only* check the browser cache for a cached version of the resource, when cacheMode is |
| 405 | // fully supported. For now, the resource is fetched directly, without cache-busting, and |
| 406 | // if the hash test fails a cache-busted request is tried before concluding that the |
| 407 | // resource isn't correct. This gives the benefit of acceleration via the HTTP cache |
| 408 | // without the risk of stale data, at the expense of a duplicate request in the event of |
| 409 | // a stale response. |
| 410 | |
| 411 | // Fetch the resource from the network (possibly hitting the HTTP cache). |
| 412 | let response = await this.safeFetch(req); |
| 413 | |
| 414 | // Decide whether a cache-busted request is necessary. A cache-busted request is necessary |
| 415 | // only if the request was successful but the hash of the retrieved contents does not match |
| 416 | // the canonical hash from the manifest. |
| 417 | let makeCacheBustedRequest = response.ok; |
| 418 | if (makeCacheBustedRequest) { |
| 419 | // The request was successful. A cache-busted request is only necessary if the hashes |
| 420 | // don't match. |
| 421 | // (Make sure to clone the response so it can be used later if it proves to be valid.) |
| 422 | const fetchedHash = sha1Binary(await response.clone().arrayBuffer()); |
| 423 | makeCacheBustedRequest = fetchedHash !== canonicalHash; |
| 424 | } |
| 425 | |
| 426 | // Make a cache busted request to the network, if necessary. |
| 427 | if (makeCacheBustedRequest) { |
| 428 | // Hash failure, the version that was retrieved under the default URL did not have the |
| 429 | // hash expected. This could be because the HTTP cache got in the way and returned stale |
| 430 | // data, or because the version on the server really doesn't match. A cache-busting |
| 431 | // request will differentiate these two situations. |
| 432 | // TODO: handle case where the URL has parameters already (unlikely for assets). |
| 433 | const cacheBustReq = this.newRequestWithMetadata(this.cacheBust(req.url), req); |
| 434 | response = await this.safeFetch(cacheBustReq); |
| 435 | |
| 436 | // If the response was successful, check the contents against the canonical hash. |
| 437 | if (response.ok) { |
| 438 | // Hash the contents. |
| 439 | // (Make sure to clone the response so it can be used later if it proves to be valid.) |
| 440 | const cacheBustedHash = sha1Binary(await response.clone().arrayBuffer()); |
| 441 | |
| 442 | // If the cache-busted version doesn't match, then the manifest is not an accurate |
| 443 | // representation of the server's current set of files, and the SW should give up. |
| 444 | if (canonicalHash !== cacheBustedHash) { |
| 445 | throw new SwCriticalError( |
| 446 | `Hash mismatch (cacheBustedFetchFromNetwork): ${req.url}: expected ${canonicalHash}, got ${cacheBustedHash} (after cache busting)`, |
nothing calls this directly
no test coverage detected
searching dependent graphs…