Skip to content

Commit 78468e3

Browse files
committed
remove remaining throws
1 parent f5c2107 commit 78468e3

File tree

6 files changed

+67
-28
lines changed

6 files changed

+67
-28
lines changed

packages/core/src/transports/multiplexed.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ export function makeMultiplexedTransport<TO extends BaseTransportOptions>(
5151
const fallbackTransport = createTransport(options);
5252
const otherTransports: Record<string, Transport> = {};
5353

54-
function getTransport(dsn: string): Transport {
54+
function getTransport(dsn: string): Transport | undefined {
5555
if (!otherTransports[dsn]) {
56-
const url = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(dsn));
56+
const validatedDsn = dsnFromString(dsn);
57+
if (!validatedDsn) {
58+
return undefined;
59+
}
60+
const url = getEnvelopeEndpointWithUrlEncodedAuth(validatedDsn);
5761
otherTransports[dsn] = createTransport({ ...options, url });
5862
}
5963

@@ -66,7 +70,9 @@ export function makeMultiplexedTransport<TO extends BaseTransportOptions>(
6670
return eventFromEnvelope(envelope, eventTypes);
6771
}
6872

69-
const transports = matcher({ envelope, getEvent }).map(dsn => getTransport(dsn));
73+
const transports = matcher({ envelope, getEvent })
74+
.map(dsn => getTransport(dsn))
75+
.filter((t): t is Transport => !!t);
7076

7177
// If we have no transports to send to, use the fallback transport
7278
if (transports.length === 0) {

packages/core/test/lib/transports/multiplexed.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ import { TextEncoder } from 'util';
1212
import { createTransport, getEnvelopeEndpointWithUrlEncodedAuth, makeMultiplexedTransport } from '../../../src';
1313

1414
const DSN1 = 'https://[email protected]/4321';
15-
const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1));
15+
const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1)!);
1616

1717
const DSN2 = 'https://[email protected]/8765';
18-
const DSN2_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN2));
18+
const DSN2_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN2)!);
1919

2020
const ERROR_EVENT = { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' };
2121
const ERROR_ENVELOPE = createEnvelope<EventEnvelope>({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [
@@ -83,6 +83,20 @@ describe('makeMultiplexedTransport', () => {
8383
await transport.send(ERROR_ENVELOPE);
8484
});
8585

86+
it('Falls back to options DSN when a matched DSN is invalid', async () => {
87+
expect.assertions(1);
88+
89+
const makeTransport = makeMultiplexedTransport(
90+
createTestTransport(url => {
91+
expect(url).toBe(DSN1_URL);
92+
}),
93+
() => ['invalidDsn'],
94+
);
95+
96+
const transport = makeTransport({ url: DSN1_URL, ...transportOptions });
97+
await transport.send(ERROR_ENVELOPE);
98+
});
99+
86100
it('DSN can be overridden via match callback', async () => {
87101
expect.assertions(1);
88102

packages/core/test/lib/transports/offline.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const REPLAY_EVENT: ReplayEvent = {
3838
replay_type: 'buffer',
3939
};
4040

41-
const DSN = dsnFromString('https://[email protected]/1337');
41+
const DSN = dsnFromString('https://[email protected]/1337')!;
4242

4343
const DATA = 'nothing';
4444

packages/nextjs/src/client/tunnelRoute.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export function applyTunnelRouteOption(options: BrowserOptions): void {
1212
const tunnelRouteOption = globalWithInjectedValues.__sentryRewritesTunnelPath__;
1313
if (tunnelRouteOption && options.dsn) {
1414
const dsnComponents = dsnFromString(options.dsn);
15+
if (!dsnComponents) {
16+
return;
17+
}
1518
const sentrySaasDsnMatch = dsnComponents.host.match(/^o(\d+)\.ingest\.sentry\.io$/);
1619
if (sentrySaasDsnMatch) {
1720
const orgId = sentrySaasDsnMatch[1];

packages/nextjs/test/utils/tunnelRoute.test.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ beforeEach(() => {
1111
});
1212

1313
describe('applyTunnelRouteOption()', () => {
14-
it('should correctly apply `tunnelRoute` option when conditions are met', () => {
14+
it('Correctly applies `tunnelRoute` option when conditions are met', () => {
1515
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
1616
const options: any = {
1717
dsn: 'https://[email protected]/3333333',
@@ -22,7 +22,7 @@ describe('applyTunnelRouteOption()', () => {
2222
expect(options.tunnel).toBe('/my-error-monitoring-route?o=2222222&p=3333333');
2323
});
2424

25-
it('should not apply `tunnelRoute` when DSN is missing', () => {
25+
it("Doesn't apply `tunnelRoute` when DSN is missing", () => {
2626
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
2727
const options: any = {
2828
// no dsn
@@ -33,7 +33,18 @@ describe('applyTunnelRouteOption()', () => {
3333
expect(options.tunnel).toBeUndefined();
3434
});
3535

36-
it("should not apply `tunnelRoute` option when `tunnelRoute` option wasn't injected", () => {
36+
it("Doesn't apply `tunnelRoute` when DSN is invalid", () => {
37+
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
38+
const options: any = {
39+
dsn: 'invalidDsn',
40+
} as BrowserOptions;
41+
42+
applyTunnelRouteOption(options);
43+
44+
expect(options.tunnel).toBeUndefined();
45+
});
46+
47+
it("Doesn't apply `tunnelRoute` option when `tunnelRoute` option wasn't injected", () => {
3748
const options: any = {
3849
dsn: 'https://[email protected]/3333333',
3950
} as BrowserOptions;
@@ -43,7 +54,7 @@ describe('applyTunnelRouteOption()', () => {
4354
expect(options.tunnel).toBeUndefined();
4455
});
4556

46-
it('should not apply `tunnelRoute` option when DSN is not a SaaS DSN', () => {
57+
it("Doesn't `tunnelRoute` option when DSN is not a SaaS DSN", () => {
4758
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
4859
const options: any = {
4960
dsn: 'https://[email protected]/3333333',

packages/utils/src/dsn.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ export function dsnToString(dsn: DsnComponents, withPassword: boolean = false):
3131
* Parses a Dsn from a given string.
3232
*
3333
* @param str A Dsn as string
34-
* @returns Dsn as DsnComponents
34+
* @returns Dsn as DsnComponents or undefined if @param str is not a valid DSN string
3535
*/
36-
export function dsnFromString(str: string): DsnComponents {
36+
export function dsnFromString(str: string): DsnComponents | undefined {
3737
const match = DSN_REGEX.exec(str);
3838

3939
if (!match) {
40-
throw new SentryError(`Invalid Sentry Dsn: ${str}`);
40+
logger.error(`Invalid Sentry Dsn: ${str}`);
41+
return undefined;
4142
}
4243

4344
const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
@@ -72,30 +73,39 @@ function dsnFromComponents(components: DsnComponents): DsnComponents {
7273
};
7374
}
7475

75-
function validateDsn(dsn: DsnComponents): boolean | void {
76+
function validateDsn(dsn: DsnComponents): boolean {
7677
if (!__DEBUG_BUILD__) {
77-
return;
78+
return true;
7879
}
7980

8081
const { port, projectId, protocol } = dsn;
8182

8283
const requiredComponents: ReadonlyArray<keyof DsnComponents> = ['protocol', 'publicKey', 'host', 'projectId'];
83-
requiredComponents.forEach(component => {
84+
const hasMissingRequiredComponent = requiredComponents.find(component => {
8485
if (!dsn[component]) {
85-
throw new SentryError(`Invalid Sentry Dsn: ${component} missing`);
86+
logger.error(`Invalid Sentry Dsn: ${component} missing`);
87+
return true;
8688
}
89+
return false;
8790
});
8891

92+
if (hasMissingRequiredComponent) {
93+
return false;
94+
}
95+
8996
if (!projectId.match(/^\d+$/)) {
90-
throw new SentryError(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
97+
logger.error(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
98+
return false;
9199
}
92100

93101
if (!isValidProtocol(protocol)) {
94-
throw new SentryError(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
102+
logger.error(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
103+
return false;
95104
}
96105

97106
if (port && isNaN(parseInt(port, 10))) {
98-
throw new SentryError(`Invalid Sentry Dsn: Invalid port ${port}`);
107+
logger.error(`Invalid Sentry Dsn: Invalid port ${port}`);
108+
return false;
99109
}
100110

101111
return true;
@@ -106,14 +116,9 @@ function validateDsn(dsn: DsnComponents): boolean | void {
106116
* @returns a valid DsnComponents object or `undefined` if @param from is an invalid DSN source
107117
*/
108118
export function makeDsn(from: DsnLike): DsnComponents | undefined {
109-
try {
110-
const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
111-
validateDsn(components);
112-
return components;
113-
} catch (e) {
114-
if (e instanceof SentryError) {
115-
logger.error(e.message);
116-
}
119+
const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
120+
if (!components || !validateDsn(components)) {
117121
return undefined;
118122
}
123+
return components;
119124
}

0 commit comments

Comments
 (0)