Skip to content

Commit a8b0287

Browse files
committed
ref: Abstract transports to use BaseTransport class
1 parent 5835e82 commit a8b0287

File tree

7 files changed

+85
-52
lines changed

7 files changed

+85
-52
lines changed

packages/browser/src/backend.ts

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Backend, DSN, Options, SentryError } from '@sentry/core';
22
import { addBreadcrumb, captureEvent } from '@sentry/minimal';
33
import { SentryEvent } from '@sentry/types';
4-
import { supportsFetch, urlEncode } from '@sentry/utils';
4+
import { supportsFetch } from '@sentry/utils';
55
import { Raven } from './raven';
66
import { FetchTransport, XHRTransport } from './transports';
77

@@ -116,51 +116,19 @@ export class BrowserBackend implements Backend {
116116
* @inheritDoc
117117
*/
118118
public async sendEvent(event: SentryEvent): Promise<number> {
119-
let dsn;
119+
let dsn: DSN;
120120

121121
if (!this.options.dsn) {
122122
throw new SentryError('Cannot sendEvent without a valid DSN');
123123
} else {
124124
dsn = new DSN(this.options.dsn);
125125
}
126126

127-
const auth = {
128-
sentry_client: `raven-js/${Raven.VERSION}`,
129-
sentry_key: dsn.user,
130-
sentry_secret: '',
131-
sentry_version: '7',
132-
};
133-
134-
if (dsn.pass) {
135-
auth.sentry_secret = dsn.pass;
136-
} else {
137-
delete auth.sentry_secret;
138-
}
139-
140-
const lastSlash = dsn.path.lastIndexOf('/');
141-
const path = dsn.path.substr(1, lastSlash);
142-
143-
const _globalProject = dsn.path.substr(lastSlash + 1);
144-
let globalServer = `//${dsn.host}${dsn.port ? `:${dsn.port}` : ''}`;
145-
146-
if (dsn.protocol) {
147-
globalServer = `${dsn.protocol}':'${globalServer}`;
148-
}
149-
150-
const _globalEndpoint = `${globalServer}/${path}api/${_globalProject}/store/`;
151-
152-
// Auth is intentionally sent as part of query string (NOT as custom HTTP header)
153-
// to avoid preflight CORS requests
154-
const url = `${_globalEndpoint}?${urlEncode(auth)}`;
155-
156127
const transport = this.options.transport
157-
? this.options.transport
128+
? new this.options.transport({ dsn })
158129
: supportsFetch()
159-
? new FetchTransport({ url })
160-
: new XHRTransport({ url });
161-
162-
// tslint:disable-next-line
163-
debugger;
130+
? new FetchTransport({ dsn })
131+
: new XHRTransport({ dsn });
164132

165133
return transport
166134
.send(event)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { SentryError } from '@sentry/core';
2+
import {
3+
DSNComponents,
4+
SentryEvent,
5+
Transport,
6+
TransportOptions,
7+
} from '@sentry/types';
8+
import { urlEncode } from '@sentry/utils';
9+
10+
/** Base Transport class implementation */
11+
export abstract class BaseTransport implements Transport {
12+
/**
13+
* @inheritDoc
14+
*/
15+
public endpointUrl: string;
16+
17+
public constructor(public options: TransportOptions) {
18+
this.endpointUrl = this.composeEndpointUrl(options.dsn);
19+
}
20+
21+
/**
22+
* @inheritDoc
23+
*/
24+
public composeEndpointUrl(dsn: DSNComponents): string {
25+
const auth = {
26+
sentry_key: dsn.user,
27+
sentry_secret: '',
28+
sentry_version: '7',
29+
};
30+
31+
if (dsn.pass) {
32+
auth.sentry_secret = dsn.pass;
33+
} else {
34+
delete auth.sentry_secret;
35+
}
36+
37+
const protocol = dsn.protocol ? `${dsn.protocol}:` : '';
38+
const port = dsn.port ? `:${dsn.port}` : '';
39+
const endpoint = `${protocol}//${dsn.host}${port}/api/${dsn.path}/store/`;
40+
41+
// Auth is intentionally sent as part of query string (NOT as custom HTTP header)
42+
// to avoid preflight CORS requests
43+
return `${endpoint}?${urlEncode(auth)}`;
44+
}
45+
46+
/**
47+
* @inheritDoc
48+
*/
49+
public async send(_: SentryEvent): Promise<Response | XMLHttpRequest> {
50+
throw new SentryError('Transport Class has to implement `send` method');
51+
}
52+
}

packages/browser/src/transports/fetch.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { SentryEvent, Transport } from '@sentry/types';
1+
import { SentryEvent } from '@sentry/types';
22
import { serialize, supportsReferrerPolicy } from '@sentry/utils';
3+
import { BaseTransport } from './base';
34

45
/** `fetch` based transport */
5-
export class FetchTransport implements Transport {
6-
public constructor(public config: { url: string }) {}
7-
6+
export class FetchTransport extends BaseTransport {
87
/**
98
* @inheritDoc
109
*/
@@ -23,6 +22,6 @@ export class FetchTransport implements Transport {
2322
};
2423

2524
// TODO: Safe _window access
26-
return window.fetch(this.config.url, defaultOptions);
25+
return window.fetch(this.endpointUrl, defaultOptions);
2726
}
2827
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export { BaseTransport } from './base';
12
export { FetchTransport } from './fetch';
23
export { XHRTransport } from './xhr';

packages/browser/src/transports/xhr.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { SentryEvent, Transport } from '@sentry/types';
1+
import { SentryEvent } from '@sentry/types';
22
import { serialize } from '@sentry/utils';
3+
import { BaseTransport } from './base';
34

45
/** `XHR` based transport */
5-
export class XHRTransport implements Transport {
6-
public constructor(public config: { url: string }) {}
7-
6+
export class XHRTransport extends BaseTransport {
87
/**
98
* @inheritDoc
109
*/
@@ -24,7 +23,7 @@ export class XHRTransport implements Transport {
2423
reject(request);
2524
};
2625

27-
request.open('POST', this.config.url);
26+
request.open('POST', this.endpointUrl);
2827
request.send(serialize(event));
2928
});
3029
}

packages/core/src/interfaces.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { Scope } from '@sentry/hub';
2-
import { Breadcrumb, Integration, SentryEvent, Transport } from '@sentry/types';
2+
import {
3+
Breadcrumb,
4+
Integration,
5+
SentryEvent,
6+
Transport,
7+
TransportClass,
8+
} from '@sentry/types';
39
import { DSN } from './dsn';
410
import { SendStatus } from './status';
511

@@ -42,7 +48,7 @@ export interface Options {
4248
/**
4349
* Transport object that should be used to send events to Sentry
4450
*/
45-
transport?: Transport;
51+
transport?: TransportClass<Transport>;
4652

4753
/**
4854
* The release identifier used when uploading respective source maps. Specify

packages/types/src/index.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,18 @@ export interface Integration {
150150
install(): void;
151151
}
152152

153+
export interface TransportOptions {
154+
dsn: DSNComponents;
155+
}
156+
153157
/** TODO */
154158
export interface Transport {
155-
config: {
156-
url: string;
157-
};
159+
endpointUrl: string;
160+
composeEndpointUrl(dsn: DSNComponents): string;
158161
send(event: SentryEvent): Promise<Response | XMLHttpRequest>;
159162
}
163+
164+
/** TODO */
165+
export interface TransportClass<T extends Transport> {
166+
new (options: TransportOptions): T;
167+
}

0 commit comments

Comments
 (0)