getRetryDelay() takes src as well

This commit is contained in:
JonnyBurger
2025-09-30 14:59:48 +02:00
parent 249d9444ce
commit 548ca74c93
2 changed files with 24 additions and 9 deletions
+2 -2
View File
@@ -578,7 +578,7 @@ export const retriedFetch = async (
fetchFn: typeof fetch,
url: string | URL | Request,
requestInit: RequestInit,
getRetryDelay: (previousAttempts: number, error: unknown) => number | null,
getRetryDelay: (previousAttempts: number, error: unknown, url: string | URL | Request) => number | null,
) => {
let attempts = 0;
@@ -587,7 +587,7 @@ export const retriedFetch = async (
return await fetchFn(url, requestInit);
} catch (error) {
attempts++;
const retryDelayInSeconds = getRetryDelay(attempts, error);
const retryDelayInSeconds = getRetryDelay(attempts, error, url);
if (retryDelayInSeconds === null) {
throw error;
+22 -7
View File
@@ -255,7 +255,7 @@ export class BlobSource extends Source {
const URL_SOURCE_MIN_LOAD_AMOUNT = 0.5 * 2 ** 20; // 0.5 MiB
const DEFAULT_RETRY_DELAY
= ((previousAttempts, error) => {
= ((previousAttempts, error, src) => {
// Check if this could be a CORS error. If so, we cannot recover from it and
// should not attempt to retry.
// CORS errors are intentionally not opaque, so we need to rely on heuristics.
@@ -265,9 +265,24 @@ const DEFAULT_RETRY_DELAY
|| error.message.includes('NetworkError when attempting to fetch resource') // Firefox
);
// Being offline would lead to the same error, in that case it would not be a CORS error
if (couldBeCorsError && navigator.onLine) {
return null;
if (couldBeCorsError) {
let originOfSrc: string | null = null;
// Checking if the origin is different, because only then a CORS error could originate
try {
if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
originOfSrc = new URL(src instanceof Request ? src.url : src, window.location.href).origin;
}
} catch {
// URL parse failed
}
// If user is offline, it is probably not a CORS error.
const isOnline
= typeof navigator !== 'undefined' && typeof navigator.onLine === 'boolean' ? navigator.onLine : true;
if (isOnline && originOfSrc !== null && originOfSrc !== window.location.origin) {
return null;
}
}
return Math.min(2 ** (previousAttempts - 2), 16);
@@ -293,7 +308,7 @@ export type UrlSourceOptions = {
* By default, it uses an exponential backoff algorithm that never gives up unless
* a CORS error is suspected (`fetch()` did reject even though `navigator.onLine` is true)
*/
getRetryDelay?: (previousAttempts: number, error: unknown) => number | null;
getRetryDelay?: (previousAttempts: number, error: unknown, url: string | URL | Request) => number | null;
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 64 MiB. */
maxCacheSize?: number;
@@ -315,7 +330,7 @@ export class UrlSource extends Source {
/** @internal */
_url: string | URL | Request;
/** @internal */
_getRetryDelay: (previousAttempts: number, error: unknown) => number | null;
_getRetryDelay: (previousAttempts: number, error: unknown, url: string | URL | Request) => number | null;
/** @internal */
_options: UrlSourceOptions;
/** @internal */
@@ -508,7 +523,7 @@ export class UrlSource extends Source {
try {
readResult = await reader.read();
} catch (error) {
const retryDelayInSeconds = this._getRetryDelay(1, error);
const retryDelayInSeconds = this._getRetryDelay(1, error, this._url);
if (retryDelayInSeconds !== null) {
console.error('Error while reading response stream. Attempting to resume.', error);
await new Promise(resolve => setTimeout(resolve, 1000 * retryDelayInSeconds));