1
1
/* eslint-disable max-lines */
2
2
import { captureException , getCurrentHub } from '@sentry/node' ;
3
3
import { getActiveTransaction } from '@sentry/tracing' ;
4
- import {
5
- addExceptionMechanism ,
6
- fill ,
7
- loadModule ,
8
- logger ,
9
- serializeBaggage ,
10
- stripUrlQueryAndFragment ,
11
- } from '@sentry/utils' ;
4
+ import { addExceptionMechanism , fill , loadModule , logger , serializeBaggage } from '@sentry/utils' ;
12
5
13
6
// Types vendored from @remix -run/server-runtime@1.6.0:
14
7
// https://github.com/remix-run/remix/blob/f3691d51027b93caa3fd2cdfe146d7b62a6eb8f2/packages/remix-server-runtime/server.ts
@@ -92,6 +85,14 @@ interface DataFunction {
92
85
( args : DataFunctionArgs ) : Promise < Response > | Response | Promise < AppData > | AppData ;
93
86
}
94
87
88
+ // Taken from Remix Implementation
89
+ // https://github.com/remix-run/remix/blob/97999d02493e8114c39d48b76944069d58526e8d/packages/remix-server-runtime/routeMatching.ts#L6-L10
90
+ export interface RouteMatch < Route > {
91
+ params : Params ;
92
+ pathname : string ;
93
+ route : Route ;
94
+ }
95
+
95
96
// Taken from Remix Implementation
96
97
// https://github.com/remix-run/remix/blob/7688da5c75190a2e29496c78721456d6e12e3abe/packages/remix-server-runtime/responses.ts#L54-L62
97
98
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -262,18 +263,58 @@ function makeWrappedMeta(origMeta: MetaFunction | HtmlMetaDescriptor = {}): Meta
262
263
} ;
263
264
}
264
265
265
- function wrapRequestHandler ( origRequestHandler : RequestHandler ) : RequestHandler {
266
+ function createRoutes ( manifest : ServerRouteManifest , parentId ?: string ) : ServerRoute [ ] {
267
+ return Object . entries ( manifest )
268
+ . filter ( ( [ , route ] ) => route . parentId === parentId )
269
+ . map ( ( [ id , route ] ) => ( {
270
+ ...route ,
271
+ children : createRoutes ( manifest , id ) ,
272
+ } ) ) ;
273
+ }
274
+
275
+ function wrapRequestHandler ( origRequestHandler : RequestHandler , build : ServerBuild ) : RequestHandler {
276
+ const routes = createRoutes ( build . routes ) ;
277
+ const pkg = loadModule < { matchRoutes : ( routes : ServerRoute [ ] , pathname : string ) => any [ ] } > ( 'react-router-dom' ) ;
278
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
279
+ // https://github.com/remix-run/remix/blob/38e127b1d97485900b9c220d93503de0deb1fc81/packages/remix-server-runtime/routeMatching.ts#L12-L24
280
+ function matchServerRoutes ( routes : ServerRoute [ ] , pathname : string ) : RouteMatch < ServerRoute > [ ] | null {
281
+ if ( ! pkg ) {
282
+ return null ;
283
+ }
284
+
285
+ const matches = pkg . matchRoutes ( routes , pathname ) ;
286
+ if ( ! matches ) {
287
+ return null ;
288
+ }
289
+
290
+ return matches . map ( match => ( {
291
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
292
+ params : match . params ,
293
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
294
+ pathname : match . pathname ,
295
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
296
+ route : match . route as unknown as ServerRoute ,
297
+ } ) ) ;
298
+ }
299
+
266
300
return async function ( this : unknown , request : Request , loadContext ?: unknown ) : Promise < Response > {
267
301
const hub = getCurrentHub ( ) ;
268
302
const currentScope = hub . getScope ( ) ;
303
+
304
+ const url = new URL ( request . url ) ;
305
+ const matches = matchServerRoutes ( routes , url . pathname ) ;
306
+
307
+ const match = matches && getRequestMatch ( url , matches ) ;
308
+ const name = match === null ? url . pathname : match . route . id ;
309
+ const source = match === null ? 'url' : 'route' ;
269
310
const transaction = hub . startTransaction ( {
270
- name : stripUrlQueryAndFragment ( request . url ) ,
311
+ name,
271
312
op : 'http.server' ,
272
313
tags : {
273
314
method : request . method ,
274
315
} ,
275
316
metadata : {
276
- source : 'url' ,
317
+ source,
277
318
} ,
278
319
} ) ;
279
320
@@ -290,6 +331,33 @@ function wrapRequestHandler(origRequestHandler: RequestHandler): RequestHandler
290
331
} ;
291
332
}
292
333
334
+ // https://github.com/remix-run/remix/blob/97999d02493e8114c39d48b76944069d58526e8d/packages/remix-server-runtime/server.ts#L573-L586
335
+ function isIndexRequestUrl ( url : URL ) : boolean {
336
+ for ( const param of url . searchParams . getAll ( 'index' ) ) {
337
+ // only use bare `?index` params without a value
338
+ // ✅ /foo?index
339
+ // ✅ /foo?index&index=123
340
+ // ✅ /foo?index=123&index
341
+ // ❌ /foo?index=123
342
+ if ( param === '' ) {
343
+ return true ;
344
+ }
345
+ }
346
+
347
+ return false ;
348
+ }
349
+
350
+ // https://github.com/remix-run/remix/blob/97999d02493e8114c39d48b76944069d58526e8d/packages/remix-server-runtime/server.ts#L588-L596
351
+ function getRequestMatch ( url : URL , matches : RouteMatch < ServerRoute > [ ] ) : RouteMatch < ServerRoute > {
352
+ const match = matches . slice ( - 1 ) [ 0 ] ;
353
+
354
+ if ( ! isIndexRequestUrl ( url ) && match . route . id . endsWith ( '/index' ) ) {
355
+ return matches . slice ( - 2 ) [ 0 ] ;
356
+ }
357
+
358
+ return match ;
359
+ }
360
+
293
361
function makeWrappedCreateRequestHandler (
294
362
origCreateRequestHandler : CreateRequestHandlerFunction ,
295
363
) : CreateRequestHandlerFunction {
@@ -318,7 +386,7 @@ function makeWrappedCreateRequestHandler(
318
386
319
387
const requestHandler = origCreateRequestHandler . call ( this , { ...build , routes, entry : wrappedEntry } , mode ) ;
320
388
321
- return wrapRequestHandler ( requestHandler ) ;
389
+ return wrapRequestHandler ( requestHandler , build ) ;
322
390
} ;
323
391
}
324
392
0 commit comments