package.build.cjs.utils-hoist.requestdata.js.map Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core Show documentation
Show all versions of core Show documentation
Base implementation for all Sentry JavaScript SDKs
The newest version!
{"version":3,"file":"requestdata.js","sources":["../../../src/utils-hoist/requestdata.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type {\n Event,\n ExtractedNodeRequestData,\n PolymorphicRequest,\n RequestEventData,\n TransactionSource,\n WebFetchHeaders,\n WebFetchRequest,\n} from '../types-hoist';\n\nimport { parseCookie } from './cookie';\nimport { DEBUG_BUILD } from './debug-build';\nimport { isPlainObject, isString } from './is';\nimport { logger } from './logger';\nimport { normalize } from './normalize';\nimport { dropUndefinedKeys } from './object';\nimport { truncate } from './string';\nimport { stripUrlQueryAndFragment } from './url';\nimport { getClientIPAddress, ipHeaderNames } from './vendor/getIpAddress';\n\nconst DEFAULT_INCLUDES = {\n ip: false,\n request: true,\n user: true,\n};\nconst DEFAULT_REQUEST_INCLUDES = ['cookies', 'data', 'headers', 'method', 'query_string', 'url'];\nexport const DEFAULT_USER_INCLUDES = ['id', 'username', 'email'];\n\n/**\n * Options deciding what parts of the request to use when enhancing an event\n */\nexport type AddRequestDataToEventOptions = {\n /** Flags controlling whether each type of data should be added to the event */\n include?: {\n ip?: boolean;\n request?: boolean | Array<(typeof DEFAULT_REQUEST_INCLUDES)[number]>;\n /** @deprecated This option will be removed in v9. It does not do anything anymore, the `transcation` is set in other places. */\n // eslint-disable-next-line deprecation/deprecation\n transaction?: boolean | TransactionNamingScheme;\n user?: boolean | Array<(typeof DEFAULT_USER_INCLUDES)[number]>;\n };\n\n /** Injected platform-specific dependencies */\n deps?: {\n cookie: {\n parse: (cookieStr: string) => Record;\n };\n url: {\n parse: (urlStr: string) => {\n query: string | null;\n };\n };\n };\n};\n\n/**\n * @deprecated This type will be removed in v9. It is not in use anymore.\n */\nexport type TransactionNamingScheme = 'path' | 'methodPath' | 'handler';\n\n/**\n * Extracts a complete and parameterized path from the request object and uses it to construct transaction name.\n * If the parameterized transaction name cannot be extracted, we fall back to the raw URL.\n *\n * Additionally, this function determines and returns the transaction name source\n *\n * eg. GET /mountpoint/user/:id\n *\n * @param req A request object\n * @param options What to include in the transaction name (method, path, or a custom route name to be\n * used instead of the request's route)\n *\n * @returns A tuple of the fully constructed transaction name [0] and its source [1] (can be either 'route' or 'url')\n * @deprecated This method will be removed in v9. It is not in use anymore.\n */\nexport function extractPathForTransaction(\n req: PolymorphicRequest,\n options: { path?: boolean; method?: boolean; customRoute?: string } = {},\n): [string, TransactionSource] {\n const method = req.method && req.method.toUpperCase();\n\n let path = '';\n let source: TransactionSource = 'url';\n\n // Check to see if there's a parameterized route we can use (as there is in Express)\n if (options.customRoute || req.route) {\n path = options.customRoute || `${req.baseUrl || ''}${req.route && req.route.path}`;\n source = 'route';\n }\n\n // Otherwise, just take the original URL\n else if (req.originalUrl || req.url) {\n path = stripUrlQueryAndFragment(req.originalUrl || req.url || '');\n }\n\n let name = '';\n if (options.method && method) {\n name += method;\n }\n if (options.method && options.path) {\n name += ' ';\n }\n if (options.path && path) {\n name += path;\n }\n\n return [name, source];\n}\n\nfunction extractUserData(\n user: {\n [key: string]: unknown;\n },\n keys: boolean | string[],\n): { [key: string]: unknown } {\n const extractedUser: { [key: string]: unknown } = {};\n const attributes = Array.isArray(keys) ? keys : DEFAULT_USER_INCLUDES;\n\n attributes.forEach(key => {\n if (user && key in user) {\n extractedUser[key] = user[key];\n }\n });\n\n return extractedUser;\n}\n\n/**\n * Normalize data from the request object, accounting for framework differences.\n *\n * @param req The request object from which to extract data\n * @param options.include An optional array of keys to include in the normalized data. Defaults to\n * DEFAULT_REQUEST_INCLUDES if not provided.\n * @param options.deps Injected, platform-specific dependencies\n * @returns An object containing normalized request data\n *\n * @deprecated Instead manually normalize the request data into a format that fits `addNormalizedRequestDataToEvent`.\n */\nexport function extractRequestData(\n req: PolymorphicRequest,\n options: {\n include?: string[];\n } = {},\n): ExtractedNodeRequestData {\n const { include = DEFAULT_REQUEST_INCLUDES } = options;\n const requestData: { [key: string]: unknown } = {};\n\n // headers:\n // node, express, koa, nextjs: req.headers\n const headers = (req.headers || {}) as typeof req.headers & {\n host?: string;\n cookie?: string;\n };\n // method:\n // node, express, koa, nextjs: req.method\n const method = req.method;\n // host:\n // express: req.hostname in > 4 and req.host in < 4\n // koa: req.host\n // node, nextjs: req.headers.host\n // Express 4 mistakenly strips off port number from req.host / req.hostname so we can't rely on them\n // See: https://github.com/expressjs/express/issues/3047#issuecomment-236653223\n // Also: https://github.com/getsentry/sentry-javascript/issues/1917\n const host = headers.host || req.hostname || req.host || '';\n // protocol:\n // node, nextjs: \n // express, koa: req.protocol\n const protocol = req.protocol === 'https' || (req.socket && req.socket.encrypted) ? 'https' : 'http';\n // url (including path and query string):\n // node, express: req.originalUrl\n // koa, nextjs: req.url\n const originalUrl = req.originalUrl || req.url || '';\n // absolute url\n const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;\n include.forEach(key => {\n switch (key) {\n case 'headers': {\n requestData.headers = headers;\n\n // Remove the Cookie header in case cookie data should not be included in the event\n if (!include.includes('cookies')) {\n delete (requestData.headers as { cookie?: string }).cookie;\n }\n\n // Remove IP headers in case IP data should not be included in the event\n if (!include.includes('ip')) {\n ipHeaderNames.forEach(ipHeaderName => {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete (requestData.headers as Record)[ipHeaderName];\n });\n }\n\n break;\n }\n case 'method': {\n requestData.method = method;\n break;\n }\n case 'url': {\n requestData.url = absoluteUrl;\n break;\n }\n case 'cookies': {\n // cookies:\n // node, express, koa: req.headers.cookie\n // vercel, sails.js, express (w/ cookie middleware), nextjs: req.cookies\n requestData.cookies =\n // TODO (v8 / #5257): We're only sending the empty object for backwards compatibility, so the last bit can\n // come off in v8\n req.cookies || (headers.cookie && parseCookie(headers.cookie)) || {};\n break;\n }\n case 'query_string': {\n // query string:\n // node: req.url (raw)\n // express, koa, nextjs: req.query\n requestData.query_string = extractQueryParams(req);\n break;\n }\n case 'data': {\n if (method === 'GET' || method === 'HEAD') {\n break;\n }\n // NOTE: As of v8, request is (unless a user sets this manually) ALWAYS a http request\n // Which does not have a body by default\n // However, in our http instrumentation, we patch the request to capture the body and store it on the\n // request as `.body` anyhow\n // In v9, we may update requestData to only work with plain http requests\n // body data:\n // express, koa, nextjs: req.body\n //\n // when using node by itself, you have to read the incoming stream(see\n // https://nodejs.dev/learn/get-http-request-body-data-using-nodejs); if a user is doing that, we can't know\n // where they're going to store the final result, so they'll have to capture this data themselves\n const body = req.body;\n if (body !== undefined) {\n const stringBody: string = isString(body)\n ? body\n : isPlainObject(body)\n ? JSON.stringify(normalize(body))\n : truncate(`${body}`, 1024);\n if (stringBody) {\n requestData.data = stringBody;\n }\n }\n break;\n }\n default: {\n if ({}.hasOwnProperty.call(req, key)) {\n requestData[key] = (req as { [key: string]: unknown })[key];\n }\n }\n }\n });\n\n return requestData;\n}\n\n/**\n * Add already normalized request data to an event.\n * This mutates the passed in event.\n */\nexport function addNormalizedRequestDataToEvent(\n event: Event,\n req: RequestEventData,\n // This is non-standard data that is not part of the regular HTTP request\n additionalData: { ipAddress?: string; user?: Record },\n options: AddRequestDataToEventOptions,\n): void {\n const include = {\n ...DEFAULT_INCLUDES,\n ...(options && options.include),\n };\n\n if (include.request) {\n const includeRequest = Array.isArray(include.request) ? [...include.request] : [...DEFAULT_REQUEST_INCLUDES];\n if (include.ip) {\n includeRequest.push('ip');\n }\n\n const extractedRequestData = extractNormalizedRequestData(req, { include: includeRequest });\n\n event.request = {\n ...event.request,\n ...extractedRequestData,\n };\n }\n\n if (include.user) {\n const extractedUser =\n additionalData.user && isPlainObject(additionalData.user)\n ? extractUserData(additionalData.user, include.user)\n : {};\n\n if (Object.keys(extractedUser).length) {\n event.user = {\n ...event.user,\n ...extractedUser,\n };\n }\n }\n\n if (include.ip) {\n const ip = (req.headers && getClientIPAddress(req.headers)) || additionalData.ipAddress;\n if (ip) {\n event.user = {\n ...event.user,\n ip_address: ip,\n };\n }\n }\n}\n\n/**\n * Add data from the given request to the given event\n *\n * @param event The event to which the request data will be added\n * @param req Request object\n * @param options.include Flags to control what data is included\n * @param options.deps Injected platform-specific dependencies\n * @returns The mutated `Event` object\n *\n * @deprecated Use `addNormalizedRequestDataToEvent` instead.\n */\nexport function addRequestDataToEvent(\n event: Event,\n req: PolymorphicRequest,\n options?: AddRequestDataToEventOptions,\n): Event {\n const include = {\n ...DEFAULT_INCLUDES,\n ...(options && options.include),\n };\n\n if (include.request) {\n const includeRequest = Array.isArray(include.request) ? [...include.request] : [...DEFAULT_REQUEST_INCLUDES];\n if (include.ip) {\n includeRequest.push('ip');\n }\n\n // eslint-disable-next-line deprecation/deprecation\n const extractedRequestData = extractRequestData(req, { include: includeRequest });\n\n event.request = {\n ...event.request,\n ...extractedRequestData,\n };\n }\n\n if (include.user) {\n const extractedUser = req.user && isPlainObject(req.user) ? extractUserData(req.user, include.user) : {};\n\n if (Object.keys(extractedUser).length) {\n event.user = {\n ...event.user,\n ...extractedUser,\n };\n }\n }\n\n // client ip:\n // node, nextjs: req.socket.remoteAddress\n // express, koa: req.ip\n // It may also be sent by proxies as specified in X-Forwarded-For or similar headers\n if (include.ip) {\n const ip = (req.headers && getClientIPAddress(req.headers)) || req.ip || (req.socket && req.socket.remoteAddress);\n if (ip) {\n event.user = {\n ...event.user,\n ip_address: ip,\n };\n }\n }\n\n return event;\n}\n\nfunction extractQueryParams(req: PolymorphicRequest): string | Record | undefined {\n // url (including path and query string):\n // node, express: req.originalUrl\n // koa, nextjs: req.url\n let originalUrl = req.originalUrl || req.url || '';\n\n if (!originalUrl) {\n return;\n }\n\n // The `URL` constructor can't handle internal URLs of the form `/some/path/here`, so stick a dummy protocol and\n // hostname on the beginning. Since the point here is just to grab the query string, it doesn't matter what we use.\n if (originalUrl.startsWith('/')) {\n originalUrl = `http://dogs.are.great${originalUrl}`;\n }\n\n try {\n const queryParams = req.query || new URL(originalUrl).search.slice(1);\n return queryParams.length ? queryParams : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Transforms a `Headers` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into a simple key-value dict.\n * The header keys will be lower case: e.g. A \"Content-Type\" header will be stored as \"content-type\".\n */\n// TODO(v8): Make this function return undefined when the extraction fails.\nexport function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record {\n const headers: Record = {};\n try {\n winterCGHeaders.forEach((value, key) => {\n if (typeof value === 'string') {\n // We check that value is a string even though it might be redundant to make sure prototype pollution is not possible.\n headers[key] = value;\n }\n });\n } catch (e) {\n DEBUG_BUILD &&\n logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.');\n }\n\n return headers;\n}\n\n/**\n * Convert common request headers to a simple dictionary.\n */\nexport function headersToDict(reqHeaders: Record): Record {\n const headers: Record = Object.create(null);\n\n try {\n Object.entries(reqHeaders).forEach(([key, value]) => {\n if (typeof value === 'string') {\n headers[key] = value;\n }\n });\n } catch (e) {\n DEBUG_BUILD &&\n logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.');\n }\n\n return headers;\n}\n\n/**\n * Converts a `Request` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into the format that the `RequestData` integration understands.\n */\nexport function winterCGRequestToRequestData(req: WebFetchRequest): RequestEventData {\n const headers = winterCGHeadersToDict(req.headers);\n\n return {\n method: req.method,\n url: req.url,\n query_string: extractQueryParamsFromUrl(req.url),\n headers,\n // TODO: Can we extract body data from the request?\n };\n}\n\n/**\n * Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.\n * Instead of allowing `PolymorphicRequest` to be passed,\n * we want to be more specific and generally require a http.IncomingMessage-like object.\n */\nexport function httpRequestToRequestData(request: {\n method?: string;\n url?: string;\n headers?: {\n [key: string]: string | string[] | undefined;\n };\n protocol?: string;\n socket?: unknown;\n}): RequestEventData {\n const headers = request.headers || {};\n const host = headers.host || '';\n const protocol = request.socket && (request.socket as { encrypted?: boolean }).encrypted ? 'https' : 'http';\n const originalUrl = request.url || '';\n const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;\n\n // This is non-standard, but may be sometimes set\n // It may be overwritten later by our own body handling\n const data = (request as PolymorphicRequest).body || undefined;\n\n // This is non-standard, but may be set on e.g. Next.js or Express requests\n const cookies = (request as PolymorphicRequest).cookies;\n\n return dropUndefinedKeys({\n url: absoluteUrl,\n method: request.method,\n query_string: extractQueryParamsFromUrl(originalUrl),\n headers: headersToDict(headers),\n cookies,\n data,\n });\n}\n\n/** Extract the query params from an URL. */\nexport function extractQueryParamsFromUrl(url: string): string | undefined {\n // url is path and query string\n if (!url) {\n return;\n }\n\n try {\n // The `URL` constructor can't handle internal URLs of the form `/some/path/here`, so stick a dummy protocol and\n // hostname as the base. Since the point here is just to grab the query string, it doesn't matter what we use.\n const queryParams = new URL(url, 'http://dogs.are.great').search.slice(1);\n return queryParams.length ? queryParams : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction extractNormalizedRequestData(\n normalizedRequest: RequestEventData,\n { include }: { include: string[] },\n): RequestEventData {\n const includeKeys = include ? (Array.isArray(include) ? include : DEFAULT_REQUEST_INCLUDES) : [];\n\n const requestData: RequestEventData = {};\n const headers = { ...normalizedRequest.headers };\n\n if (includeKeys.includes('headers')) {\n requestData.headers = headers;\n\n // Remove the Cookie header in case cookie data should not be included in the event\n if (!include.includes('cookies')) {\n delete (headers as { cookie?: string }).cookie;\n }\n\n // Remove IP headers in case IP data should not be included in the event\n if (!include.includes('ip')) {\n ipHeaderNames.forEach(ipHeaderName => {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete (headers as Record)[ipHeaderName];\n });\n }\n }\n\n if (includeKeys.includes('method')) {\n requestData.method = normalizedRequest.method;\n }\n\n if (includeKeys.includes('url')) {\n requestData.url = normalizedRequest.url;\n }\n\n if (includeKeys.includes('cookies')) {\n const cookies = normalizedRequest.cookies || (headers && headers.cookie ? parseCookie(headers.cookie) : undefined);\n requestData.cookies = cookies || {};\n }\n\n if (includeKeys.includes('query_string')) {\n requestData.query_string = normalizedRequest.query_string;\n }\n\n if (includeKeys.includes('data')) {\n requestData.data = normalizedRequest.data;\n }\n\n return requestData;\n}\n"],"names":["stripUrlQueryAndFragment","ipHeaderNames","parseCookie","isString","isPlainObject","normalize","truncate","getClientIPAddress","DEBUG_BUILD","logger","dropUndefinedKeys"],"mappings":"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"}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy