Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
try {
const response = await this.matchPrecache(request);
if (response) {
return response;
}
// This shouldn't normally happen, but there are edge cases:
// https://github.com/GoogleChrome/workbox/issues/1441
throw new WorkboxError('missing-precache-entry', {
cacheName: this._cacheName,
url: request.url,
});
} catch (error) {
if (fallbackToNetwork) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Unable to respond with precached response. ` +
`Falling back to network.`, error);
}
return fetch(request);
}
throw error;
}
};
}
self.addEventListener('message', ((event: ExtendableMessageEvent) => {
if (event.data && event.data.type === 'CACHE_URLS') {
const {payload}: CacheURLsMessageData = event.data;
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Caching URLs from the window`, payload.urlsToCache);
}
const requestPromises = Promise.all(payload.urlsToCache.map(
(entry: string | [string, RequestInit?]) => {
if (typeof entry === 'string') {
entry = [entry];
}
const request = new Request(...entry);
return this.handleRequest({request});
// TODO(philipwalton): TypeScript errors without this typecast for
// some reason (probably a bug). The real type here should work but
// doesn't: `Array | undefined>`.
}) as any[]); // TypeScript
if (!(firstResponse instanceof Response &&
secondResponse instanceof Response)) {
throw new WorkboxError('invalid-responses-are-same-args');
}
}
const atLeastOneHeaderAvailable = headersToCheck.some((header) => {
return firstResponse.headers.has(header) &&
secondResponse.headers.has(header);
});
if (!atLeastOneHeaderAvailable) {
if (process.env.NODE_ENV !== 'production') {
logger.warn(`Unable to determine where the response has been updated ` +
`because none of the headers that would be checked are present.`);
logger.debug(`Attempting to compare the following: `,
firstResponse, secondResponse, headersToCheck);
}
// Just return true, indicating the that responses are the same, since we
// can't determine otherwise.
return true;
}
return headersToCheck.every((header) => {
const headerStateComparison = firstResponse.headers.has(header) ===
secondResponse.headers.has(header);
const headerValueComparison = firstResponse.headers.get(header) ===
secondResponse.headers.get(header);
return headerStateComparison && headerValueComparison;
});
self.addEventListener('fetch', ((event: FetchEvent) => {
const precachedURL = getCacheKeyForURL(event.request.url, {
cleanURLs,
directoryIndex,
ignoreURLParametersMatching,
urlManipulation,
});
if (!precachedURL) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Precaching did not find a match for ` +
getFriendlyURL(event.request.url));
}
return;
}
let responsePromise = self.caches.open(cacheName).then((cache) => {
return cache.match(precachedURL);
}).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
// Fall back to the network if we don't have a cached response
// (perhaps due to manual cache cleanup).
if (process.env.NODE_ENV !== 'production') {
logger.warn(`The precached response for ` +
const match: MatchCallback = ({url}: MatchCallbackOptions) => {
const result = regExp.exec(url.href);
// Return immediately if there's no match.
if (!result) {
return;
}
// Require that the match start at the first character in the URL string
// if it's a cross-origin request.
// See https://github.com/GoogleChrome/workbox/issues/281 for the context
// behind this behavior.
if ((url.origin !== location.origin) && (result.index !== 0)) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(
`The regular expression '${regExp}' only partially matched ` +
`against the cross-origin URL '${url}'. RegExpRoute's will only ` +
`handle cross-origin requests if they match the entire URL.`
);
}
return;
}
// If the route matches, but there aren't any capture groups defined, then
// this will return [], which is truthy and therefore sufficient to
// indicate a match.
// If there are capture groups, then it will return their values.
return result.slice(1);
};
if (response) {
return response;
}
// This shouldn't normally happen, but there are edge cases:
// https://github.com/GoogleChrome/workbox/issues/1441
throw new Error(`The cache ${cacheName} did not have an entry for ` +
`${cachedAssetUrl}.`);
} catch (error) {
// If there's either a cache miss, or the caches.match() call threw
// an exception, then attempt to fulfill the navigation request with
// a response from the network rather than leaving the user with a
// failed navigation.
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Unable to respond to navigation request with ` +
`cached response. Falling back to network.`, error);
}
// This might still fail if the browser is offline...
return fetch(cachedAssetUrl);
}
};
const pathnameAndSearch = url.pathname + url.search;
for (const regExp of this._blacklist) {
if (regExp.test(pathnameAndSearch)) {
if (process.env.NODE_ENV !== 'production') {
logger.log(`The navigation route ${pathnameAndSearch} is not ` +
`being used, since the URL matches this blacklist pattern: ` +
`${regExp}`);
}
return false;
}
}
if (this._whitelist.some((regExp) => regExp.test(pathnameAndSearch))) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`The navigation route ${pathnameAndSearch} ` +
`is being used.`);
}
return true;
}
if (process.env.NODE_ENV !== 'production') {
logger.log(`The navigation route ${pathnameAndSearch} is not ` +
`being used, since the URL being navigated to doesn't ` +
`match the whitelist.`);
}
return false;
}
}
const matchCallback: MatchCallback = ({url}) => {
if (process.env.NODE_ENV !== 'production') {
if ((url.pathname === captureUrl.pathname) &&
(url.origin !== captureUrl.origin)) {
logger.debug(
`${capture} only partially matches the cross-origin URL ` +
`${url}. This route will only handle cross-origin requests ` +
`if they match the entire URL.`);
}
}
return url.href === captureUrl.href;
};
request: Request,
event?: ExtendableEvent,
}): Promise | undefined {
if (process.env.NODE_ENV !== 'production') {
assert!.isInstance(request, Request, {
moduleName: 'workbox-routing',
className: 'Router',
funcName: 'handleRequest',
paramName: 'options.request',
});
}
const url = new URL(request.url, location.href);
if (!url.protocol.startsWith('http')) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(
`Workbox Router only supports URLs that start with 'http'.`);
}
return;
}
let {params, route} = this.findMatchingRoute({url, request, event});
let handler = route && route.handler;
let debugMessages = [];
if (process.env.NODE_ENV !== 'production') {
if (handler) {
debugMessages.push([
`Found a route to handle this request:`, route,
]);
if (params) {
await cache.delete(url);
}
if (process.env.NODE_ENV !== 'production') {
if (urlsExpired.length > 0) {
logger.groupCollapsed(
`Expired ${urlsExpired.length} ` +
`${urlsExpired.length === 1 ? 'entry' : 'entries'} and removed ` +
`${urlsExpired.length === 1 ? 'it' : 'them'} from the ` +
`'${this._cacheName}' cache.`);
logger.log(`Expired the following ${urlsExpired.length === 1 ?
'URL' : 'URLs'}:`);
urlsExpired.forEach((url) => logger.log(` ${url}`));
logger.groupEnd();
} else {
logger.debug(`Cache expiration ran and found no entries to remove.`);
}
}
this._isRunning = false;
if (this._rerunRequested) {
this._rerunRequested = false;
dontWaitFor(this.expireEntries());
}
}