{"version":3,"file":"xhr.js","sources":["../../../src/instrument/xhr.ts"],"sourcesContent":["// TODO(v8): Move everything in this file into the browser package. Nothing here is generic and we run risk of leaking browser types into non-browser packages.\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/ban-types */\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, WrappedFunction } from '@sentry/types';\n\nimport { isString } from '../is';\nimport { fill } from '../object';\nimport { GLOBAL_OBJ } from '../worldwide';\nimport { addHandler, maybeInstrument, triggerHandlers } from './_handlers';\n\nconst WINDOW = GLOBAL_OBJ as unknown as Window;\n\nexport const SENTRY_XHR_DATA_KEY = '__sentry_xhr_v3__';\n\n/**\n * Add an instrumentation handler for when an XHR request happens.\n * The handler function is called once when the request starts and once when it ends,\n * which can be identified by checking if it has an `endTimestamp`.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addXhrInstrumentationHandler(handler: (data: HandlerDataXhr) => void): void {\n const type = 'xhr';\n addHandler(type, handler);\n maybeInstrument(type, instrumentXHR);\n}\n\n/** Exported only for tests. */\nexport function instrumentXHR(): void {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (!(WINDOW as any).XMLHttpRequest) {\n return;\n }\n\n const xhrproto = XMLHttpRequest.prototype;\n\n fill(xhrproto, 'open', function (originalOpen: () => void): () => void {\n return function (this: XMLHttpRequest & SentryWrappedXMLHttpRequest, ...args: any[]): void {\n const startTimestamp = Date.now();\n\n // open() should always be called with two or more arguments\n // But to be on the safe side, we actually validate this and bail out if we don't have a method & url\n const method = isString(args[0]) ? args[0].toUpperCase() : undefined;\n const url = parseUrl(args[1]);\n\n if (!method || !url) {\n return originalOpen.apply(this, args);\n }\n\n this[SENTRY_XHR_DATA_KEY] = {\n method,\n url,\n request_headers: {},\n };\n\n // if Sentry key appears in URL, don't capture it as a request\n if (method === 'POST' && url.match(/sentry_key/)) {\n this.__sentry_own_request__ = true;\n }\n\n const onreadystatechangeHandler: () => void = () => {\n // For whatever reason, this is not the same instance here as from the outer method\n const xhrInfo = this[SENTRY_XHR_DATA_KEY];\n\n if (!xhrInfo) {\n return;\n }\n\n if (this.readyState === 4) {\n try {\n // touching statusCode in some platforms throws\n // an exception\n xhrInfo.status_code = this.status;\n } catch (e) {\n /* do nothing */\n }\n\n const handlerData: HandlerDataXhr = {\n args: [method, url],\n endTimestamp: Date.now(),\n startTimestamp,\n xhr: this,\n };\n triggerHandlers('xhr', handlerData);\n }\n };\n\n if ('onreadystatechange' in this && typeof this.onreadystatechange === 'function') {\n fill(this, 'onreadystatechange', function (original: WrappedFunction): Function {\n return function (this: SentryWrappedXMLHttpRequest, ...readyStateArgs: any[]): void {\n onreadystatechangeHandler();\n return original.apply(this, readyStateArgs);\n };\n });\n } else {\n this.addEventListener('readystatechange', onreadystatechangeHandler);\n }\n\n // Intercepting `setRequestHeader` to access the request headers of XHR instance.\n // This will only work for user/library defined headers, not for the default/browser-assigned headers.\n // Request cookies are also unavailable for XHR, as `Cookie` header can't be defined by `setRequestHeader`.\n fill(this, 'setRequestHeader', function (original: WrappedFunction): Function {\n return function (this: SentryWrappedXMLHttpRequest, ...setRequestHeaderArgs: unknown[]): void {\n const [header, value] = setRequestHeaderArgs;\n\n const xhrInfo = this[SENTRY_XHR_DATA_KEY];\n\n if (xhrInfo && isString(header) && isString(value)) {\n xhrInfo.request_headers[header.toLowerCase()] = value;\n }\n\n return original.apply(this, setRequestHeaderArgs);\n };\n });\n\n return originalOpen.apply(this, args);\n };\n });\n\n fill(xhrproto, 'send', function (originalSend: () => void): () => void {\n return function (this: XMLHttpRequest & SentryWrappedXMLHttpRequest, ...args: any[]): void {\n const sentryXhrData = this[SENTRY_XHR_DATA_KEY];\n\n if (!sentryXhrData) {\n return originalSend.apply(this, args);\n }\n\n if (args[0] !== undefined) {\n sentryXhrData.body = args[0];\n }\n\n const handlerData: HandlerDataXhr = {\n args: [sentryXhrData.method, sentryXhrData.url],\n startTimestamp: Date.now(),\n xhr: this,\n };\n triggerHandlers('xhr', handlerData);\n\n return originalSend.apply(this, args);\n };\n });\n}\n\nfunction parseUrl(url: string | unknown): string | undefined {\n if (isString(url)) {\n return url;\n }\n\n try {\n // url can be a string or URL\n // but since URL is not available in IE11, we do not check for it,\n // but simply assume it is an URL and return `toString()` from it (which returns the full URL)\n // If that fails, we just return undefined\n return (url as URL).toString();\n } catch {} // eslint-disable-line no-empty\n\n return undefined;\n}\n"],"names":[],"mappings":"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"}