diff --git a/packages/hono/src/shared/middlewareHandlers.ts b/packages/hono/src/shared/middlewareHandlers.ts index ffba879603ea..0eddae5e81e0 100644 --- a/packages/hono/src/shared/middlewareHandlers.ts +++ b/packages/hono/src/shared/middlewareHandlers.ts @@ -11,7 +11,6 @@ import { winterCGRequestToRequestData, } from '@sentry/core'; import type { Context } from 'hono'; -import { hasFetchEvent } from '../utils/hono-context'; import { defaultShouldHandleError } from './defaultShouldHandleError'; import { resolveRouteName } from './resolveRouteName'; import { type SentryHonoMiddlewareOptions } from '../shared/types'; @@ -29,7 +28,7 @@ export function requestHandler(context: Context, getConnInfo?: GetConnInfo): voi updateSpanRouteName(isolationScope, context); isolationScope.setSDKProcessingMetadata({ - normalizedRequest: winterCGRequestToRequestData(hasFetchEvent(context) ? context.event.request : context.req.raw), + normalizedRequest: winterCGRequestToRequestData(context.req.raw), }); if (getConnInfo) { diff --git a/packages/hono/src/utils/hono-context.ts b/packages/hono/src/utils/hono-context.ts deleted file mode 100644 index 96df44ee655a..000000000000 --- a/packages/hono/src/utils/hono-context.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Context } from 'hono'; - -/** - * Checks whether the given Hono context has a fetch event. - */ -export function hasFetchEvent(c: Context): boolean { - let hasFetchEvent = true; - try { - // eslint-disable-next-line @typescript-eslint/no-unused-expressions - c.event; - } catch { - hasFetchEvent = false; - } - return hasFetchEvent; -} diff --git a/packages/hono/test/shared/middlewareHandlers.test.ts b/packages/hono/test/shared/middlewareHandlers.test.ts index c52e4f62eb69..0f406192ea8d 100644 --- a/packages/hono/test/shared/middlewareHandlers.test.ts +++ b/packages/hono/test/shared/middlewareHandlers.test.ts @@ -1,5 +1,6 @@ import * as SentryCore from '@sentry/core'; import { SENTRY_SEGMENT_NAME_SOURCE, HTTP_ROUTE } from '@sentry/conventions/attributes'; +import { Context } from 'hono'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { requestHandler, responseHandler } from '../../src/shared/middlewareHandlers'; @@ -8,10 +9,6 @@ vi.mock('hono/route', () => ({ matchedRoutes: () => [{ basePath: '/', path: '/test', method: 'GET', handler: (_c: unknown) => undefined }], })); -vi.mock('../../src/utils/hono-context', () => ({ - hasFetchEvent: () => false, -})); - const mockSetTransactionName = vi.fn(); const mockSetSDKProcessingMetadata = vi.fn(); const mockSetUser = vi.fn(); @@ -44,12 +41,14 @@ vi.mock('@sentry/core', async () => { })), getClient: vi.fn(() => undefined), captureException: vi.fn(), + winterCGRequestToRequestData: vi.fn(actual.winterCGRequestToRequestData), }; }); const getClientMock = SentryCore.getClient as ReturnType; const captureExceptionMock = SentryCore.captureException as ReturnType; const getActiveSpanMock = SentryCore.getActiveSpan as ReturnType; +const winterCGRequestToRequestDataMock = SentryCore.winterCGRequestToRequestData as ReturnType; function createMockContext(status: number, error?: Error): unknown { return { @@ -185,11 +184,21 @@ describe('responseHandler', () => { }); describe('transaction name', () => { - it('sets transaction name on isolation scope', () => { + it('sets request metadata and transaction name without reading the event', () => { + const context = createMockContext(200) as ReturnType & { + req: { raw: Request }; + }; + const eventGetter = vi.fn(() => { + throw new Error('This context has no FetchEvent'); + }); + Object.defineProperty(context, 'event', { get: eventGetter }); + // oxlint-disable-next-line typescript/no-explicit-any - requestHandler(createMockContext(200) as any); + requestHandler(context as any); expect(mockSetTransactionName).toHaveBeenCalledWith('GET /test'); + expect(winterCGRequestToRequestDataMock).toHaveBeenCalledWith(context.req.raw); + expect(eventGetter).not.toHaveBeenCalled(); }); it('sets http.route and segment name source on the root span', () => { @@ -332,3 +341,27 @@ describe('requestHandler — connection info', () => { expect(mockSetUser).not.toHaveBeenCalled(); }); }); + +describe('requestHandler — request metadata', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('uses the same request exposed by a legacy FetchEvent context', () => { + const request = new Request('http://localhost/test?source=event'); + const context = new Context(request, { + env: {}, + executionCtx: { + request, + respondWith: vi.fn(), + passThroughOnException: vi.fn(), + waitUntil: vi.fn(), + }, + }); + + requestHandler(context); + + expect(context.event.request).toBe(context.req.raw); + expect(winterCGRequestToRequestDataMock).toHaveBeenCalledWith(request); + }); +});