Skip to content

Commit

Permalink
fix(browser): Handle case where fetch can be undefined (#5973)
Browse files Browse the repository at this point in the history
Some users reported cases where the `nativeFetch` call was returning undefined. I have no idea how this happens, but in order for us to not send unnecessary errors to Sentry, let's be a little defensive in the usage of fetch.
  • Loading branch information
AbhiPrasad committed Oct 25, 2022
1 parent ac03a39 commit fe1a22c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 9 deletions.
22 changes: 14 additions & 8 deletions packages/browser/src/transports/fetch.ts
@@ -1,8 +1,9 @@
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';
import { clearCachedFetchImplementation, FetchImpl, getNativeFetchImplementation } from './utils';

/**
* Creates a Transport that uses the Fetch API to send events to Sentry.
Expand Down Expand Up @@ -30,13 +31,18 @@ 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) {
clearCachedFetchImplementation();
return rejectedSyncPromise(e);
}
}

return createTransport(options, makeRequest);
Expand Down
7 changes: 6 additions & 1 deletion packages/browser/src/transports/utils.ts
Expand Up @@ -2,7 +2,7 @@ import { isNativeFetch, logger } from '@sentry/utils';

import { WINDOW } from '../helpers';

let cachedFetchImpl: FetchImpl;
let cachedFetchImpl: FetchImpl | undefined = undefined;

export type FetchImpl = typeof fetch;

Expand Down Expand Up @@ -78,3 +78,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;
}
9 changes: 9 additions & 0 deletions packages/browser/test/unit/transports/fetch.test.ts
Expand Up @@ -98,4 +98,13 @@ describe('NewFetchTransport', () => {
...REQUEST_OPTIONS,
});
});

it('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);
});
});

0 comments on commit fe1a22c

Please sign in to comment.