Skip to content

Commit e46b6eb

Browse files
committed
ref: Move httpRequestToRequestData to core, avoiding HTTP dependency
1 parent d3cbe40 commit e46b6eb

File tree

9 files changed

+56
-52
lines changed

9 files changed

+56
-52
lines changed

dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const NODE_EXPORTS_IGNORE = [
2121
'SentryContextManager',
2222
'validateOpenTelemetrySetup',
2323
'preloadOpenTelemetry',
24-
'httpRequestToRequestEventData',
2524
];
2625

2726
const nodeExports = Object.keys(SentryNode).filter(e => !NODE_EXPORTS_IGNORE.includes(e));

packages/core/src/utils-hoist/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export {
7373
extractRequestData,
7474
winterCGHeadersToDict,
7575
winterCGRequestToRequestData,
76+
httpRequestToRequestData,
7677
extractQueryParamsFromUrl,
7778
headersToDict,
7879
} from './requestdata';

packages/core/src/utils-hoist/requestdata.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { DEBUG_BUILD } from './debug-build';
1414
import { isPlainObject, isString } from './is';
1515
import { logger } from './logger';
1616
import { normalize } from './normalize';
17+
import { dropUndefinedKeys } from './object';
1718
import { truncate } from './string';
1819
import { stripUrlQueryAndFragment } from './url';
1920
import { getClientIPAddress, ipHeaderNames } from './vendor/getIpAddress';
@@ -451,6 +452,43 @@ export function winterCGRequestToRequestData(req: WebFetchRequest): RequestEvent
451452
};
452453
}
453454

455+
/**
456+
* Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.
457+
* Instead of allowing `PolymorphicRequest` to be passed,
458+
* we want to be more specific and generally require a http.IncomingMessage-like object.
459+
*/
460+
export function httpRequestToRequestData(request: {
461+
method?: string;
462+
url?: string;
463+
headers?: {
464+
[key: string]: string | string[] | undefined;
465+
};
466+
protocol?: string;
467+
socket?: unknown;
468+
}): RequestEventData {
469+
const headers = request.headers || {};
470+
const host = headers.host || '<no host>';
471+
const protocol = request.socket && (request.socket as { encrypted?: boolean }).encrypted ? 'https' : 'http';
472+
const originalUrl = request.url || '';
473+
const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;
474+
475+
// This is non-standard, but may be sometimes set
476+
// It may be overwritten later by our own body handling
477+
const data = (request as PolymorphicRequest).body;
478+
479+
// This is non-standard, but may be set on e.g. Next.js or Express requests
480+
const cookies = (request as PolymorphicRequest).cookies;
481+
482+
return dropUndefinedKeys({
483+
url: absoluteUrl,
484+
method: request.method,
485+
query_string: extractQueryParamsFromUrl(originalUrl),
486+
headers: headersToDict(headers),
487+
cookies,
488+
data,
489+
});
490+
}
491+
454492
/** Extract the query params from an URL. */
455493
export function extractQueryParamsFromUrl(url: string): string | undefined {
456494
// url is path and query string

packages/google-cloud-serverless/src/gcpfunction/http.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,13 @@ import {
22
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
33
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
44
handleCallbackErrors,
5+
httpRequestToRequestData,
56
isString,
67
logger,
78
setHttpStatus,
89
stripUrlQueryAndFragment,
910
} from '@sentry/core';
10-
import {
11-
captureException,
12-
continueTrace,
13-
flush,
14-
getCurrentScope,
15-
httpRequestToRequestEventData,
16-
startSpanManual,
17-
} from '@sentry/node';
11+
import { captureException, continueTrace, flush, getCurrentScope, startSpanManual } from '@sentry/node';
1812
import { DEBUG_BUILD } from '../debug-build';
1913
import { domainify, markEventUnhandled, proxyFunction } from '../utils';
2014
import type { HttpFunction, WrapperOptions } from './general';
@@ -52,7 +46,7 @@ function _wrapHttpFunction(fn: HttpFunction, options: Partial<WrapperOptions>):
5246
const baggage = req.headers?.baggage;
5347

5448
return continueTrace({ sentryTrace, baggage }, () => {
55-
const normalizedRequest = httpRequestToRequestEventData(req);
49+
const normalizedRequest = httpRequestToRequestData(req);
5650
getCurrentScope().setSDKProcessingMetadata({ normalizedRequest });
5751

5852
return startSpanManual(

packages/nextjs/src/common/pages-router-instrumentation/_error.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { captureException, withScope } from '@sentry/core';
1+
import { captureException, httpRequestToRequestData, withScope } from '@sentry/core';
22
import { vercelWaitUntil } from '@sentry/core';
3-
import { httpRequestToRequestEventData } from '@sentry/node';
43
import type { NextPageContext } from 'next';
54
import { flushSafelyWithTimeout } from '../utils/responseEnd';
65

@@ -39,7 +38,7 @@ export async function captureUnderscoreErrorException(contextOrProps: ContextOrP
3938

4039
withScope(scope => {
4140
if (req) {
42-
const normalizedRequest = httpRequestToRequestEventData(req);
41+
const normalizedRequest = httpRequestToRequestData(req);
4342
scope.setSDKProcessingMetadata({ normalizedRequest });
4443
}
4544

packages/nextjs/src/common/pages-router-instrumentation/wrapApiHandlerWithSentry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import {
33
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
44
captureException,
55
continueTrace,
6+
httpRequestToRequestData,
67
setHttpStatus,
78
startSpanManual,
89
withIsolationScope,
910
} from '@sentry/core';
1011
import { isString, logger, objectify } from '@sentry/core';
1112

1213
import { vercelWaitUntil } from '@sentry/core';
13-
import { httpRequestToRequestEventData } from '@sentry/node';
1414
import type { NextApiRequest } from 'next';
1515
import type { AugmentedNextApiResponse, NextApiHandler } from '../types';
1616
import { flushSafelyWithTimeout } from '../utils/responseEnd';
@@ -66,7 +66,7 @@ export function wrapApiHandlerWithSentry(apiHandler: NextApiHandler, parameteriz
6666
},
6767
() => {
6868
const reqMethod = `${(req.method || 'GET').toUpperCase()} `;
69-
const normalizedRequest = httpRequestToRequestEventData(req);
69+
const normalizedRequest = httpRequestToRequestData(req);
7070

7171
isolationScope.setSDKProcessingMetadata({ normalizedRequest });
7272
isolationScope.setTransactionName(`${reqMethod}${parameterizedRoute}`);

packages/nextjs/src/common/utils/wrapperUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
getIsolationScope,
77
getRootSpan,
88
getTraceData,
9+
httpRequestToRequestData,
910
} from '@sentry/core';
10-
import { httpRequestToRequestEventData } from '@sentry/node';
1111
import { TRANSACTION_ATTR_SENTRY_ROUTE_BACKFILL } from '../span-attributes-with-logic-attached';
1212

1313
/**
@@ -62,7 +62,7 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
6262
this: unknown,
6363
...args: Parameters<F>
6464
): Promise<{ data: ReturnType<F>; sentryTrace?: string; baggage?: string }> {
65-
const normalizedRequest = httpRequestToRequestEventData(req);
65+
const normalizedRequest = httpRequestToRequestData(req);
6666
getCurrentScope().setTransactionName(`${options.dataFetchingMethodName} (${options.dataFetcherRouteName})`);
6767
getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });
6868

packages/node/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export { httpIntegration } from './integrations/http';
2-
export { httpRequestToRequestEventData } from './integrations/http/SentryHttpInstrumentation';
32
export { nativeNodeFetchIntegration } from './integrations/node-fetch';
43
export { fsIntegration } from './integrations/fs';
54

packages/node/src/integrations/http/SentryHttpInstrumentation.ts

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ import { VERSION } from '@opentelemetry/core';
55
import type { InstrumentationConfig } from '@opentelemetry/instrumentation';
66
import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
77
import { getRequestInfo } from '@opentelemetry/instrumentation-http';
8-
import { addBreadcrumb, dropUndefinedKeys, getClient, getIsolationScope, withIsolationScope } from '@sentry/core';
98
import {
10-
extractQueryParamsFromUrl,
9+
addBreadcrumb,
1110
getBreadcrumbLogLevelFromHttpStatusCode,
11+
getClient,
12+
getIsolationScope,
1213
getSanitizedUrlString,
13-
headersToDict,
14+
httpRequestToRequestData,
1415
logger,
1516
parseUrl,
1617
stripUrlQueryAndFragment,
18+
withIsolationScope,
1719
} from '@sentry/core';
18-
import type { PolymorphicRequest, RequestEventData, SanitizedRequestData, Scope } from '@sentry/types';
20+
import type { RequestEventData, SanitizedRequestData, Scope } from '@sentry/types';
1921
import { DEBUG_BUILD } from '../../debug-build';
2022
import type { NodeClient } from '../../sdk/client';
2123
import { getRequestUrl } from '../../utils/getRequestUrl';
@@ -133,7 +135,8 @@ export class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpIns
133135

134136
const isolationScope = getIsolationScope().clone();
135137
const request = args[0] as http.IncomingMessage;
136-
const normalizedRequest = httpRequestToRequestEventData(request);
138+
139+
const normalizedRequest = httpRequestToRequestData(request);
137140

138141
patchRequestToCaptureBody(request, isolationScope);
139142

@@ -428,32 +431,3 @@ function patchRequestToCaptureBody(req: IncomingMessage, isolationScope: Scope):
428431
// ignore errors if we can't patch stuff
429432
}
430433
}
431-
432-
/**
433-
* Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.
434-
*/
435-
export function httpRequestToRequestEventData(request: IncomingMessage): RequestEventData {
436-
const headers = request.headers || {};
437-
const host = headers.host || '<no host>';
438-
const protocol = request.socket && (request.socket as { encrypted?: boolean }).encrypted ? 'https' : 'http';
439-
const originalUrl = request.url || '';
440-
const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;
441-
442-
// This is non-standard, but may be sometimes set
443-
// It may be overwritten later by our own body handling
444-
const data = (request as PolymorphicRequest).body;
445-
446-
// This is non-standard, but may be set on e.g. Next.js or Express requests
447-
const cookies = (request as PolymorphicRequest).cookies;
448-
449-
const normalizedRequest: RequestEventData = dropUndefinedKeys({
450-
url: absoluteUrl,
451-
method: request.method,
452-
query_string: extractQueryParamsFromUrl(originalUrl),
453-
headers: headersToDict(headers),
454-
cookies,
455-
data,
456-
});
457-
458-
return normalizedRequest;
459-
}

0 commit comments

Comments
 (0)