Skip to content

Commit 46ac778

Browse files
authored
feat(core)!: Update requestDataIntegration handling (#14806)
This PR cleans up the behavior of `requestDataIntegration`. For this, there are a bunch of parts that come together: 1. Removed the `addNormalizedRequestDataToEvent` export, this does not really do much, you can just directly add the data to the event. 2. Removed the `RequestDataIntegrationOptions` type 3. Stops setting `request` on SDK processing metadata, now only relying on `normalizedRequest` 4. Streamlined code related to this, taking it out of `utils-hoist`. Now, all the code related directly to the requestDataIntegration is in that file, while the more general utils are in core/src/utils/request.ts 5. Also moved the cookie & getClientIpAddress utils out of utils-hoist 6. Added tests for the request utils, we did not have any unit tests there... 7. Streamlined the header extraction to avoid debug logs and simply try-catch there normally 8. Streamlined the request extraction to avoid weird urls if no host is found. Closes #14297
1 parent c612915 commit 46ac778

File tree

18 files changed

+456
-407
lines changed

18 files changed

+456
-407
lines changed

Diff for: docs/migration/v8-to-v9.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ Sentry.init({
173173
- The `getDomElement` method has been removed. There is no replacement.
174174
- The `memoBuilder` method has been removed. There is no replacement.
175175
- The `extractRequestData` method has been removed. Manually extract relevant data off request instead.
176-
- The `addRequestDataToEvent` method has been removed. Use `addNormalizedRequestDataToEvent` instead.
176+
- The `addRequestDataToEvent` method has been removed. Use `httpRequestToRequestData` instead and put the resulting object directly on `event.request`.
177177
- The `extractPathForTransaction` method has been removed. There is no replacement.
178+
- The `addNormalizedRequestDataToEvent` method has been removed. Use `httpRequestToRequestData` instead and put the resulting object directly on `event.request`.
178179

179180
#### Other/Internal Changes
180181

@@ -254,6 +255,7 @@ Since v9, the types have been merged into `@sentry/core`, which removed some of
254255
- The `samplingContext.request` attribute in the `tracesSampler` has been removed. Use `samplingContext.normalizedRequest` instead. Note that the type of `normalizedRequest` differs from `request`.
255256
- `Client` now always expects the `BaseClient` class - there is no more abstract `Client` that can be implemented! Any `Client` class has to extend from `BaseClient`.
256257
- `ReportDialogOptions` now extends `Record<string, unknown>` instead of `Record<string, any>` - this should not affect most users.
258+
- The `RequestDataIntegrationOptions` type has been removed. There is no replacement.
257259

258260
# No Version Support Timeline
259261

@@ -307,7 +309,7 @@ The Sentry metrics beta has ended and the metrics API has been removed from the
307309
- Deprecated `TransactionNamingScheme` type.
308310
- Deprecated `validSeverityLevels`. Will not be replaced.
309311
- Deprecated `urlEncode`. No replacements.
310-
- Deprecated `addRequestDataToEvent`. Use `addNormalizedRequestDataToEvent` instead.
312+
- Deprecated `addRequestDataToEvent`. Use `httpRequestToRequestData` instead and put the resulting object directly on `event.request`.
311313
- Deprecated `extractRequestData`. Instead manually extract relevant data off request.
312314
- Deprecated `arrayify`. No replacements.
313315
- Deprecated `memoBuilder`. No replacements.

Diff for: packages/bun/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export type {
1616
Thread,
1717
User,
1818
} from '@sentry/core';
19-
export type { AddRequestDataToEventOptions } from '@sentry/core';
2019

2120
export {
2221
addEventProcessor,

Diff for: packages/cloudflare/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export type {
1616
Thread,
1717
User,
1818
} from '@sentry/core';
19-
export type { AddRequestDataToEventOptions } from '@sentry/core';
2019

2120
export type { CloudflareOptions } from './client';
2221

Diff for: packages/core/src/index.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ export type { AsyncContextStrategy } from './asyncContext/types';
33
export type { Carrier } from './carrier';
44
export type { OfflineStore, OfflineTransportOptions } from './transports/offline';
55
export type { ServerRuntimeClientOptions } from './server-runtime-client';
6-
export type { RequestDataIntegrationOptions } from './integrations/requestdata';
76
export type { IntegrationIndex } from './integration';
87

98
export * from './tracing';
@@ -90,6 +89,13 @@ export { parseSampleRate } from './utils/parseSampleRate';
9089
export { applySdkMetadata } from './utils/sdkMetadata';
9190
export { getTraceData } from './utils/traceData';
9291
export { getTraceMetaTags } from './utils/meta';
92+
export {
93+
winterCGHeadersToDict,
94+
winterCGRequestToRequestData,
95+
httpRequestToRequestData,
96+
extractQueryParamsFromUrl,
97+
headersToDict,
98+
} from './utils/request';
9399
export { DEFAULT_ENVIRONMENT } from './constants';
94100
export { addBreadcrumb } from './breadcrumbs';
95101
export { functionToStringIntegration } from './integrations/functiontostring';

Diff for: packages/core/src/integrations/requestdata.ts

+94-57
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,49 @@
11
import { defineIntegration } from '../integration';
2-
import type { IntegrationFn } from '../types-hoist';
3-
import { type AddRequestDataToEventOptions, addNormalizedRequestDataToEvent } from '../utils-hoist/requestdata';
2+
import type { Event, IntegrationFn, RequestEventData } from '../types-hoist';
3+
import { parseCookie } from '../utils/cookie';
4+
import { getClientIPAddress, ipHeaderNames } from '../vendor/getIpAddress';
45

5-
export type RequestDataIntegrationOptions = {
6+
interface RequestDataIncludeOptions {
7+
cookies?: boolean;
8+
data?: boolean;
9+
headers?: boolean;
10+
ip?: boolean;
11+
query_string?: boolean;
12+
url?: boolean;
13+
}
14+
15+
type RequestDataIntegrationOptions = {
616
/**
7-
* Controls what data is pulled from the request and added to the event
17+
* Controls what data is pulled from the request and added to the event.
818
*/
9-
include?: {
10-
cookies?: boolean;
11-
data?: boolean;
12-
headers?: boolean;
13-
ip?: boolean;
14-
query_string?: boolean;
15-
url?: boolean;
16-
};
19+
include?: RequestDataIncludeOptions;
1720
};
1821

19-
const DEFAULT_OPTIONS = {
20-
include: {
21-
cookies: true,
22-
data: true,
23-
headers: true,
24-
ip: false,
25-
query_string: true,
26-
url: true,
27-
},
28-
transactionNamingScheme: 'methodPath' as const,
22+
const DEFAULT_INCLUDE: RequestDataIncludeOptions = {
23+
cookies: true,
24+
data: true,
25+
headers: true,
26+
ip: false,
27+
query_string: true,
28+
url: true,
2929
};
3030

3131
const INTEGRATION_NAME = 'RequestData';
3232

3333
const _requestDataIntegration = ((options: RequestDataIntegrationOptions = {}) => {
34-
const _options: Required<RequestDataIntegrationOptions> = {
35-
...DEFAULT_OPTIONS,
36-
...options,
37-
include: {
38-
...DEFAULT_OPTIONS.include,
39-
...options.include,
40-
},
34+
const include = {
35+
...DEFAULT_INCLUDE,
36+
...options.include,
4137
};
4238

4339
return {
4440
name: INTEGRATION_NAME,
4541
processEvent(event) {
46-
// Note: In the long run, most of the logic here should probably move into the request data utility functions. For
47-
// the moment it lives here, though, until https://github.com/getsentry/sentry-javascript/issues/5718 is addressed.
48-
// (TL;DR: Those functions touch many parts of the repo in many different ways, and need to be cleaned up. Once
49-
// that's happened, it will be easier to add this logic in without worrying about unexpected side effects.)
50-
5142
const { sdkProcessingMetadata = {} } = event;
5243
const { normalizedRequest, ipAddress } = sdkProcessingMetadata;
5344

54-
const addRequestDataOptions = convertReqDataIntegrationOptsToAddReqDataOpts(_options);
55-
5645
if (normalizedRequest) {
57-
addNormalizedRequestDataToEvent(event, normalizedRequest, { ipAddress }, addRequestDataOptions);
58-
return event;
46+
addNormalizedRequestDataToEvent(event, normalizedRequest, { ipAddress }, include);
5947
}
6048

6149
return event;
@@ -69,26 +57,75 @@ const _requestDataIntegration = ((options: RequestDataIntegrationOptions = {}) =
6957
*/
7058
export const requestDataIntegration = defineIntegration(_requestDataIntegration);
7159

72-
/** Convert this integration's options to match what `addRequestDataToEvent` expects */
73-
/** TODO: Can possibly be deleted once https://github.com/getsentry/sentry-javascript/issues/5718 is fixed */
74-
function convertReqDataIntegrationOptsToAddReqDataOpts(
75-
integrationOptions: Required<RequestDataIntegrationOptions>,
76-
): AddRequestDataToEventOptions {
77-
const {
78-
include: { ip, ...requestOptions },
79-
} = integrationOptions;
80-
81-
const requestIncludeKeys: string[] = ['method'];
82-
for (const [key, value] of Object.entries(requestOptions)) {
83-
if (value) {
84-
requestIncludeKeys.push(key);
60+
/**
61+
* Add already normalized request data to an event.
62+
* This mutates the passed in event.
63+
*/
64+
function addNormalizedRequestDataToEvent(
65+
event: Event,
66+
req: RequestEventData,
67+
// Data that should not go into `event.request` but is somehow related to requests
68+
additionalData: { ipAddress?: string },
69+
include: RequestDataIncludeOptions,
70+
): void {
71+
event.request = {
72+
...event.request,
73+
...extractNormalizedRequestData(req, include),
74+
};
75+
76+
if (include.ip) {
77+
const ip = (req.headers && getClientIPAddress(req.headers)) || additionalData.ipAddress;
78+
if (ip) {
79+
event.user = {
80+
...event.user,
81+
ip_address: ip,
82+
};
8583
}
8684
}
85+
}
8786

88-
return {
89-
include: {
90-
ip,
91-
request: requestIncludeKeys.length !== 0 ? requestIncludeKeys : undefined,
92-
},
93-
};
87+
function extractNormalizedRequestData(
88+
normalizedRequest: RequestEventData,
89+
include: RequestDataIncludeOptions,
90+
): RequestEventData {
91+
const requestData: RequestEventData = {};
92+
const headers = { ...normalizedRequest.headers };
93+
94+
if (include.headers) {
95+
requestData.headers = headers;
96+
97+
// Remove the Cookie header in case cookie data should not be included in the event
98+
if (!include.cookies) {
99+
delete (headers as { cookie?: string }).cookie;
100+
}
101+
102+
// Remove IP headers in case IP data should not be included in the event
103+
if (!include.ip) {
104+
ipHeaderNames.forEach(ipHeaderName => {
105+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
106+
delete (headers as Record<string, unknown>)[ipHeaderName];
107+
});
108+
}
109+
}
110+
111+
requestData.method = normalizedRequest.method;
112+
113+
if (include.url) {
114+
requestData.url = normalizedRequest.url;
115+
}
116+
117+
if (include.cookies) {
118+
const cookies = normalizedRequest.cookies || (headers?.cookie ? parseCookie(headers.cookie) : undefined);
119+
requestData.cookies = cookies || {};
120+
}
121+
122+
if (include.query_string) {
123+
requestData.query_string = normalizedRequest.query_string;
124+
}
125+
126+
if (include.data) {
127+
requestData.data = normalizedRequest.data;
128+
}
129+
130+
return requestData;
94131
}

Diff for: packages/core/src/scope.ts

-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {
1212
EventProcessor,
1313
Extra,
1414
Extras,
15-
PolymorphicRequest,
1615
Primitive,
1716
PropagationContext,
1817
RequestEventData,
@@ -60,7 +59,6 @@ export interface SdkProcessingMetadata {
6059
requestSession?: {
6160
status: 'ok' | 'errored' | 'crashed';
6261
};
63-
request?: PolymorphicRequest;
6462
normalizedRequest?: RequestEventData;
6563
dynamicSamplingContext?: Partial<DynamicSamplingContext>;
6664
capturedSpanScope?: Scope;

Diff for: packages/core/src/utils-hoist/index.ts

-11
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,6 @@ export { basename, dirname, isAbsolute, join, normalizePath, relative, resolve }
6464
export { makePromiseBuffer } from './promisebuffer';
6565
export type { PromiseBuffer } from './promisebuffer';
6666

67-
// TODO: Remove requestdata export once equivalent integration is used everywhere
68-
export {
69-
addNormalizedRequestDataToEvent,
70-
winterCGHeadersToDict,
71-
winterCGRequestToRequestData,
72-
httpRequestToRequestData,
73-
extractQueryParamsFromUrl,
74-
headersToDict,
75-
} from './requestdata';
76-
export type { AddRequestDataToEventOptions } from './requestdata';
77-
7867
export { severityLevelFromString } from './severity';
7968
export {
8069
UNKNOWN_FUNCTION,

0 commit comments

Comments
 (0)