From 91d686ff37a97ca824b265bb0ac24c7b777a836d Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 17 Oct 2022 14:10:56 +0200 Subject: [PATCH 1/3] add failing test --- packages/browser/test/unit/transports/fetch.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/browser/test/unit/transports/fetch.test.ts b/packages/browser/test/unit/transports/fetch.test.ts index 6bf6671ea1da..42913f201bc8 100644 --- a/packages/browser/test/unit/transports/fetch.test.ts +++ b/packages/browser/test/unit/transports/fetch.test.ts @@ -98,4 +98,13 @@ describe('NewFetchTransport', () => { ...REQUEST_OPTIONS, }); }); + + it.only('handles when `getNativeFetchImplementation` is undefined', async () => { + const mockFetch = jest.fn(() => undefined) as unknown as FetchImpl; + const transport = makeFetchTransport(DEFAULT_FETCH_TRANSPORT_OPTIONS, mockFetch); + + expect(mockFetch).toHaveBeenCalledTimes(0); + await expect(() => transport.send(ERROR_ENVELOPE)).not.toThrow(); + expect(mockFetch).toHaveBeenCalledTimes(1); + }); }); From 7f8758542a9577c4d045adcd15117f95a069ee1b Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 17 Oct 2022 14:11:21 +0200 Subject: [PATCH 2/3] fix(browser): Handle case where fetch can be undefined --- packages/browser/src/transports/fetch.ts | 19 ++++++++++++------- .../test/unit/transports/fetch.test.ts | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/browser/src/transports/fetch.ts b/packages/browser/src/transports/fetch.ts index 4c7cc3230fde..99e2052d2001 100644 --- a/packages/browser/src/transports/fetch.ts +++ b/packages/browser/src/transports/fetch.ts @@ -1,5 +1,6 @@ import { createTransport } from '@sentry/core'; import { Transport, TransportMakeRequestResponse, TransportRequest } from '@sentry/types'; +import { rejectedSyncPromise } from '@sentry/utils'; import { BrowserTransportOptions } from './types'; import { FetchImpl, getNativeFetchImplementation } from './utils'; @@ -30,13 +31,17 @@ export function makeFetchTransport( ...options.fetchOptions, }; - return nativeFetch(options.url, requestOptions).then(response => ({ - statusCode: response.status, - headers: { - 'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'), - 'retry-after': response.headers.get('Retry-After'), - }, - })); + try { + return nativeFetch(options.url, requestOptions).then(response => ({ + statusCode: response.status, + headers: { + 'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'), + 'retry-after': response.headers.get('Retry-After'), + }, + })); + } catch (e) { + return rejectedSyncPromise(e); + } } return createTransport(options, makeRequest); diff --git a/packages/browser/test/unit/transports/fetch.test.ts b/packages/browser/test/unit/transports/fetch.test.ts index 42913f201bc8..624a3d1d007a 100644 --- a/packages/browser/test/unit/transports/fetch.test.ts +++ b/packages/browser/test/unit/transports/fetch.test.ts @@ -99,7 +99,7 @@ describe('NewFetchTransport', () => { }); }); - it.only('handles when `getNativeFetchImplementation` is undefined', async () => { + it('handles when `getNativeFetchImplementation` is undefined', async () => { const mockFetch = jest.fn(() => undefined) as unknown as FetchImpl; const transport = makeFetchTransport(DEFAULT_FETCH_TRANSPORT_OPTIONS, mockFetch); From ea35dc2eed9adab3d282e59f3b40f9f9efc7a342 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 25 Oct 2022 14:35:13 +0200 Subject: [PATCH 3/3] bust the cache when we hit an error --- packages/browser/src/transports/fetch.ts | 3 ++- packages/browser/src/transports/utils.ts | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/browser/src/transports/fetch.ts b/packages/browser/src/transports/fetch.ts index 99e2052d2001..5f64bcdde841 100644 --- a/packages/browser/src/transports/fetch.ts +++ b/packages/browser/src/transports/fetch.ts @@ -3,7 +3,7 @@ import { Transport, TransportMakeRequestResponse, TransportRequest } from '@sent import { rejectedSyncPromise } from '@sentry/utils'; import { BrowserTransportOptions } from './types'; -import { FetchImpl, getNativeFetchImplementation } from './utils'; +import { clearCachedFetchImplementation, FetchImpl, getNativeFetchImplementation } from './utils'; /** * Creates a Transport that uses the Fetch API to send events to Sentry. @@ -40,6 +40,7 @@ export function makeFetchTransport( }, })); } catch (e) { + clearCachedFetchImplementation(); return rejectedSyncPromise(e); } } diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index 137cbc88487e..1243c2cc4292 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -1,6 +1,6 @@ import { isNativeFetch, logger, WINDOW } from '@sentry/utils'; -let cachedFetchImpl: FetchImpl; +let cachedFetchImpl: FetchImpl | undefined = undefined; export type FetchImpl = typeof fetch; @@ -76,3 +76,8 @@ export function getNativeFetchImplementation(): FetchImpl { return (cachedFetchImpl = fetchImpl.bind(WINDOW)); /* eslint-enable @typescript-eslint/unbound-method */ } + +/** Clears cached fetch impl */ +export function clearCachedFetchImplementation(): void { + cachedFetchImpl = undefined; +}