UNPKG

@sentry/core

Version:
219 lines (215 loc) 9.48 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const currentScopes = require('../currentScopes.js'); const integration = require('../integration.js'); const semanticAttributes = require('../semanticAttributes.js'); const cookie = require('../utils/cookie.js'); const filteringSnippets = require('../utils/data-collection/filtering-snippets.js'); const filterKeyValueData = require('../utils/data-collection/filterKeyValueData.js'); const localhost = require('../utils/localhost.js'); const filterQueryParams = require('../utils/data-collection/filterQueryParams.js'); const filterUrlQuery = require('../utils/data-collection/filterUrlQuery.js'); const request = require('../utils/request.js'); const url = require('../utils/url.js'); const getIpAddress = require('../vendor/getIpAddress.js'); const captureSpan = require('../tracing/spans/captureSpan.js'); const attributes = require('@sentry/conventions/attributes'); const INTEGRATION_NAME = "RequestData"; const _requestDataIntegration = ((options = {}) => { function resolveRequestDataOptions(client) { const dataCollection = client.getDataCollectionOptions(); const include = { // oxlint-disable-next-line typescript/no-deprecated cookies: options.include?.cookies ?? dataCollection.cookies !== false, // Always attach body data that's already on the scope — dataCollection.httpBodies gates write-time, not read-time // oxlint-disable-next-line typescript/no-deprecated data: options.include?.data ?? true, // oxlint-disable-next-line typescript/no-deprecated headers: options.include?.headers ?? dataCollection.httpHeaders.request !== false, // oxlint-disable-next-line typescript/no-deprecated ip: options.include?.ip ?? dataCollection.userInfo, // oxlint-disable-next-line typescript/no-deprecated query_string: options.include?.query_string ?? dataCollection.urlQueryParams !== false, // No dataCollection equivalent — URL is always included // oxlint-disable-next-line typescript/no-deprecated url: options.include?.url ?? true }; return { include, dataCollection: { ...dataCollection, cookies: resolveFilteringBehavior(include.cookies, dataCollection.cookies), httpHeaders: { ...dataCollection.httpHeaders, request: resolveFilteringBehavior(include.headers, dataCollection.httpHeaders.request) }, urlQueryParams: resolveFilteringBehavior(include.query_string, dataCollection.urlQueryParams) } }; } return { name: INTEGRATION_NAME, processEvent(event, _hint, client) { const { sdkProcessingMetadata = {} } = event; const { normalizedRequest, ipAddress } = sdkProcessingMetadata; if (!normalizedRequest) { return event; } const { include, dataCollection } = resolveRequestDataOptions(client); addNormalizedRequestDataToEvent(event, normalizedRequest, { ipAddress }, include, dataCollection); return event; }, processSpan(span) { const { user, sdkProcessingMetadata } = currentScopes.getIsolationScope().getScopeData(); captureSpan.safeSetSpanJSONAttributes(span, { "sentry.is_localhost": isLocalhostSpan(sdkProcessingMetadata, user.ip_address) }); }, processSegmentSpan(span, client) { const { sdkProcessingMetadata = {} } = currentScopes.getIsolationScope().getScopeData(); const { normalizedRequest, ipAddress } = sdkProcessingMetadata; if (!normalizedRequest) { return; } const { include, dataCollection } = resolveRequestDataOptions(client); addNormalizedRequestDataToSpan(span, normalizedRequest, ipAddress, include, dataCollection); } }; }); const localhostByRequest = /* @__PURE__ */ new WeakMap(); function isLocalhostSpan(sdkProcessingMetadata, scopeUserIpAddress) { const { normalizedRequest, ipAddress } = sdkProcessingMetadata; if (!normalizedRequest) { return localhost.isLocalhostRequest(void 0, ipAddress || scopeUserIpAddress); } const cached = localhostByRequest.get(normalizedRequest); if (cached !== void 0) { return cached; } const headers = normalizedRequest.headers; const clientIpAddress = headers && getIpAddress.getClientIPAddress(headers) || ipAddress || scopeUserIpAddress; const isLocalhost = localhost.isLocalhostRequest(normalizedRequest, clientIpAddress); localhostByRequest.set(normalizedRequest, isLocalhost); return isLocalhost; } const requestDataIntegration = integration.defineIntegration(_requestDataIntegration); function addNormalizedRequestDataToEvent(event, req, additionalData, include, dataCollection) { const requestData = extractNormalizedRequestData(req, include); if (requestData.cookies) { requestData.cookies = filterKeyValueData.filterKeyValueData( requestData.cookies, dataCollection.cookies, filteringSnippets.SENSITIVE_COOKIE_NAME_SNIPPETS ); } if (requestData.headers) { requestData.headers = filterKeyValueData.filterKeyValueData(requestData.headers, dataCollection.httpHeaders.request); } if (requestData.query_string) { requestData.query_string = normalizeAndFilterQueryString(requestData.query_string, dataCollection.urlQueryParams); } if (requestData.url) { requestData.url = filterUrlQuery.filterUrlQuery(requestData.url, dataCollection.urlQueryParams); } event.request = { ...event.request, ...requestData }; if (include.ip) { const ip = req.headers && getIpAddress.getClientIPAddress(req.headers) || additionalData.ipAddress; if (ip) { event.user = { ...event.user, ip_address: ip }; } } } function addNormalizedRequestDataToSpan(span, normalizedRequest, ipAddress, include, dataCollection) { const requestData = extractNormalizedRequestData(normalizedRequest, include); const attributes$1 = {}; if (requestData.url) { attributes$1[attributes.URL_FULL] = filterUrlQuery.filterUrlQuery(requestData.url, dataCollection.urlQueryParams); } if (requestData.method) { attributes$1["http.request.method"] = requestData.method; } if (requestData.query_string) { attributes$1[attributes.URL_QUERY] = normalizeAndFilterQueryString(requestData.query_string, dataCollection.urlQueryParams); } captureSpan.safeSetSpanJSONAttributes(span, attributes$1); if (include.cookies) { const cookieHeader = normalizedRequest.headers?.cookie; const cookiePairs = normalizedRequest.cookies ? Object.entries(normalizedRequest.cookies) : cookieHeader ? cookie.parseCookieHeader(cookieHeader, "cookie") : []; if (cookiePairs.length > 0) { captureSpan.safeSetSpanJSONAttributes(span, { "http.request.header.cookie": request.filterCookiePairs(cookiePairs, dataCollection.cookies) }); } } if (requestData.headers) { const headerAttributes = request.httpHeadersToSpanAttributes(requestData.headers, dataCollection, "request"); captureSpan.safeSetSpanJSONAttributes(span, headerAttributes); } if (requestData.data != null) { const serialized = typeof requestData.data === "string" ? requestData.data : JSON.stringify(requestData.data); if (serialized) { captureSpan.safeSetSpanJSONAttributes(span, { "http.request.body.data": serialized }); } } if (include.ip) { const ip = normalizedRequest.headers && getIpAddress.getClientIPAddress(normalizedRequest.headers) || ipAddress || void 0; if (ip) { captureSpan.safeSetSpanJSONAttributes(span, { [semanticAttributes.SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: ip }); } } } function extractNormalizedRequestData(normalizedRequest, include) { const requestData = {}; const headers = { ...normalizedRequest.headers }; if (include.headers) { requestData.headers = headers; if (!include.cookies) { delete headers.cookie; } if (!include.ip) { const ipHeaderNamesLower = new Set(getIpAddress.ipHeaderNames.map((name) => name.toLowerCase())); for (const key of Object.keys(headers)) { if (ipHeaderNamesLower.has(key.toLowerCase())) { delete headers[key]; } } } } requestData.method = normalizedRequest.method; if (include.url) { requestData.url = normalizedRequest.url; } if (include.cookies) { const cookies = normalizedRequest.cookies || (headers?.cookie ? cookie.cookiePairsToRecord(cookie.parseCookieHeader(headers.cookie, "cookie")) : void 0); requestData.cookies = cookies || {}; } if (include.query_string) { requestData.query_string = normalizedRequest.query_string; } if (include.data) { requestData.data = normalizedRequest.data; } return requestData; } function resolveFilteringBehavior(isIncluded, behavior) { return isIncluded && behavior === false ? true : behavior; } function normalizeAndFilterQueryString(queryString, behavior) { const normalized = normalizeQueryString(queryString); return normalized ? filterQueryParams.filterQueryParams(normalized, behavior) : void 0; } function normalizeQueryString(queryString) { if (typeof queryString === "string") { return url.getUrlQuery(queryString); } const pairs = Array.isArray(queryString) ? queryString : Object.entries(queryString); const normalized = new URLSearchParams(pairs).toString(); return normalized || void 0; } exports.requestDataIntegration = requestDataIntegration; //# sourceMappingURL=requestdata.js.map