{"version":3,"file":"request.js","sources":["../../../src/utils/request.ts"],"sourcesContent":["/* eslint-disable max-lines-per-function */\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { Scope } from '../scope';\nimport type { PolymorphicRequest } from '../types-hoist/polymorphics';\nimport type { RequestEventData } from '../types-hoist/request';\nimport type { WebFetchHeaders, WebFetchRequest } from '../types-hoist/webfetchapi';\nimport { debug } from './debug-logger';\nimport { safeUnref } from './timer';\n\n/**\n * Maximum size of incoming HTTP request bodies attached to events.\n *\n * - `'none'`: No request bodies will be attached\n * - `'small'`: Request bodies up to 1,000 bytes will be attached\n * - `'medium'`: Request bodies up to 10,000 bytes will be attached\n * - `'always'`: Request bodies will always be attached (up to 1MB hard cap)\n */\nexport type MaxRequestBodySize = 'none' | 'small' | 'medium' | 'always';\n\n/** Hard cap on captured body size, even when `maxRequestBodySize` is `'always'`. */\nexport const MAX_BODY_BYTE_LENGTH = 1_024 * 1_024;\n\n/** Content types that are safe to capture as text. */\nconst TEXT_CONTENT_TYPES = [\n  'text/',\n  'application/json',\n  'application/x-www-form-urlencoded',\n  'application/xml',\n  'application/graphql',\n];\n\n/**\n * Convert a `maxRequestBodySize` setting to a maximum byte length.\n */\nexport function getMaxBodyByteLength(maxRequestBodySize: Exclude<MaxRequestBodySize, 'none'>): number {\n  if (maxRequestBodySize === 'small') return 1_000;\n  if (maxRequestBodySize === 'medium') return 10_000;\n  return MAX_BODY_BYTE_LENGTH;\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 */\nexport function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record<string, string> {\n  const headers: Record<string, string> = {};\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 {\n    // just return the empty headers\n  }\n\n  return headers;\n}\n\n/**\n * Convert common request headers to a simple dictionary.\n */\nexport function headersToDict(reqHeaders: Record<string, string | string[] | undefined>): Record<string, string> {\n  const headers: Record<string, string> = 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 {\n    // just return the empty headers\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 * Checks if the content type is textual and safe to capture.\n */\nfunction isTextualContentType(contentType: string | null): boolean {\n  if (!contentType) {\n    return false;\n  }\n  const lowerContentType = contentType.toLowerCase();\n  return TEXT_CONTENT_TYPES.some(type => lowerContentType.includes(type));\n}\n\n/**\n * Captures the body from a Web Fetch API Request and adds it to the isolation scope.\n *\n * This function clones the request to read the body without affecting the original.\n * Only textual content types are captured - binary data is skipped.\n *\n * This is used by WinterCG-compatible runtimes (Cloudflare Workers, Deno, Bun, Vercel Edge, etc.)\n * that use the Web Fetch API Request object.\n *\n * @param request - The incoming Web Fetch API Request\n * @param isolationScope - The isolation scope to add the body to\n * @param maxRequestBodySize - The maximum size of the request body to capture ('small' = 1KB, 'medium' = 10KB, 'always' = 1MB)\n */\nexport async function captureBodyFromWinterCGRequest(\n  request: WebFetchRequest,\n  isolationScope: Scope,\n  maxRequestBodySize: Exclude<MaxRequestBodySize, 'none'>,\n): Promise<void> {\n  try {\n    const contentType = request.headers.get('content-type');\n\n    if (!isTextualContentType(contentType)) {\n      DEBUG_BUILD && debug.log('Skipping body capture for non-textual content type:', contentType);\n      return;\n    }\n\n    if (!request.body) {\n      return;\n    }\n\n    const contentLength = request.headers.get('content-length');\n    const maxBodySize = getMaxBodyByteLength(maxRequestBodySize);\n\n    if (contentLength) {\n      const length = parseInt(contentLength, 10);\n      if (!isNaN(length) && length > MAX_BODY_BYTE_LENGTH) {\n        DEBUG_BUILD && debug.log('Skipping body capture: body too large', length);\n        return;\n      }\n    }\n\n    const clonedRequest = request.clone();\n    const bodyPromise = clonedRequest.text();\n    const timeoutPromise = new Promise<null>(resolve => {\n      safeUnref(setTimeout(() => resolve(null), 2000));\n    });\n\n    const body = await Promise.race([bodyPromise, timeoutPromise]);\n\n    if (body === null) {\n      DEBUG_BUILD && debug.log('Timeout reading request body');\n      return;\n    }\n\n    if (!body) {\n      return;\n    }\n\n    // Using TextEncoder to get byte length for UTF-8 strings\n    const encoder = new TextEncoder();\n    const bytes = encoder.encode(body);\n    const bodyByteLength = bytes.length;\n\n    let truncatedBody: string;\n    if (bodyByteLength > maxBodySize) {\n      const decoder = new TextDecoder();\n      truncatedBody = `${decoder.decode(bytes.slice(0, maxBodySize - 3))}...`;\n    } else {\n      truncatedBody = body;\n    }\n\n    isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: truncatedBody } });\n\n    DEBUG_BUILD && debug.log('Captured request body:', bodyByteLength, 'bytes');\n  } catch (error) {\n    DEBUG_BUILD && debug.error('Error capturing request body:', error);\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?: {\n    encrypted?: boolean;\n    remoteAddress?: string;\n  };\n}): RequestEventData {\n  const headers = request.headers || {};\n\n  // Check for x-forwarded-host first, then fall back to host header\n  const forwardedHost = typeof headers['x-forwarded-host'] === 'string' ? headers['x-forwarded-host'] : undefined;\n  const host = forwardedHost || (typeof headers.host === 'string' ? headers.host : undefined);\n\n  // Check for x-forwarded-proto first, then fall back to existing protocol detection\n  const forwardedProto = typeof headers['x-forwarded-proto'] === 'string' ? headers['x-forwarded-proto'] : undefined;\n  const protocol = forwardedProto || request.protocol || (request.socket?.encrypted ? 'https' : 'http');\n\n  const url = request.url || '';\n\n  const absoluteUrl = getAbsoluteUrl({\n    url,\n    host,\n    protocol,\n  });\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 {\n    url: absoluteUrl,\n    method: request.method,\n    query_string: extractQueryParamsFromUrl(url),\n    headers: headersToDict(headers),\n    cookies,\n    data,\n  };\n}\n\nfunction getAbsoluteUrl({\n  url,\n  protocol,\n  host,\n}: {\n  url?: string;\n  protocol: string;\n  host?: string;\n}): string | undefined {\n  if (url?.startsWith('http')) {\n    return url;\n  }\n\n  if (url && host) {\n    return `${protocol}://${host}${url}`;\n  }\n\n  return undefined;\n}\n\nconst SENSITIVE_HEADER_SNIPPETS = [\n  'auth',\n  'token',\n  'secret',\n  'session', // for the user_session cookie\n  'password',\n  'passwd',\n  'pwd',\n  'key',\n  'jwt',\n  'bearer',\n  'sso',\n  'saml',\n  'csrf',\n  'xsrf',\n  'credentials',\n  // Always treat cookie headers as sensitive in case individual key-value cookie pairs cannot properly be extracted\n  'set-cookie',\n  'cookie',\n];\n\n/**\n * Extra substrings matched only against individual Cookie / Set-Cookie **names** (not header names),\n * so we can cover common session secrets that do not match {@link SENSITIVE_HEADER_SNIPPETS}\n * (e.g. `connect.sid` does not contain `session`) without false positives on arbitrary HTTP headers.\n *\n * Cookie names are checked with the same `includes()` list as headers plus these entries; omit redundant\n * cookie-only snippets that are already implied by a header match (e.g. `oauth` → `auth`, `id_token` → `token`,\n * `next-auth` → `auth`).\n */\nconst SENSITIVE_COOKIE_NAME_SNIPPETS = [\n  // Express / Connect default session cookie\n  '.sid',\n  // Opaque session ids (PHPSESSID, ASPSESSIONID*, BIGipServer*, *sessid*, …)\n  'sessid',\n  // Laravel etc. \"remember me\" tokens\n  'remember',\n  // OIDC / OAuth auxiliary (`oauth*` covered by header snippet `auth`)\n  'oidc',\n  'pkce',\n  'nonce',\n  // RFC 6265bis high-security cookie name prefixes\n  '__secure-',\n  '__host-',\n  // Load balancer / CDN sticky-session cookies (opaque routing tokens)\n  'awsalb',\n  'awselb',\n  'akamai',\n  // BaaS / IdP session cookies (names often omit \"session\")\n  '__stripe',\n  'cognito',\n  'firebase',\n  'supabase',\n  'sb-',\n  // Step-up / MFA cookies\n  'mfa',\n  '2fa',\n];\n\nconst PII_HEADER_SNIPPETS = ['x-forwarded-', '-user'];\n\n/**\n * Converts incoming HTTP request or response headers to OpenTelemetry span attributes following semantic conventions.\n * Header names are converted to the format: http.<request|response>.header.<key>\n * where <key> is the header name in lowercase with dashes converted to underscores.\n *\n * @param lifecycle - The lifecycle of the headers, either 'request' or 'response'\n *\n * @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/#http-request-header\n * @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/#http-response-header\n *\n * @see https://getsentry.github.io/sentry-conventions/attributes/http/#http-request-header-key\n * @see https://getsentry.github.io/sentry-conventions/attributes/http/#http-response-header-key\n */\nexport function httpHeadersToSpanAttributes(\n  headers: Record<string, string | string[] | undefined>,\n  sendDefaultPii: boolean = false,\n  lifecycle: 'request' | 'response' = 'request',\n): Record<string, string> {\n  const spanAttributes: Record<string, string> = {};\n\n  try {\n    Object.entries(headers).forEach(([key, value]) => {\n      if (value == null) {\n        return;\n      }\n\n      const lowerCasedHeaderKey = key.toLowerCase();\n      const isCookieHeader = lowerCasedHeaderKey === 'cookie' || lowerCasedHeaderKey === 'set-cookie';\n\n      if (isCookieHeader && typeof value === 'string' && value !== '') {\n        // Set-Cookie: single cookie with attributes (\"name=value; HttpOnly; Secure\")\n        // Cookie: multiple cookies separated by \"; \" (\"cookie1=value1; cookie2=value2\")\n        const isSetCookie = lowerCasedHeaderKey === 'set-cookie';\n        const semicolonIndex = value.indexOf(';');\n        const cookieString = isSetCookie && semicolonIndex !== -1 ? value.substring(0, semicolonIndex) : value;\n        const cookies = isSetCookie ? [cookieString] : cookieString.split('; ');\n\n        for (const cookie of cookies) {\n          // Split only at the first '=' to preserve '=' characters in cookie values\n          const equalSignIndex = cookie.indexOf('=');\n          const cookieKey = equalSignIndex !== -1 ? cookie.substring(0, equalSignIndex) : cookie;\n          const cookieValue = equalSignIndex !== -1 ? cookie.substring(equalSignIndex + 1) : '';\n\n          const lowerCasedCookieKey = cookieKey.toLowerCase();\n\n          addSpanAttribute({\n            spanAttributes,\n            headerKey: lowerCasedHeaderKey,\n            cookieKey: lowerCasedCookieKey,\n            value: cookieValue,\n            sendDefaultPii,\n            lifecycle,\n          });\n        }\n      } else {\n        addSpanAttribute({\n          spanAttributes,\n          headerKey: lowerCasedHeaderKey,\n          value,\n          sendDefaultPii,\n          lifecycle,\n        });\n      }\n    });\n  } catch {\n    // Return empty object if there's an error\n  }\n\n  return spanAttributes;\n}\n\nfunction normalizeAttributeKey(key: string): string {\n  return key.replace(/-/g, '_');\n}\n\ntype AddSpanAttributeOptions = {\n  spanAttributes: Record<string, string>;\n  /** Lowercased HTTP header name (e.g. `cookie`, `set-cookie`, `accept`). */\n  headerKey: string;\n  /**\n   * Lowercased cookie name when this attribute comes from a parsed `Cookie` / `Set-Cookie` value.\n   * Omit for non-cookie headers; when present and non-empty, cookie-specific sensitivity rules apply.\n   */\n  cookieKey?: string;\n  value: string | string[] | undefined;\n  sendDefaultPii: boolean;\n  lifecycle: 'request' | 'response';\n};\n\nfunction addSpanAttribute({\n  spanAttributes,\n  headerKey,\n  cookieKey,\n  value,\n  sendDefaultPii,\n  lifecycle,\n}: AddSpanAttributeOptions): void {\n  const isCookieSubKey = Boolean(cookieKey);\n  const nameForSensitivity = cookieKey || headerKey;\n  const headerValue = handleHttpHeader(nameForSensitivity, value, sendDefaultPii, isCookieSubKey);\n  if (headerValue == null) {\n    return;\n  }\n\n  const normalizedKey = `http.${lifecycle}.header.${normalizeAttributeKey(headerKey)}${cookieKey ? `.${normalizeAttributeKey(cookieKey)}` : ''}`;\n  spanAttributes[normalizedKey] = headerValue;\n}\n\nfunction handleHttpHeader(\n  lowerCasedKey: string,\n  value: string | string[] | undefined,\n  sendPii: boolean,\n  isCookieSubKey: boolean = false,\n): string | undefined {\n  const snippetsForSensitivity = isCookieSubKey\n    ? [...SENSITIVE_HEADER_SNIPPETS, ...SENSITIVE_COOKIE_NAME_SNIPPETS]\n    : SENSITIVE_HEADER_SNIPPETS;\n\n  const isSensitive = sendPii\n    ? snippetsForSensitivity.some(snippet => lowerCasedKey.includes(snippet))\n    : [...PII_HEADER_SNIPPETS, ...snippetsForSensitivity].some(snippet => lowerCasedKey.includes(snippet));\n\n  if (isSensitive) {\n    return '[Filtered]';\n  } else if (Array.isArray(value)) {\n    return value.map(v => (v != null ? String(v) : v)).join(';');\n  } else if (typeof value === 'string') {\n    return value;\n  }\n\n  return undefined;\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://s.io').search.slice(1);\n    return queryParams.length ? queryParams : undefined;\n  } catch {\n    return undefined;\n  }\n}\n"],"names":["DEBUG_BUILD","debug","safeUnref"],"mappings":"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"}