All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.build.cjs.utils-hoist.requestdata.js.map Maven / Gradle / Ivy

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