diff --git a/packages/browser/src/exports.ts b/packages/browser/src/exports.ts index d198d921d6ae..ad96e21c4ffe 100644 --- a/packages/browser/src/exports.ts +++ b/packages/browser/src/exports.ts @@ -58,4 +58,4 @@ export { winjsStackLineParser, } from './stack-parsers'; export { defaultIntegrations, forceLoad, init, lastEventId, onLoad, showReportDialog, flush, close, wrap } from './sdk'; -export { GlobalHandlers, TryCatch, Breadcrumbs, LinkedErrors, HttpContext, HttpClient, Dedupe } from './integrations'; +export { GlobalHandlers, TryCatch, Breadcrumbs, LinkedErrors, HttpContext, Dedupe } from './integrations'; diff --git a/packages/browser/src/integrations/index.ts b/packages/browser/src/integrations/index.ts index f581d82c4fe5..e029422f363c 100644 --- a/packages/browser/src/integrations/index.ts +++ b/packages/browser/src/integrations/index.ts @@ -4,4 +4,3 @@ export { Breadcrumbs } from './breadcrumbs'; export { LinkedErrors } from './linkederrors'; export { HttpContext } from './httpcontext'; export { Dedupe } from './dedupe'; -export { HttpClient } from './httpclient'; diff --git a/packages/integration-tests/suites/integrations/httpclient/init.js b/packages/integration-tests/suites/integrations/httpclient/init.js index 5dbc124bb83b..5d43b49e75fb 100644 --- a/packages/integration-tests/suites/integrations/httpclient/init.js +++ b/packages/integration-tests/suites/integrations/httpclient/init.js @@ -1,10 +1,11 @@ import * as Sentry from '@sentry/browser'; +import { HttpClient } from '@sentry/integrations'; window.Sentry = Sentry; Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', - integrations: [new Sentry.Integrations.HttpClient()], + integrations: [new HttpClient()], tracesSampleRate: 1, sendDefaultPii: true, }); diff --git a/packages/browser/src/integrations/httpclient.ts b/packages/integrations/src/httpclient.ts similarity index 88% rename from packages/browser/src/integrations/httpclient.ts rename to packages/integrations/src/httpclient.ts index 046c974fa802..8792ca5901fc 100644 --- a/packages/browser/src/integrations/httpclient.ts +++ b/packages/integrations/src/httpclient.ts @@ -1,9 +1,6 @@ -import { captureEvent, getCurrentHub } from '@sentry/core'; -import { Event as SentryEvent, Integration } from '@sentry/types'; +import { Event as SentryEvent, EventProcessor, Hub, Integration } from '@sentry/types'; import { addExceptionMechanism, fill, GLOBAL_OBJ, logger, supportsNativeFetch } from '@sentry/utils'; -import { eventFromUnknownInput } from '../eventbuilder'; - export type HttpStatusCodeRange = [number, number] | number; export type HttpRequestTarget = string | RegExp; interface HttpClientOptions { @@ -41,6 +38,11 @@ export class HttpClient implements Integration { private readonly _options: HttpClientOptions; + /** + * Returns current hub. + */ + private _getCurrentHub?: () => Hub; + /** * @inheritDoc * @@ -59,7 +61,8 @@ export class HttpClient implements Integration { * * @param options */ - public setupOnce(): void { + public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { + this._getCurrentHub = getCurrentHub; this._wrapFetch(); this._wrapXHR(); } @@ -72,12 +75,13 @@ export class HttpClient implements Integration { * @param requestInit The request init object */ private _fetchResponseHandler(requestInfo: RequestInfo, response: Response, requestInit?: RequestInit): void { - if (this._shouldCaptureResponse(response.status, response.url)) { + if (this._getCurrentHub && this._shouldCaptureResponse(response.status, response.url)) { const request = new Request(requestInfo, requestInit); + const hub = this._getCurrentHub(); let requestHeaders, responseHeaders, requestCookies, responseCookies; - if (getCurrentHub().shouldSendDefaultPii()) { + if (hub.shouldSendDefaultPii()) { [{ headers: requestHeaders, cookies: requestCookies }, { headers: responseHeaders, cookies: responseCookies }] = [ { cookieHeader: 'Cookie', obj: request }, @@ -113,7 +117,7 @@ export class HttpClient implements Integration { responseCookies, }); - captureEvent(event); + hub.captureEvent(event); } } @@ -125,10 +129,11 @@ export class HttpClient implements Integration { * @param headers The HTTP headers */ private _xhrResponseHandler(xhr: XMLHttpRequest, method: string, headers: Record): void { - if (this._shouldCaptureResponse(xhr.status, xhr.responseURL)) { + if (this._getCurrentHub && this._shouldCaptureResponse(xhr.status, xhr.responseURL)) { let requestHeaders, responseCookies, responseHeaders; + const hub = this._getCurrentHub(); - if (getCurrentHub().shouldSendDefaultPii()) { + if (hub.shouldSendDefaultPii()) { try { const cookieString = xhr.getResponseHeader('Set-Cookie') || xhr.getResponseHeader('set-cookie') || undefined; @@ -158,7 +163,7 @@ export class HttpClient implements Integration { responseCookies, }); - captureEvent(event); + hub.captureEvent(event); } } @@ -362,7 +367,7 @@ export class HttpClient implements Integration { * @param url url to verify */ private _isSentryRequest(url: string): boolean { - const client = getCurrentHub().getClient(); + const client = this._getCurrentHub && this._getCurrentHub().getClient(); if (!client) { return false; @@ -397,22 +402,31 @@ export class HttpClient implements Integration { requestHeaders?: Record; requestCookies?: Record; }): SentryEvent { - const event = eventFromUnknownInput(() => [], `HTTP Client Error with status code: ${data.status}`); - - event.request = { - url: data.url, - method: data.method, - headers: data.requestHeaders, - cookies: data.requestCookies, - }; - - event.contexts = { - ...event.contexts, - response: { - status_code: data.status, - headers: data.responseHeaders, - cookies: data.responseCookies, - body_size: this._getResponseSizeFromHeaders(data.responseHeaders), + const message = `HTTP Client Error with status code: ${data.status}`; + + const event: SentryEvent = { + message, + exception: { + values: [ + { + type: 'Error', + value: message, + }, + ], + }, + request: { + url: data.url, + method: data.method, + headers: data.requestHeaders, + cookies: data.requestCookies, + }, + contexts: { + response: { + status_code: data.status, + headers: data.responseHeaders, + cookies: data.responseCookies, + body_size: this._getResponseSizeFromHeaders(data.responseHeaders), + }, }, }; diff --git a/packages/integrations/src/index.ts b/packages/integrations/src/index.ts index 9a2573ee5a44..2f3708075ac1 100644 --- a/packages/integrations/src/index.ts +++ b/packages/integrations/src/index.ts @@ -7,3 +7,4 @@ export { ReportingObserver } from './reportingobserver'; export { RewriteFrames } from './rewriteframes'; export { SessionTiming } from './sessiontiming'; export { Transaction } from './transaction'; +export { HttpClient } from './httpclient'; diff --git a/packages/types/src/hub.ts b/packages/types/src/hub.ts index a34d4372e08d..555da1ef94ab 100644 --- a/packages/types/src/hub.ts +++ b/packages/types/src/hub.ts @@ -227,4 +227,10 @@ export interface Hub { * @param endSession If set the session will be marked as exited and removed from the scope */ captureSession(endSession?: boolean): void; + + /** + * Returns if default PII should be sent to Sentry and propagated in ourgoing requests + * when Tracing is used. + */ + shouldSendDefaultPii(): boolean; }