Skip to content

Commit f7257a1

Browse files
authored
ref: Hoist RequestData integration to @sentry/core (#9597)
1 parent f251833 commit f7257a1

File tree

13 files changed

+168
-449
lines changed

13 files changed

+168
-449
lines changed

packages/core/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export type { ClientClass } from './sdk';
22
export type { AsyncContextStrategy, Carrier, Layer, RunWithAsyncContextOptions } from './hub';
33
export type { OfflineStore, OfflineTransportOptions } from './transports/offline';
44
export type { ServerRuntimeClientOptions } from './server-runtime-client';
5+
export type { RequestDataIntegrationOptions } from './integrations/requestdata';
56

67
export * from './tracing';
78
export { createEventEnvelope } from './envelope';
@@ -56,6 +57,7 @@ export { hasTracingEnabled } from './utils/hasTracingEnabled';
5657
export { isSentryRequestUrl } from './utils/isSentryRequestUrl';
5758
export { DEFAULT_ENVIRONMENT } from './constants';
5859
export { ModuleMetadata } from './integrations/metadata';
60+
export { RequestData } from './integrations/requestdata';
5961
import * as Integrations from './integrations';
6062

6163
export { Integrations };

packages/node/src/integrations/requestdata.ts renamed to packages/core/src/integrations/requestdata.ts

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
// TODO (v8 or v9): Whenever this becomes a default integration for `@sentry/browser`, move this to `@sentry/core`. For
2-
// now, we leave it in `@sentry/integrations` so that it doesn't contribute bytes to our CDN bundles.
3-
41
import type { Event, EventProcessor, Hub, Integration, PolymorphicRequest, Transaction } from '@sentry/types';
5-
import { extractPathForTransaction } from '@sentry/utils';
6-
7-
import type { AddRequestDataToEventOptions, TransactionNamingScheme } from '../requestdata';
8-
import { addRequestDataToEvent } from '../requestdata';
2+
import type { AddRequestDataToEventOptions, TransactionNamingScheme } from '@sentry/utils';
3+
import { addRequestDataToEvent, extractPathForTransaction } from '@sentry/utils';
94

105
export type RequestDataIntegrationOptions = {
116
/**
@@ -59,7 +54,7 @@ export class RequestData implements Integration {
5954
/**
6055
* @inheritDoc
6156
*/
62-
public name: string = RequestData.id;
57+
public name: string;
6358

6459
/**
6560
* Function for adding request data to event. Defaults to `addRequestDataToEvent` from `@sentry/node` for now, but
@@ -74,6 +69,7 @@ export class RequestData implements Integration {
7469
* @inheritDoc
7570
*/
7671
public constructor(options: RequestDataIntegrationOptions = {}) {
72+
this.name = RequestData.id;
7773
this._addRequestData = addRequestDataToEvent;
7874
this._options = {
7975
...DEFAULT_OPTIONS,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import type { RequestDataIntegrationOptions } from '@sentry/core';
2+
import { getCurrentHub, Hub, makeMain, RequestData } from '@sentry/core';
3+
import type { Event, EventProcessor } from '@sentry/types';
4+
import * as sentryUtils from '@sentry/utils';
5+
import type { IncomingMessage } from 'http';
6+
7+
import { getDefaultTestClientOptions, TestClient } from '../../mocks/client';
8+
9+
const addRequestDataToEventSpy = jest.spyOn(sentryUtils, 'addRequestDataToEvent');
10+
const requestDataEventProcessor = jest.fn();
11+
12+
const headers = { ears: 'furry', nose: 'wet', tongue: 'spotted', cookie: 'favorite=zukes' };
13+
const method = 'wagging';
14+
const protocol = 'mutualsniffing';
15+
const hostname = 'the.dog.park';
16+
const path = '/by/the/trees/';
17+
const queryString = 'chase=me&please=thankyou';
18+
19+
function initWithRequestDataIntegrationOptions(integrationOptions: RequestDataIntegrationOptions): void {
20+
const setMockEventProcessor = (eventProcessor: EventProcessor) =>
21+
requestDataEventProcessor.mockImplementationOnce(eventProcessor);
22+
23+
const requestDataIntegration = new RequestData({
24+
...integrationOptions,
25+
});
26+
27+
const client = new TestClient(
28+
getDefaultTestClientOptions({
29+
dsn: 'https://[email protected]/12312012',
30+
integrations: [requestDataIntegration],
31+
}),
32+
);
33+
client.setupIntegrations = () => requestDataIntegration.setupOnce(setMockEventProcessor, getCurrentHub);
34+
client.getIntegration = () => requestDataIntegration as any;
35+
36+
const hub = new Hub(client);
37+
38+
makeMain(hub);
39+
}
40+
41+
describe('`RequestData` integration', () => {
42+
let req: IncomingMessage, event: Event;
43+
44+
beforeEach(() => {
45+
req = {
46+
headers,
47+
method,
48+
protocol,
49+
hostname,
50+
originalUrl: `${path}?${queryString}`,
51+
} as unknown as IncomingMessage;
52+
event = { sdkProcessingMetadata: { request: req } };
53+
});
54+
55+
afterEach(() => {
56+
jest.clearAllMocks();
57+
});
58+
59+
describe('option conversion', () => {
60+
it('leaves `ip` and `user` at top level of `include`', () => {
61+
initWithRequestDataIntegrationOptions({ include: { ip: false, user: true } });
62+
63+
requestDataEventProcessor(event);
64+
65+
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2];
66+
67+
expect(passedOptions?.include).toEqual(expect.objectContaining({ ip: false, user: true }));
68+
});
69+
70+
it('moves `transactionNamingScheme` to `transaction` include', () => {
71+
initWithRequestDataIntegrationOptions({ transactionNamingScheme: 'path' });
72+
73+
requestDataEventProcessor(event);
74+
75+
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2];
76+
77+
expect(passedOptions?.include).toEqual(expect.objectContaining({ transaction: 'path' }));
78+
});
79+
80+
it('moves `true` request keys into `request` include, but omits `false` ones', async () => {
81+
initWithRequestDataIntegrationOptions({ include: { data: true, cookies: false } });
82+
83+
requestDataEventProcessor(event);
84+
85+
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2];
86+
87+
expect(passedOptions?.include?.request).toEqual(expect.arrayContaining(['data']));
88+
expect(passedOptions?.include?.request).not.toEqual(expect.arrayContaining(['cookies']));
89+
});
90+
91+
it('moves `true` user keys into `user` include, but omits `false` ones', async () => {
92+
initWithRequestDataIntegrationOptions({ include: { user: { id: true, email: false } } });
93+
94+
requestDataEventProcessor(event);
95+
96+
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2];
97+
98+
expect(passedOptions?.include?.user).toEqual(expect.arrayContaining(['id']));
99+
expect(passedOptions?.include?.user).not.toEqual(expect.arrayContaining(['email']));
100+
});
101+
});
102+
});

packages/node/src/handlers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
addRequestDataToTransaction,
1616
dropUndefinedKeys,
1717
extractPathForTransaction,
18+
extractRequestData,
1819
isString,
1920
isThenable,
2021
logger,
@@ -23,7 +24,6 @@ import {
2324
import type * as http from 'http';
2425

2526
import type { NodeClient } from './client';
26-
import { extractRequestData } from './requestdata';
2727
// TODO (v8 / XXX) Remove this import
2828
import type { ParseRequestOptions } from './requestDataDeprecated';
2929
import { isAutoSessionTrackingEnabled } from './sdk';

packages/node/src/index.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ export type {
1818
Transaction,
1919
User,
2020
} from '@sentry/types';
21-
export type { AddRequestDataToEventOptions } from '@sentry/utils';
21+
export type { AddRequestDataToEventOptions, TransactionNamingScheme } from '@sentry/utils';
2222

23-
export type { TransactionNamingScheme } from './requestdata';
2423
export type { NodeOptions } from './types';
2524

2625
export {
@@ -72,7 +71,7 @@ export { autoDiscoverNodePerformanceMonitoringIntegrations } from './tracing';
7271
export { NodeClient } from './client';
7372
export { makeNodeTransport } from './transports';
7473
export { defaultIntegrations, init, defaultStackParser, getSentryRelease } from './sdk';
75-
export { addRequestDataToEvent, DEFAULT_USER_INCLUDES, extractRequestData } from './requestdata';
74+
export { addRequestDataToEvent, DEFAULT_USER_INCLUDES, extractRequestData } from '@sentry/utils';
7675
export { deepReadDirSync } from './utils';
7776
export { getModuleFromFilename } from './module';
7877
export { enableAnrDetection } from './anr';

packages/node/src/integrations/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ export { OnUnhandledRejection } from './onunhandledrejection';
55
export { Modules } from './modules';
66
export { ContextLines } from './contextlines';
77
export { Context } from './context';
8-
export { RequestData } from './requestdata';
8+
export { RequestData } from '@sentry/core';
99
export { LocalVariables } from './localvariables';
1010
export { Undici } from './undici';

packages/node/src/requestDataDeprecated.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
/* eslint-disable deprecation/deprecation */
88
/* eslint-disable @typescript-eslint/no-explicit-any */
99
import type { Event, ExtractedNodeRequestData, PolymorphicRequest } from '@sentry/types';
10-
11-
import type { AddRequestDataToEventOptions } from './requestdata';
12-
import { addRequestDataToEvent, extractRequestData as _extractRequestData } from './requestdata';
10+
import type { AddRequestDataToEventOptions } from '@sentry/utils';
11+
import { addRequestDataToEvent, extractRequestData as _extractRequestData } from '@sentry/utils';
1312

1413
/**
1514
* @deprecated `Handlers.ExpressRequest` is deprecated and will be removed in v8. Use `PolymorphicRequest` instead.

0 commit comments

Comments
 (0)