123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- Copyright 2018 Google LLC
- Use of this source code is governed by an MIT-style
- license that can be found in the LICENSE file or at
- https://opensource.org/licenses/MIT.
- */
- import {WorkboxError} from './WorkboxError.mjs';
- import {logger} from './logger.mjs';
- import {assert} from './assert.mjs';
- import {getFriendlyURL} from '../_private/getFriendlyURL.mjs';
- import {pluginEvents} from '../models/pluginEvents.mjs';
- import {pluginUtils} from '../utils/pluginUtils.mjs';
- import '../_version.mjs';
- /**
- * Wrapper around the fetch API.
- *
- * Will call requestWillFetch on available plugins.
- *
- * @param {Object} options
- * @param {Request|string} options.request
- * @param {Object} [options.fetchOptions]
- * @param {Event} [options.event]
- * @param {Array<Object>} [options.plugins=[]]
- * @return {Promise<Response>}
- *
- * @private
- * @memberof module:workbox-core
- */
- const wrappedFetch = async ({
- request,
- fetchOptions,
- event,
- plugins = []}) => {
- // We *should* be able to call `await event.preloadResponse` even if it's
- // undefined, but for some reason, doing so leads to errors in our Node unit
- // tests. To work around that, explicitly check preloadResponse's value first.
- if (event && event.preloadResponse) {
- const possiblePreloadResponse = await event.preloadResponse;
- if (possiblePreloadResponse) {
- if (process.env.NODE_ENV !== 'production') {
- logger.log(`Using a preloaded navigation response for ` +
- `'${getFriendlyURL(request.url)}'`);
- }
- return possiblePreloadResponse;
- }
- }
- if (typeof request === 'string') {
- request = new Request(request);
- }
- if (process.env.NODE_ENV !== 'production') {
- assert.isInstance(request, Request, {
- paramName: request,
- expectedClass: 'Request',
- moduleName: 'workbox-core',
- className: 'fetchWrapper',
- funcName: 'wrappedFetch',
- });
- }
- const failedFetchPlugins = pluginUtils.filter(
- plugins, pluginEvents.FETCH_DID_FAIL);
- // If there is a fetchDidFail plugin, we need to save a clone of the
- // original request before it's either modified by a requestWillFetch
- // plugin or before the original request's body is consumed via fetch().
- const originalRequest = failedFetchPlugins.length > 0 ?
- request.clone() : null;
- try {
- for (let plugin of plugins) {
- if (pluginEvents.REQUEST_WILL_FETCH in plugin) {
- request = await plugin[pluginEvents.REQUEST_WILL_FETCH].call(plugin, {
- request: request.clone(),
- event,
- });
- if (process.env.NODE_ENV !== 'production') {
- if (request) {
- assert.isInstance(request, Request, {
- moduleName: 'Plugin',
- funcName: pluginEvents.CACHED_RESPONSE_WILL_BE_USED,
- isReturnValueProblem: true,
- });
- }
- }
- }
- }
- } catch (err) {
- throw new WorkboxError('plugin-error-request-will-fetch', {
- thrownError: err,
- });
- }
- // The request can be altered by plugins with `requestWillFetch` making
- // the original request (Most likely from a `fetch` event) to be different
- // to the Request we make. Pass both to `fetchDidFail` to aid debugging.
- let pluginFilteredRequest = request.clone();
- try {
- let fetchResponse;
- // See https://github.com/GoogleChrome/workbox/issues/1796
- if (request.mode === 'navigate') {
- fetchResponse = await fetch(request);
- } else {
- fetchResponse = await fetch(request, fetchOptions);
- }
- if (process.env.NODE_ENV !== 'production') {
- logger.debug(`Network request for `+
- `'${getFriendlyURL(request.url)}' returned a response with ` +
- `status '${fetchResponse.status}'.`);
- }
- for (const plugin of plugins) {
- if (pluginEvents.FETCH_DID_SUCCEED in plugin) {
- fetchResponse = await plugin[pluginEvents.FETCH_DID_SUCCEED]
- .call(plugin, {
- event,
- request: pluginFilteredRequest,
- response: fetchResponse,
- });
- if (process.env.NODE_ENV !== 'production') {
- if (fetchResponse) {
- assert.isInstance(fetchResponse, Response, {
- moduleName: 'Plugin',
- funcName: pluginEvents.FETCH_DID_SUCCEED,
- isReturnValueProblem: true,
- });
- }
- }
- }
- }
- return fetchResponse;
- } catch (error) {
- if (process.env.NODE_ENV !== 'production') {
- logger.error(`Network request for `+
- `'${getFriendlyURL(request.url)}' threw an error.`, error);
- }
- for (const plugin of failedFetchPlugins) {
- await plugin[pluginEvents.FETCH_DID_FAIL].call(plugin, {
- error,
- event,
- originalRequest: originalRequest.clone(),
- request: pluginFilteredRequest.clone(),
- });
- }
- throw error;
- }
- };
- const fetchWrapper = {
- fetch: wrappedFetch,
- };
- export {fetchWrapper};
|