Skip to content

Commit 1120c08

Browse files
HazATkamilogorek
authored andcommitted
fix: Fixes the dsn behaviour (#1411)
* fix: Fixes the dsn behaviour * fix: Browser endpoint
1 parent edd08f9 commit 1120c08

File tree

4 files changed

+67
-22
lines changed

4 files changed

+67
-22
lines changed

packages/browser/src/transports/base.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ export abstract class BaseTransport implements Transport {
3636

3737
const protocol = dsn.protocol ? `${dsn.protocol}:` : '';
3838
const port = dsn.port ? `:${dsn.port}` : '';
39-
const endpoint = `${protocol}//${dsn.host}${port}/api/${dsn.path}/store/`;
39+
const path = dsn.path ? `/${dsn.path}` : '';
40+
const endpoint = `${protocol}//${dsn.host}${port}${path}/api/${
41+
dsn.projectId
42+
}/store/`;
4043

4144
// Auth is intentionally sent as part of query string (NOT as custom HTTP header)
4245
// to avoid preflight CORS requests

packages/core/src/dsn.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ export class DSN implements DSNComponents {
1616
public host!: string;
1717
/** Port of the Sentry instance. */
1818
public port!: string;
19-
/** Project path */
19+
/** Path */
2020
public path!: string;
21+
/** Project ID */
22+
public projectId!: string;
2123

2224
/** Creates a new DSN component */
2325
public constructor(from: DSNLike) {
@@ -41,10 +43,12 @@ export class DSN implements DSNComponents {
4143
*/
4244
public toString(withPassword: boolean = false): string {
4345
// tslint:disable-next-line:no-this-assignment
44-
const { host, path, pass, port, protocol, user } = this;
46+
const { host, path, pass, port, projectId, protocol, user } = this;
4547
return (
4648
`${protocol}://${user}${withPassword && pass ? `:${pass}` : ''}` +
47-
`@${host}${port ? `:${port}` : ''}/${path}`
49+
`@${host}${port ? `:${port}` : ''}/${
50+
path ? `${path}/` : path
51+
}${projectId}`
4852
);
4953
}
5054

@@ -55,8 +59,17 @@ export class DSN implements DSNComponents {
5559
throw new SentryError('Invalid DSN');
5660
}
5761

58-
const [protocol, user, pass = '', host, port = '', path] = match.slice(1);
59-
Object.assign(this, { host, pass, path, port, protocol, user });
62+
const [protocol, user, pass = '', host, port = '', lastPath] = match.slice(
63+
1,
64+
);
65+
let path = '';
66+
let projectId = lastPath;
67+
const split = projectId.split('/');
68+
if (split.length > 1) {
69+
path = split.slice(0, -1).join('/');
70+
projectId = split.pop() as string;
71+
}
72+
Object.assign(this, { host, pass, path, projectId, port, protocol, user });
6073
}
6174

6275
/** Maps DSN components into this instance. */
@@ -66,12 +79,13 @@ export class DSN implements DSNComponents {
6679
this.pass = components.pass || '';
6780
this.host = components.host;
6881
this.port = components.port || '';
69-
this.path = components.path;
82+
this.path = components.path || '';
83+
this.projectId = components.projectId;
7084
}
7185

7286
/** Validates this DSN and throws on error. */
7387
private validate(): void {
74-
for (const component of ['protocol', 'user', 'host', 'path']) {
88+
for (const component of ['protocol', 'user', 'host', 'projectId']) {
7589
if (!this[component as keyof DSNComponents]) {
7690
throw new SentryError(`Invalid DSN: Missing ${component}`);
7791
}

packages/core/test/lib/dsn.test.ts

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ describe('DSN', () => {
77
const dsn = new DSN({
88
host: 'sentry.io',
99
pass: 'xyz',
10-
path: '123',
1110
port: '1234',
11+
projectId: '123',
1212
protocol: 'https',
1313
user: 'abc',
1414
});
@@ -17,13 +17,14 @@ describe('DSN', () => {
1717
expect(dsn.pass).toBe('xyz');
1818
expect(dsn.host).toBe('sentry.io');
1919
expect(dsn.port).toBe('1234');
20-
expect(dsn.path).toBe('123');
20+
expect(dsn.projectId).toBe('123');
21+
expect(dsn.path).toBe('');
2122
});
2223

2324
test('applies partial components', () => {
2425
const dsn = new DSN({
2526
host: 'sentry.io',
26-
path: '123',
27+
projectId: '123',
2728
protocol: 'https',
2829
user: 'abc',
2930
});
@@ -32,15 +33,16 @@ describe('DSN', () => {
3233
expect(dsn.pass).toBe('');
3334
expect(dsn.host).toBe('sentry.io');
3435
expect(dsn.port).toBe('');
35-
expect(dsn.path).toBe('123');
36+
expect(dsn.projectId).toBe('123');
37+
expect(dsn.path).toBe('');
3638
});
3739

3840
test('throws for missing components', () => {
3941
expect(
4042
() =>
4143
new DSN({
4244
host: '',
43-
path: '123',
45+
projectId: '123',
4446
protocol: 'https',
4547
user: 'abc',
4648
}),
@@ -49,7 +51,7 @@ describe('DSN', () => {
4951
() =>
5052
new DSN({
5153
host: 'sentry.io',
52-
path: '',
54+
projectId: '',
5355
protocol: 'https',
5456
user: 'abc',
5557
}),
@@ -58,7 +60,7 @@ describe('DSN', () => {
5860
() =>
5961
new DSN({
6062
host: 'sentry.io',
61-
path: '123',
63+
projectId: '123',
6264
protocol: '' as 'http', // Trick the type checker here
6365
user: 'abc',
6466
}),
@@ -67,7 +69,7 @@ describe('DSN', () => {
6769
() =>
6870
new DSN({
6971
host: 'sentry.io',
70-
path: '123',
72+
projectId: '123',
7173
protocol: 'https',
7274
user: '',
7375
}),
@@ -79,7 +81,7 @@ describe('DSN', () => {
7981
() =>
8082
new DSN({
8183
host: 'sentry.io',
82-
path: '123',
84+
projectId: '123',
8385
protocol: 'httpx' as 'http', // Trick the type checker here
8486
user: 'abc',
8587
}),
@@ -88,8 +90,8 @@ describe('DSN', () => {
8890
() =>
8991
new DSN({
9092
host: 'sentry.io',
91-
path: '123',
9293
port: 'xxx',
94+
projectId: '123',
9395
protocol: 'https',
9496
user: 'abc',
9597
}),
@@ -105,17 +107,32 @@ describe('DSN', () => {
105107
expect(dsn.pass).toBe('xyz');
106108
expect(dsn.host).toBe('sentry.io');
107109
expect(dsn.port).toBe('1234');
108-
expect(dsn.path).toBe('123');
110+
expect(dsn.projectId).toBe('123');
111+
expect(dsn.path).toBe('');
109112
});
110113

111114
test('parses a valid partial DSN', () => {
112-
const dsn = new DSN('https://[email protected]/123');
115+
const dsn = new DSN('https://[email protected]/123/321');
113116
expect(dsn.protocol).toBe('https');
114117
expect(dsn.user).toBe('abc');
115118
expect(dsn.pass).toBe('');
116119
expect(dsn.host).toBe('sentry.io');
117120
expect(dsn.port).toBe('');
118121
expect(dsn.path).toBe('123');
122+
expect(dsn.projectId).toBe('321');
123+
});
124+
125+
test('with a long path', () => {
126+
const dsn = new DSN(
127+
'https://[email protected]/sentry/custom/installation/321',
128+
);
129+
expect(dsn.protocol).toBe('https');
130+
expect(dsn.user).toBe('abc');
131+
expect(dsn.pass).toBe('');
132+
expect(dsn.host).toBe('sentry.io');
133+
expect(dsn.port).toBe('');
134+
expect(dsn.path).toBe('sentry/custom/installation');
135+
expect(dsn.projectId).toBe('321');
119136
});
120137

121138
test('throws when provided invalid DSN', () => {
@@ -157,5 +174,14 @@ describe('DSN', () => {
157174
const dsn = new DSN('https://[email protected]/123');
158175
expect(dsn.toString()).toBe('https://[email protected]/123');
159176
});
177+
178+
test('renders the full path correctly', () => {
179+
const dsn = new DSN(
180+
'https://[email protected]/sentry/custom/installation/321',
181+
);
182+
expect(dsn.toString()).toBe(
183+
'https://[email protected]/sentry/custom/installation/321',
184+
);
185+
});
160186
});
161187
});

packages/types/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ export interface DSNComponents {
1313
host: string;
1414
/** Port of the Sentry instance. */
1515
port?: string;
16-
/** Project path */
17-
path: string;
16+
/** Sub path/ */
17+
path?: string;
18+
/** Project ID */
19+
projectId: string;
1820
}
1921

2022
/** Anything that can be parsed into a DSN. */

0 commit comments

Comments
 (0)