* The handler for fetch events. * * This is the transition point between the synchronous event handler and the * asynchronous execution that eventually resolves for respondWith() and waitUntil().
(event: FetchEvent)
| 231 | * asynchronous execution that eventually resolves for respondWith() and waitUntil(). |
| 232 | */ |
| 233 | private onFetch(event: FetchEvent): void { |
| 234 | const req = event.request; |
| 235 | const scopeUrl = this.scope.registration.scope; |
| 236 | const requestUrlObj = this.adapter.parseUrl(req.url, scopeUrl); |
| 237 | |
| 238 | if (req.headers.has('ngsw-bypass') || /[?&]ngsw-bypass(?:[=&]|$)/i.test(requestUrlObj.search)) { |
| 239 | return; |
| 240 | } |
| 241 | |
| 242 | // The only thing that is served unconditionally is the debug page. |
| 243 | if (requestUrlObj.path === this.ngswStatePath) { |
| 244 | // Allow the debugger to handle the request, but don't affect SW state in any other way. |
| 245 | event.respondWith(this.debugger.handleFetch(req)); |
| 246 | return; |
| 247 | } |
| 248 | |
| 249 | // If the SW is in a broken state where it's not safe to handle requests at all, |
| 250 | // returning causes the request to fall back on the network. This is preferred over |
| 251 | // `respondWith(fetch(req))` because the latter still shows in DevTools that the |
| 252 | // request was handled by the SW. |
| 253 | if (this.state === DriverReadyState.SAFE_MODE) { |
| 254 | // Even though the worker is in safe mode, idle tasks still need to happen so |
| 255 | // things like update checks, etc. can take place. |
| 256 | event.waitUntil(this.idle.trigger()); |
| 257 | return; |
| 258 | } |
| 259 | |
| 260 | // Although "passive mixed content" (like images) only produces a warning without a |
| 261 | // ServiceWorker, fetching it via a ServiceWorker results in an error. Let such requests be |
| 262 | // handled by the browser, since handling with the ServiceWorker would fail anyway. |
| 263 | // See https://github.com/angular/angular/issues/23012#issuecomment-376430187 for more details. |
| 264 | if (requestUrlObj.origin.startsWith('http:') && scopeUrl.startsWith('https:')) { |
| 265 | // Still, log the incident for debugging purposes. |
| 266 | this.debugger.log(`Ignoring passive mixed content request: Driver.fetch(${req.url})`); |
| 267 | return; |
| 268 | } |
| 269 | |
| 270 | // When opening DevTools in Chrome, a request is made for the current URL (and possibly related |
| 271 | // resources, e.g. scripts) with `cache: 'only-if-cached'` and `mode: 'no-cors'`. These request |
| 272 | // will eventually fail, because `only-if-cached` is only allowed to be used with |
| 273 | // `mode: 'same-origin'`. |
| 274 | // This is likely a bug in Chrome DevTools. Avoid handling such requests. |
| 275 | // (See also https://github.com/angular/angular/issues/22362.) |
| 276 | // TODO(gkalpak): Remove once no longer necessary (i.e. fixed in Chrome DevTools). |
| 277 | if (req.cache === 'only-if-cached' && req.mode !== 'same-origin') { |
| 278 | // Log the incident only the first time it happens, to avoid spamming the logs. |
| 279 | if (!this.loggedInvalidOnlyIfCachedRequest) { |
| 280 | this.loggedInvalidOnlyIfCachedRequest = true; |
| 281 | this.debugger.log( |
| 282 | `Ignoring invalid request: 'only-if-cached' can be set only with 'same-origin' mode`, |
| 283 | `Driver.fetch(${req.url}, cache: ${req.cache}, mode: ${req.mode})`, |
| 284 | ); |
| 285 | } |
| 286 | return; |
| 287 | } |
| 288 | |
| 289 | // Past this point, the SW commits to handling the request itself. This could still |
| 290 | // fail (and result in `state` being set to `SAFE_MODE`), but even in that case the |
no test coverage detected