Skip to content

Commit c90b6f9

Browse files
committed
ref(core): simplify dsn parsing
1 parent 5311fcb commit c90b6f9

File tree

2 files changed

+26
-35
lines changed

2 files changed

+26
-35
lines changed

packages/utils/src/dsn.ts

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { Dsn, DsnComponents, DsnLike, DsnProtocol } from '@sentry/types';
33
import { isDebugBuild } from './env';
44
import { SentryError } from './error';
55

6-
/** Regular expression used to parse a Dsn. */
7-
const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+))?@)([\w.-]+)(?::(\d+))?\/(.+)/;
8-
96
function isValidProtocol(protocol?: string): protocol is DsnProtocol {
107
return protocol === 'http' || protocol === 'https';
118
}
129

10+
function normalizeProtocol(input: string): string {
11+
return input.replace(/:$/, '');
12+
}
13+
1314
/**
1415
* Renders the string representation of this Dsn.
1516
*
@@ -20,38 +21,28 @@ function isValidProtocol(protocol?: string): protocol is DsnProtocol {
2021
* @param withPassword When set to true, the password will be included.
2122
*/
2223
function dsntoString(dsn: Dsn, withPassword: boolean = false): string {
23-
const { host, path, pass, port, projectId, protocol, publicKey } = dsn;
24+
const { host, port, path, pass, projectId, protocol, publicKey } = dsn;
2425
return (
2526
`${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
26-
`@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`
27+
`@${host}${port ? `:${port}` : ''}${path}/${projectId}`
2728
);
2829
}
2930

3031
function dsnFromString(str: string): Dsn {
31-
const match = DSN_REGEX.exec(str);
32-
33-
if (!match) {
34-
throw new SentryError('Invalid Dsn');
35-
}
36-
37-
const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
38-
let path = '';
39-
let projectId = lastPath;
40-
41-
const split = projectId.split('/');
42-
if (split.length > 1) {
43-
path = split.slice(0, -1).join('/');
44-
projectId = split.pop() as string;
45-
}
46-
47-
if (projectId) {
48-
const projectMatch = projectId.match(/^\d+/);
49-
if (projectMatch) {
50-
projectId = projectMatch[0];
51-
}
52-
}
53-
54-
return dsnFromComponents({ host, pass, path, projectId, port, protocol: protocol as DsnProtocol, publicKey });
32+
const url = new URL(str);
33+
34+
const pathComponents = url.pathname.split('/');
35+
const projectId = pathComponents.pop();
36+
37+
return dsnFromComponents({
38+
host: url.hostname,
39+
pass: url.password,
40+
path: pathComponents.join('/'),
41+
projectId: projectId || '',
42+
port: url.port,
43+
protocol: normalizeProtocol(url.protocol) as DsnProtocol,
44+
publicKey: url.username,
45+
});
5546
}
5647

5748
function dsnFromComponents(components: DsnComponents): Dsn {

packages/utils/test/dsn.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ describe('Dsn', () => {
4848
makeDsn({
4949
host: '',
5050
projectId: '123',
51-
protocol: 'https',
51+
protocol: 'https:',
5252
publicKey: 'abc',
5353
}),
5454
).toThrow(SentryError);
5555
expect(() =>
5656
makeDsn({
5757
host: 'sentry.io',
5858
projectId: '',
59-
protocol: 'https',
59+
protocol: 'https:',
6060
publicKey: 'abc',
6161
}),
6262
).toThrow(SentryError);
@@ -72,7 +72,7 @@ describe('Dsn', () => {
7272
makeDsn({
7373
host: 'sentry.io',
7474
projectId: '123',
75-
protocol: 'https',
75+
protocol: 'https:',
7676
publicKey: '',
7777
}),
7878
).toThrow(SentryError);
@@ -92,7 +92,7 @@ describe('Dsn', () => {
9292
host: 'sentry.io',
9393
port: 'xxx',
9494
projectId: '123',
95-
protocol: 'https',
95+
protocol: 'https:',
9696
publicKey: 'abc',
9797
}),
9898
).toThrow(SentryError);
@@ -118,7 +118,7 @@ describe('Dsn', () => {
118118
expect(dsn.pass).toBe('');
119119
expect(dsn.host).toBe('sentry.io');
120120
expect(dsn.port).toBe('');
121-
expect(dsn.path).toBe('123');
121+
expect(dsn.path).toBe('/123');
122122
expect(dsn.projectId).toBe('321');
123123
});
124124

@@ -129,7 +129,7 @@ describe('Dsn', () => {
129129
expect(dsn.pass).toBe('');
130130
expect(dsn.host).toBe('sentry.io');
131131
expect(dsn.port).toBe('');
132-
expect(dsn.path).toBe('sentry/custom/installation');
132+
expect(dsn.path).toBe('/sentry/custom/installation');
133133
expect(dsn.projectId).toBe('321');
134134
});
135135

0 commit comments

Comments
 (0)