diff --git a/src/main/request.ts b/src/main/request.ts index 63c2a23..41096c9 100644 --- a/src/main/request.ts +++ b/src/main/request.ts @@ -27,6 +27,7 @@ export const DEFAULT_REQUEST_CONFIG: RequestConfig = { retryDelayIncrement: 500, retryStatusCodes: [429, 502, 503, 504], authInvalidateStatusCodes: [401, 403], + handleShouldRetry: () => false, headers: {}, fetch, }; @@ -108,7 +109,7 @@ export class Request { const status = err.details?.status; const statusText = err.details?.statusText; const info: RequestDebugInfo = { method, url, headers: options.headers ?? {}, status, statusText }; - const retry = shouldRetry || NETWORK_ERRORS.includes(err.code); + const retry = shouldRetry || NETWORK_ERRORS.includes(err.code) || this.config.handleShouldRetry?.(err); if (retry) { lastError = err; lastInfo = info; diff --git a/src/main/types.ts b/src/main/types.ts index 145cf00..1cec5d2 100644 --- a/src/main/types.ts +++ b/src/main/types.ts @@ -28,6 +28,7 @@ export interface RequestConfig { authInvalidateStatusCodes: number[]; headers: RequestHeaders; fetch: Fetch; + handleShouldRetry?: (error: Error) => boolean; } export interface Fetch { diff --git a/src/test/request.test.ts b/src/test/request.test.ts index 78a95a8..875ff06 100644 --- a/src/test/request.test.ts +++ b/src/test/request.test.ts @@ -84,6 +84,37 @@ describe('Request', () => { assert.strictEqual(thrownError.details.status, 504); }); + it('retry if handleShouldRetry returns true', async () => { + let thrownError: any; + const fetch = fetchMock({ status: 500 }); + const request = new Request({ + fetch, + retryAttempts, + retryDelay: 0, + retryDelayIncrement: 10, + handleShouldRetry: err => { + err.message = 'should-retry'; + return true; + }, + }); + request.onRetry = err => { thrownError = err; }; + await request.send('get', 'http://example.com').catch(() => {}); + assert.ok(thrownError); + assert.strictEqual(thrownError.message, 'should-retry'); + assert.strictEqual(thrownError.details.status, 500); + }); + + it('do not retry by default config', async () => { + let retried = false; + const fetch = fetchMock({ status: 500 }); + const request = new Request({ + fetch + }); + request.onRetry = () => { retried = true; }; + await request.send('get', 'http://example.com').catch(() => {}); + assert.ok(!retried); + }); + }); describe('mergeHeaders', () => {