From 77a8a2878bc10b445360d985d2defff5871f5293 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 09:50:00 -0500 Subject: [PATCH 1/7] feat(core): Deprecate API class --- packages/core/src/api.ts | 156 +++++++++++++++++++++++-------------- packages/core/src/index.ts | 10 ++- 2 files changed, 106 insertions(+), 60 deletions(-) diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts index c5dff08ba653..07c9dead3fb6 100644 --- a/packages/core/src/api.ts +++ b/packages/core/src/api.ts @@ -3,10 +3,26 @@ import { Dsn, urlEncode } from '@sentry/utils'; const SENTRY_API_VERSION = '7'; +/** + * Stores details about a Sentry SDK + */ +export interface APIDetails { + /** The DSN as passed to Sentry.init() */ + initDsn: DsnLike; + /** Metadata about the SDK (name, version, etc) for inclusion in envelope headers */ + metadata: SdkMetadata; + /** The internally used Dsn object. */ + readonly dsn: Dsn; + /** The envelope tunnel to use. */ + readonly tunnel?: string; +} + /** * Helper class to provide urls, headers and metadata that can be used to form * different types of requests to Sentry endpoints. * Supports both envelopes and regular event requests. + * + * @deprecated Please use APIDetails **/ export class API { /** The DSN as passed to Sentry.init() */ @@ -41,13 +57,12 @@ export class API { /** Returns the prefix to construct Sentry ingestion API endpoints. */ public getBaseApiEndpoint(): string { - const dsn = this.getDsn(); - return getBaseApiEndpoint(dsn); + return getBaseApiEndpoint(this._dsnObject); } /** Returns the store endpoint URL. */ public getStoreEndpoint(): string { - return this._getIngestEndpoint('store'); + return getStoreEndpoint(this._dsnObject); } /** @@ -56,7 +71,7 @@ export class API { * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests. */ public getStoreEndpointWithUrlEncodedAuth(): string { - return `${this.getStoreEndpoint()}?${this._encodedAuth()}`; + return getStoreEndpointWithUrlEncodedAuth(this._dsnObject); } /** @@ -65,71 +80,94 @@ export class API { * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests. */ public getEnvelopeEndpointWithUrlEncodedAuth(): string { - if (this.forceEnvelope()) { - return this._tunnel as string; - } - - return `${this._getEnvelopeEndpoint()}?${this._encodedAuth()}`; + return getEnvelopeEndpointWithUrlEncodedAuth(this._dsnObject, this._tunnel); } +} - /** Returns only the path component for the store endpoint. */ - public getStoreEndpointPath(): string { - const dsn = this.getDsn(); - return `${dsn.path ? `/${dsn.path}` : ''}/api/${dsn.projectId}/store/`; - } +/** Initializes API Details */ +export function initAPIDetails(dsn: DsnLike, metadata?: SdkMetadata, tunnel?: string): APIDetails { + return { + initDsn: dsn, + metadata: metadata || {}, + dsn: new Dsn(dsn), + tunnel, + } as APIDetails; +} - /** - * Returns an object that can be used in request headers. - * This is needed for node and the old /store endpoint in sentry - */ - public getRequestHeaders(clientName: string, clientVersion: string): { [key: string]: string } { - // CHANGE THIS to use metadata but keep clientName and clientVersion compatible - const dsn = this.getDsn(); - const header = [`Sentry sentry_version=${SENTRY_API_VERSION}`]; - header.push(`sentry_client=${clientName}/${clientVersion}`); - header.push(`sentry_key=${dsn.publicKey}`); - if (dsn.pass) { - header.push(`sentry_secret=${dsn.pass}`); - } - return { - 'Content-Type': 'application/json', - 'X-Sentry-Auth': header.join(', '), - }; - } +/** Returns the prefix to construct Sentry ingestion API endpoints. */ +function getBaseApiEndpoint(dsn: Dsn): string { + const protocol = dsn.protocol ? `${dsn.protocol}:` : ''; + const port = dsn.port ? `:${dsn.port}` : ''; + return `${protocol}//${dsn.host}${port}${dsn.path ? `/${dsn.path}` : ''}/api/`; +} - /** Returns the envelope endpoint URL. */ - private _getEnvelopeEndpoint(): string { - return this._getIngestEndpoint('envelope'); +/** Returns the ingest API endpoint for target. */ +function _getIngestEndpoint(dsn: Dsn, target: 'store' | 'envelope', tunnel?: string): string { + if (tunnel) { + return tunnel; } + return `${getBaseApiEndpoint(dsn)}${dsn.projectId}/${target}/`; +} - /** Returns the ingest API endpoint for target. */ - private _getIngestEndpoint(target: 'store' | 'envelope'): string { - if (this._tunnel) { - return this._tunnel; - } - const base = this.getBaseApiEndpoint(); - const dsn = this.getDsn(); - return `${base}${dsn.projectId}/${target}/`; - } +/** Returns a URL-encoded string with auth config suitable for a query string. */ +function _encodedAuth(dsn: Dsn): string { + const auth = { + // We send only the minimum set of required information. See + // https://github.com/getsentry/sentry-javascript/issues/2572. + sentry_key: dsn.publicKey, + sentry_version: SENTRY_API_VERSION, + }; + return urlEncode(auth); +} - /** Returns a URL-encoded string with auth config suitable for a query string. */ - private _encodedAuth(): string { - const dsn = this.getDsn(); - const auth = { - // We send only the minimum set of required information. See - // https://github.com/getsentry/sentry-javascript/issues/2572. - sentry_key: dsn.publicKey, - sentry_version: SENTRY_API_VERSION, - }; - return urlEncode(auth); +/** Returns the store endpoint URL. */ +function getStoreEndpoint(dsn: Dsn): string { + return _getIngestEndpoint(dsn, 'store'); +} + +/** + * Returns the store endpoint URL with auth in the query string. + * + * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests. + */ +export function getStoreEndpointWithUrlEncodedAuth(dsn: Dsn): string { + return `${getStoreEndpoint(dsn)}?${_encodedAuth(dsn)}`; +} + +/** Returns the envelope endpoint URL. */ +function _getEnvelopeEndpoint(dsn: Dsn, tunnel?: string): string { + return _getIngestEndpoint(dsn, 'envelope', tunnel); +} + +/** + * Returns the envelope endpoint URL with auth in the query string. + * + * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests. + */ +export function getEnvelopeEndpointWithUrlEncodedAuth(dsn: Dsn, tunnel?: string): string { + if (tunnel) { + return tunnel; } + + return `${_getEnvelopeEndpoint(dsn, tunnel)}?${_encodedAuth(dsn)}`; } -/** Returns the prefix to construct Sentry ingestion API endpoints. */ -function getBaseApiEndpoint(dsn: Dsn): string { - const protocol = dsn.protocol ? `${dsn.protocol}:` : ''; - const port = dsn.port ? `:${dsn.port}` : ''; - return `${protocol}//${dsn.host}${port}${dsn.path ? `/${dsn.path}` : ''}/api/`; +/** + * Returns an object that can be used in request headers. + * This is needed for node and the old /store endpoint in sentry + */ +function getRequestHeaders(dsn: Dsn, clientName: string, clientVersion: string): { [key: string]: string } { + // CHANGE THIS to use metadata but keep clientName and clientVersion compatible + const header = [`Sentry sentry_version=${SENTRY_API_VERSION}`]; + header.push(`sentry_client=${clientName}/${clientVersion}`); + header.push(`sentry_key=${dsn.publicKey}`); + if (dsn.pass) { + header.push(`sentry_secret=${dsn.pass}`); + } + return { + 'Content-Type': 'application/json', + 'X-Sentry-Auth': header.join(', '), + }; } /** Returns the url to the report dialog endpoint. */ diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7e7423b11ff8..c54d16d7e3ac 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -14,7 +14,15 @@ export { withScope, } from '@sentry/minimal'; export { addGlobalEventProcessor, getCurrentHub, getHubFromCarrier, Hub, makeMain, Scope } from '@sentry/hub'; -export { API, getReportDialogEndpoint } from './api'; +export { + // eslint-disable-next-line deprecation/deprecation + API, + APIDetails, + getStoreEndpointWithUrlEncodedAuth, + getEnvelopeEndpointWithUrlEncodedAuth, + initAPIDetails, + getReportDialogEndpoint, +} from './api'; export { BaseClient } from './baseclient'; export { BackendClass, BaseBackend } from './basebackend'; export { eventToSentryRequest, sessionToSentryRequest } from './request'; From 0672c710092eaa0a35f2fc500598a5e97d2f2960 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 10:01:40 -0500 Subject: [PATCH 2/7] Convert transports to use functions instead of API class --- packages/browser/src/transports/base.ts | 17 +++++++++++------ packages/core/src/api.ts | 2 +- packages/core/src/index.ts | 3 ++- packages/core/src/request.ts | 18 +++++++++--------- packages/node/src/transports/base/index.ts | 11 ++++++----- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 072b8f88b463..bdb7694505f6 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -1,4 +1,9 @@ -import { API } from '@sentry/core'; +import { + APIDetails, + getEnvelopeEndpointWithUrlEncodedAuth, + getStoreEndpointWithUrlEncodedAuth, + initAPIDetails, +} from '@sentry/core'; import { Event, Outcome, @@ -38,7 +43,7 @@ export abstract class BaseTransport implements Transport { public url: string; /** Helper to get Sentry API endpoints. */ - protected readonly _api: API; + protected readonly _api: APIDetails; /** A simple buffer holding all requests. */ protected readonly _buffer: PromiseBuffer = new PromiseBuffer(30); @@ -49,9 +54,9 @@ export abstract class BaseTransport implements Transport { protected _outcomes: { [key: string]: number } = {}; public constructor(public options: TransportOptions) { - this._api = new API(options.dsn, options._metadata, options.tunnel); + this._api = initAPIDetails(options.dsn, options._metadata, options.tunnel); // eslint-disable-next-line deprecation/deprecation - this.url = this._api.getStoreEndpointWithUrlEncodedAuth(); + this.url = getStoreEndpointWithUrlEncodedAuth(this._api.dsn); if (this.options.sendClientReports && global.document) { global.document.addEventListener('visibilitychange', () => { @@ -112,9 +117,9 @@ export abstract class BaseTransport implements Transport { logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); - const url = this._api.getEnvelopeEndpointWithUrlEncodedAuth(); + const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn); // Envelope header is required to be at least an empty object - const envelopeHeader = JSON.stringify({ ...(this.options.tunnel && { dsn: this._api.getDsn().toString() }) }); + const envelopeHeader = JSON.stringify({ ...(this.options.tunnel && { dsn: this._api.dsn.toString() }) }); const itemHeaders = JSON.stringify({ type: 'client_report', }); diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts index 07c9dead3fb6..44139f6b0a22 100644 --- a/packages/core/src/api.ts +++ b/packages/core/src/api.ts @@ -156,7 +156,7 @@ export function getEnvelopeEndpointWithUrlEncodedAuth(dsn: Dsn, tunnel?: string) * Returns an object that can be used in request headers. * This is needed for node and the old /store endpoint in sentry */ -function getRequestHeaders(dsn: Dsn, clientName: string, clientVersion: string): { [key: string]: string } { +export function getRequestHeaders(dsn: Dsn, clientName: string, clientVersion: string): { [key: string]: string } { // CHANGE THIS to use metadata but keep clientName and clientVersion compatible const header = [`Sentry sentry_version=${SENTRY_API_VERSION}`]; header.push(`sentry_client=${clientName}/${clientVersion}`); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index c54d16d7e3ac..22308a0cb7e8 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -18,8 +18,9 @@ export { // eslint-disable-next-line deprecation/deprecation API, APIDetails, - getStoreEndpointWithUrlEncodedAuth, getEnvelopeEndpointWithUrlEncodedAuth, + getStoreEndpointWithUrlEncodedAuth, + getRequestHeaders, initAPIDetails, getReportDialogEndpoint, } from './api'; diff --git a/packages/core/src/request.ts b/packages/core/src/request.ts index 54197023a2eb..da8dff52d7aa 100644 --- a/packages/core/src/request.ts +++ b/packages/core/src/request.ts @@ -1,9 +1,9 @@ import { Event, SdkInfo, SentryRequest, SentryRequestType, Session, SessionAggregates } from '@sentry/types'; -import { API } from './api'; +import { APIDetails, getEnvelopeEndpointWithUrlEncodedAuth, getStoreEndpointWithUrlEncodedAuth } from './api'; /** Extract sdk info from from the API metadata */ -function getSdkMetadataForEnvelopeHeader(api: API): SdkInfo | undefined { +function getSdkMetadataForEnvelopeHeader(api: APIDetails): SdkInfo | undefined { if (!api.metadata || !api.metadata.sdk) { return; } @@ -28,12 +28,12 @@ function enhanceEventWithSdkInfo(event: Event, sdkInfo?: SdkInfo): Event { } /** Creates a SentryRequest from a Session. */ -export function sessionToSentryRequest(session: Session | SessionAggregates, api: API): SentryRequest { +export function sessionToSentryRequest(session: Session | SessionAggregates, api: APIDetails): SentryRequest { const sdkInfo = getSdkMetadataForEnvelopeHeader(api); const envelopeHeaders = JSON.stringify({ sent_at: new Date().toISOString(), ...(sdkInfo && { sdk: sdkInfo }), - ...(api.forceEnvelope() && { dsn: api.getDsn().toString() }), + ...(!!api.tunnel && { dsn: api.dsn.toString() }), }); // I know this is hacky but we don't want to add `session` to request type since it's never rate limited const type: SentryRequestType = 'aggregates' in session ? ('sessions' as SentryRequestType) : 'session'; @@ -44,15 +44,15 @@ export function sessionToSentryRequest(session: Session | SessionAggregates, api return { body: `${envelopeHeaders}\n${itemHeaders}\n${JSON.stringify(session)}`, type, - url: api.getEnvelopeEndpointWithUrlEncodedAuth(), + url: getEnvelopeEndpointWithUrlEncodedAuth(api.dsn), }; } /** Creates a SentryRequest from an event. */ -export function eventToSentryRequest(event: Event, api: API): SentryRequest { +export function eventToSentryRequest(event: Event, api: APIDetails): SentryRequest { const sdkInfo = getSdkMetadataForEnvelopeHeader(api); const eventType = event.type || 'event'; - const useEnvelope = eventType === 'transaction' || api.forceEnvelope(); + const useEnvelope = eventType === 'transaction' || !!api.tunnel; const { transactionSampling, ...metadata } = event.debug_meta || {}; const { method: samplingMethod, rate: sampleRate } = transactionSampling || {}; @@ -65,7 +65,7 @@ export function eventToSentryRequest(event: Event, api: API): SentryRequest { const req: SentryRequest = { body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, api.metadata.sdk) : event), type: eventType, - url: useEnvelope ? api.getEnvelopeEndpointWithUrlEncodedAuth() : api.getStoreEndpointWithUrlEncodedAuth(), + url: useEnvelope ? getEnvelopeEndpointWithUrlEncodedAuth(api.dsn) : getStoreEndpointWithUrlEncodedAuth(api.dsn), }; // https://develop.sentry.dev/sdk/envelopes/ @@ -79,7 +79,7 @@ export function eventToSentryRequest(event: Event, api: API): SentryRequest { event_id: event.event_id, sent_at: new Date().toISOString(), ...(sdkInfo && { sdk: sdkInfo }), - ...(api.forceEnvelope() && { dsn: api.getDsn().toString() }), + ...(!!api.tunnel && { dsn: api.dsn.toString() }), }); const itemHeaders = JSON.stringify({ type: eventType, diff --git a/packages/node/src/transports/base/index.ts b/packages/node/src/transports/base/index.ts index 0cfa3f78943f..11260113ab62 100644 --- a/packages/node/src/transports/base/index.ts +++ b/packages/node/src/transports/base/index.ts @@ -1,4 +1,4 @@ -import { API, SDK_VERSION } from '@sentry/core'; +import { APIDetails, getRequestHeaders, initAPIDetails, SDK_VERSION } from '@sentry/core'; import { DsnProtocol, Event, @@ -41,7 +41,7 @@ export abstract class BaseTransport implements Transport { public client?: http.Agent | https.Agent; /** API object */ - protected _api: API; + protected _api: APIDetails; /** A simple buffer holding all requests. */ protected readonly _buffer: PromiseBuffer = new PromiseBuffer(30); @@ -51,7 +51,8 @@ export abstract class BaseTransport implements Transport { /** Create instance and set this.dsn */ public constructor(public options: TransportOptions) { - this._api = new API(options.dsn, options._metadata, options.tunnel); + // eslint-disable-next-line deprecation/deprecation + this._api = initAPIDetails(options.dsn, options._metadata, options.tunnel); } /** Default function used to parse URLs */ @@ -89,7 +90,7 @@ export abstract class BaseTransport implements Transport { return proxy; } - const { host, port } = this._api.getDsn(); + const { host, port } = this._api.dsn; for (const np of no_proxy.split(',')) { if (host.endsWith(np) || `${host}:${port}`.endsWith(np)) { return; @@ -102,7 +103,7 @@ export abstract class BaseTransport implements Transport { /** Returns a build request option object used by request */ protected _getRequestOptions(urlParts: URLParts): http.RequestOptions | https.RequestOptions { const headers = { - ...this._api.getRequestHeaders(SDK_NAME, SDK_VERSION), + ...getRequestHeaders(this._api.dsn, SDK_NAME, SDK_VERSION), ...this.options.headers, }; const { hostname, pathname, port, protocol } = urlParts; From 3bd4301750f68782432c603ca4dcfb78c9f31510 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 10:05:43 -0500 Subject: [PATCH 3/7] fix tests --- packages/core/test/lib/api.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/test/lib/api.test.ts b/packages/core/test/lib/api.test.ts index 4ca0b381ed09..a4d951ced7ba 100644 --- a/packages/core/test/lib/api.test.ts +++ b/packages/core/test/lib/api.test.ts @@ -1,6 +1,6 @@ import { Dsn } from '@sentry/utils'; -import { API, getReportDialogEndpoint } from '../../src/api'; +import { API, getReportDialogEndpoint, getRequestHeaders } from '../../src/api'; const ingestDsn = 'https://abc@xxxx.ingest.sentry.io:1234/subpath/123'; const dsnPublic = 'https://abc@sentry.io:1234/subpath/123'; @@ -24,12 +24,12 @@ describe('API', () => { }); test('getRequestHeaders', () => { - expect(new API(dsnPublic).getRequestHeaders('a', '1.0')).toMatchObject({ + expect(getRequestHeaders(new Dsn(dsnPublic), 'a', '1.0')).toMatchObject({ 'Content-Type': 'application/json', 'X-Sentry-Auth': expect.stringMatching(/^Sentry sentry_version=\d, sentry_client=a\/1\.0, sentry_key=abc$/), }); - expect(new API(legacyDsn).getRequestHeaders('a', '1.0')).toMatchObject({ + expect(getRequestHeaders(new Dsn(legacyDsn), 'a', '1.0')).toMatchObject({ 'Content-Type': 'application/json', 'X-Sentry-Auth': expect.stringMatching( /^Sentry sentry_version=\d, sentry_client=a\/1\.0, sentry_key=abc, sentry_secret=123$/, From c1d6f8bfcbb7896463a77c4df917096d40e57a37 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 10:28:42 -0500 Subject: [PATCH 4/7] fix request tests --- packages/core/test/lib/request.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/test/lib/request.test.ts b/packages/core/test/lib/request.test.ts index 3419874d1a97..6e27bb26a4af 100644 --- a/packages/core/test/lib/request.test.ts +++ b/packages/core/test/lib/request.test.ts @@ -1,6 +1,6 @@ import { DebugMeta, Event, SentryRequest, TransactionSamplingMethod } from '@sentry/types'; -import { API } from '../../src/api'; +import { initAPIDetails } from '../../src/api'; import { eventToSentryRequest, sessionToSentryRequest } from '../../src/request'; const ingestDsn = 'https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012'; @@ -8,7 +8,7 @@ const ingestUrl = 'https://squirrelchasers.ingest.sentry.io/api/12312012/envelope/?sentry_key=dogsarebadatkeepingsecrets&sentry_version=7'; const tunnel = 'https://hello.com/world'; -const api = new API(ingestDsn, { +const api = initAPIDetails(ingestDsn, { sdk: { integrations: ['AWSLambda'], name: 'sentry.javascript.browser', @@ -132,15 +132,15 @@ describe('eventToSentryRequest', () => { }); it('uses tunnel as the url if it is configured', () => { - const tunnelRequest = eventToSentryRequest(event, new API(ingestDsn, {}, tunnel)); + const tunnelRequest = eventToSentryRequest(event, initAPIDetails(ingestDsn, {}, tunnel)); expect(tunnelRequest.url).toEqual(tunnel); - const defaultRequest = eventToSentryRequest(event, new API(ingestDsn, {})); + const defaultRequest = eventToSentryRequest(event, initAPIDetails(ingestDsn, {})); expect(defaultRequest.url).toEqual(ingestUrl); }); it('adds dsn to envelope header if tunnel is configured', () => { - const result = eventToSentryRequest(event, new API(ingestDsn, {}, tunnel)); + const result = eventToSentryRequest(event, initAPIDetails(ingestDsn, {}, tunnel)); const envelope = parseEnvelopeRequest(result); expect(envelope.envelopeHeader).toEqual( @@ -153,7 +153,7 @@ describe('eventToSentryRequest', () => { it('adds default "event" item type to item header if tunnel is configured', () => { delete event.type; - const result = eventToSentryRequest(event, new API(ingestDsn, {}, tunnel)); + const result = eventToSentryRequest(event, initAPIDetails(ingestDsn, {}, tunnel)); const envelope = parseEnvelopeRequest(result); expect(envelope.itemHeader).toEqual( @@ -193,15 +193,15 @@ describe('sessionToSentryRequest', () => { }); it('uses tunnel as the url if it is configured', () => { - const tunnelRequest = sessionToSentryRequest({ aggregates: [] }, new API(ingestDsn, {}, tunnel)); + const tunnelRequest = sessionToSentryRequest({ aggregates: [] }, initAPIDetails(ingestDsn, {}, tunnel)); expect(tunnelRequest.url).toEqual(tunnel); - const defaultRequest = sessionToSentryRequest({ aggregates: [] }, new API(ingestDsn, {})); + const defaultRequest = sessionToSentryRequest({ aggregates: [] }, initAPIDetails(ingestDsn, {})); expect(defaultRequest.url).toEqual(ingestUrl); }); it('adds dsn to envelope header if tunnel is configured', () => { - const result = sessionToSentryRequest({ aggregates: [] }, new API(ingestDsn, {}, tunnel)); + const result = sessionToSentryRequest({ aggregates: [] }, initAPIDetails(ingestDsn, {}, tunnel)); const envelope = parseEnvelopeRequest(result); expect(envelope.envelopeHeader).toEqual( From fed9ce66460e5f038ff678eb800e67707c4b6a7d Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 10:40:54 -0500 Subject: [PATCH 5/7] pass down tunnel properly --- packages/browser/src/transports/base.ts | 4 ++-- packages/core/src/request.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index bdb7694505f6..8fd960593ac5 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -117,9 +117,9 @@ export abstract class BaseTransport implements Transport { logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); - const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn); + const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn, this._api.tunnel); // Envelope header is required to be at least an empty object - const envelopeHeader = JSON.stringify({ ...(this.options.tunnel && { dsn: this._api.dsn.toString() }) }); + const envelopeHeader = JSON.stringify({ ...(this._api.tunnel && { dsn: this._api.dsn.toString() }) }); const itemHeaders = JSON.stringify({ type: 'client_report', }); diff --git a/packages/core/src/request.ts b/packages/core/src/request.ts index da8dff52d7aa..c1242e0dce12 100644 --- a/packages/core/src/request.ts +++ b/packages/core/src/request.ts @@ -44,7 +44,7 @@ export function sessionToSentryRequest(session: Session | SessionAggregates, api return { body: `${envelopeHeaders}\n${itemHeaders}\n${JSON.stringify(session)}`, type, - url: getEnvelopeEndpointWithUrlEncodedAuth(api.dsn), + url: getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel), }; } @@ -65,7 +65,9 @@ export function eventToSentryRequest(event: Event, api: APIDetails): SentryReque const req: SentryRequest = { body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, api.metadata.sdk) : event), type: eventType, - url: useEnvelope ? getEnvelopeEndpointWithUrlEncodedAuth(api.dsn) : getStoreEndpointWithUrlEncodedAuth(api.dsn), + url: useEnvelope + ? getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel) + : getStoreEndpointWithUrlEncodedAuth(api.dsn), }; // https://develop.sentry.dev/sdk/envelopes/ From f8754e15ad596c7dc5c4cb313da01e0e99db44ce Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 10:53:35 -0500 Subject: [PATCH 6/7] eslint disable deprecation --- packages/core/test/lib/api.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/test/lib/api.test.ts b/packages/core/test/lib/api.test.ts index a4d951ced7ba..fd2e97b6d77d 100644 --- a/packages/core/test/lib/api.test.ts +++ b/packages/core/test/lib/api.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable deprecation/deprecation */ import { Dsn } from '@sentry/utils'; import { API, getReportDialogEndpoint, getRequestHeaders } from '../../src/api'; From 37e83a4de25f6683eba503ff843cf82c10a207c8 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 14 Dec 2021 11:21:26 -0500 Subject: [PATCH 7/7] only check for tunnel once --- packages/core/src/api.ts | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts index 44139f6b0a22..78369d80fcec 100644 --- a/packages/core/src/api.ts +++ b/packages/core/src/api.ts @@ -102,22 +102,18 @@ function getBaseApiEndpoint(dsn: Dsn): string { } /** Returns the ingest API endpoint for target. */ -function _getIngestEndpoint(dsn: Dsn, target: 'store' | 'envelope', tunnel?: string): string { - if (tunnel) { - return tunnel; - } +function _getIngestEndpoint(dsn: Dsn, target: 'store' | 'envelope'): string { return `${getBaseApiEndpoint(dsn)}${dsn.projectId}/${target}/`; } /** Returns a URL-encoded string with auth config suitable for a query string. */ function _encodedAuth(dsn: Dsn): string { - const auth = { + return urlEncode({ // We send only the minimum set of required information. See // https://github.com/getsentry/sentry-javascript/issues/2572. sentry_key: dsn.publicKey, sentry_version: SENTRY_API_VERSION, - }; - return urlEncode(auth); + }); } /** Returns the store endpoint URL. */ @@ -135,8 +131,8 @@ export function getStoreEndpointWithUrlEncodedAuth(dsn: Dsn): string { } /** Returns the envelope endpoint URL. */ -function _getEnvelopeEndpoint(dsn: Dsn, tunnel?: string): string { - return _getIngestEndpoint(dsn, 'envelope', tunnel); +function _getEnvelopeEndpoint(dsn: Dsn): string { + return _getIngestEndpoint(dsn, 'envelope'); } /** @@ -145,11 +141,7 @@ function _getEnvelopeEndpoint(dsn: Dsn, tunnel?: string): string { * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests. */ export function getEnvelopeEndpointWithUrlEncodedAuth(dsn: Dsn, tunnel?: string): string { - if (tunnel) { - return tunnel; - } - - return `${_getEnvelopeEndpoint(dsn, tunnel)}?${_encodedAuth(dsn)}`; + return tunnel ? tunnel : `${_getEnvelopeEndpoint(dsn)}?${_encodedAuth(dsn)}`; } /**