From df82610fa5398b97679aa96a76f1846e1402dbca Mon Sep 17 00:00:00 2001 From: Lubomir Igonda Date: Thu, 26 Oct 2023 08:41:04 +0000 Subject: [PATCH] fix(tracing-internal): Fix case when middleware contain array of routes with special chars as @ --- .../src/node/integrations/express.ts | 54 ++++++++++--------- .../test/node/express.test.ts | 21 ++++++++ 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/packages/tracing-internal/src/node/integrations/express.ts b/packages/tracing-internal/src/node/integrations/express.ts index e46096d9ed84..f7ff20fa9986 100644 --- a/packages/tracing-internal/src/node/integrations/express.ts +++ b/packages/tracing-internal/src/node/integrations/express.ts @@ -65,7 +65,7 @@ type Layer = { route?: { path: RouteType | RouteType[] }; path?: string; regexp?: RegExp; - keys?: { name: string; offset: number; optional: boolean }[]; + keys?: { name: string | number; offset: number; optional: boolean }[]; }; type RouteType = string | RegExp; @@ -433,30 +433,34 @@ export const extractOriginalRoute = ( /** * iterate param matches from regexp.exec */ - paramIndices.forEach(([startOffset, endOffset], index: number) => { - /** - * isolate part before param - */ - const substr1 = resultPath.substring(0, startOffset - indexShift); - /** - * define paramName as replacement in format :pathParam - */ - const replacement = `:${orderedKeys[index].name}`; - - /** - * isolate part after param - */ - const substr2 = resultPath.substring(endOffset - indexShift); - - /** - * recreate original path but with param replacement - */ - resultPath = substr1 + replacement + substr2; - - /** - * calculate new index shift after resultPath was modified - */ - indexShift = indexShift + (endOffset - startOffset - replacement.length); + paramIndices.forEach((item: [number, number] | undefined, index: number) => { + /** check if offsets is define because in some cases regex d flag returns undefined */ + if (item) { + const [startOffset, endOffset] = item; + /** + * isolate part before param + */ + const substr1 = resultPath.substring(0, startOffset - indexShift); + /** + * define paramName as replacement in format :pathParam + */ + const replacement = `:${orderedKeys[index].name}`; + + /** + * isolate part after param + */ + const substr2 = resultPath.substring(endOffset - indexShift); + + /** + * recreate original path but with param replacement + */ + resultPath = substr1 + replacement + substr2; + + /** + * calculate new index shift after resultPath was modified + */ + indexShift = indexShift + (endOffset - startOffset - replacement.length); + } }); return resultPath; diff --git a/packages/tracing-internal/test/node/express.test.ts b/packages/tracing-internal/test/node/express.test.ts index e9f4df236b33..4b8d31fb2cdc 100644 --- a/packages/tracing-internal/test/node/express.test.ts +++ b/packages/tracing-internal/test/node/express.test.ts @@ -87,5 +87,26 @@ if (major >= 16) { ]; expect(extractOriginalRoute(path, regex, keys)).toBe('/user/:userId/profile/:username'); }); + + it('should handle complex regex scheme extract from array of routes', () => { + const path1 = '/@fs/*'; + const path2 = '/@vite/client'; + const path3 = '/@react-refresh'; + const path4 = '/manifest.json'; + + const regex = + /(?:^\/manifest\.json\/?(?=\/|$)|^\/@vite\/client\/?(?=\/|$)|^\/@react-refresh\/?(?=\/|$)|^\/src\/(.*)\/?(?=\/|$)|^\/vite\/(.*)\/?(?=\/|$)|^\/node_modules\/(.*)\/?(?=\/|$)|^\/@fs\/(.*)\/?(?=\/|$)|^\/@vite-plugin-checker-runtime\/?(?=\/|$)|^\/?$\/?(?=\/|$)|^\/home\/?$\/?(?=\/|$)|^\/login\/?(?=\/|$))/; + const keys = [ + { name: 0, offset: 8, optional: false }, + { name: 0, offset: 8, optional: false }, + { name: 0, offset: 9, optional: false }, + { name: 0, offset: 17, optional: false }, + ]; + + expect(extractOriginalRoute(path1, regex, keys)).toBe('/@fs/:0'); + expect(extractOriginalRoute(path2, regex, keys)).toBe('/@vite/client'); + expect(extractOriginalRoute(path3, regex, keys)).toBe('/@react-refresh'); + expect(extractOriginalRoute(path4, regex, keys)).toBe('/manifest.json'); + }); }); }