@@ -22,8 +22,7 @@ import {
22
22
startSpan ,
23
23
withIsolationScope ,
24
24
} from '@sentry/node' ;
25
- import type { APIContext , MiddlewareResponseHandler } from 'astro' ;
26
- import type { ResolvedRouteWithCasedPattern } from '../integration/types' ;
25
+ import type { APIContext , MiddlewareResponseHandler , RoutePart } from 'astro' ;
27
26
28
27
type MiddlewareOptions = {
29
28
/**
@@ -96,9 +95,6 @@ async function instrumentRequest(
96
95
addNonEnumerableProperty ( locals , '__sentry_wrapped__' , true ) ;
97
96
}
98
97
99
- const storedBuildTimeRoutes = ( globalThis as unknown as { __sentryRouteInfo ?: ResolvedRouteWithCasedPattern [ ] } )
100
- ?. __sentryRouteInfo ;
101
-
102
98
const isDynamicPageRequest = checkIsDynamicPageRequest ( ctx ) ;
103
99
104
100
const request = ctx . request ;
@@ -135,10 +131,21 @@ async function instrumentRequest(
135
131
// `routePattern` is available after Astro 5
136
132
const contextWithRoutePattern = ctx as Parameters < MiddlewareResponseHandler > [ 0 ] & { routePattern ?: string } ;
137
133
const rawRoutePattern = contextWithRoutePattern . routePattern ;
138
- const foundRoute = storedBuildTimeRoutes ?. find ( route => route . pattern === rawRoutePattern ) ;
134
+
135
+ // @ts -expect-error Implicit any on Symbol.for (This is available in Astro 5)
136
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
137
+ const routesFromManifest = ctx ?. [ Symbol . for ( 'context.routes' ) ] ?. manifest ?. routes ;
138
+
139
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
140
+ const matchedRouteSegmentsFromManifest = routesFromManifest ?. find (
141
+ ( route : { routeData ?: { route ?: string } } ) => route ?. routeData ?. route === rawRoutePattern ,
142
+ ) ?. routeData ?. segments ;
139
143
140
144
const parametrizedRoute =
141
- foundRoute ?. patternCaseSensitive || interpolateRouteFromUrlAndParams ( ctx . url . pathname , ctx . params ) ;
145
+ // Astro v5 - Joining the segments to get the correct casing of the parametrized route
146
+ ( matchedRouteSegmentsFromManifest && joinRouteSegments ( matchedRouteSegmentsFromManifest ) ) ||
147
+ // Fallback (Astro v4 and earlier)
148
+ interpolateRouteFromUrlAndParams ( ctx . url . pathname , ctx . params ) ;
142
149
143
150
const source = parametrizedRoute ? 'route' : 'url' ;
144
151
// storing res in a variable instead of directly returning is necessary to
@@ -365,3 +372,18 @@ function checkIsDynamicPageRequest(context: Parameters<MiddlewareResponseHandler
365
372
return false ;
366
373
}
367
374
}
375
+
376
+ /**
377
+ * Join Astro route segments into a case-sensitive single path string.
378
+ *
379
+ * Astro lowercases the parametrized route. Joining segments manually is recommended to get the correct casing of the routes.
380
+ * Recommendation in comment: https://github.com/withastro/astro/issues/13885#issuecomment-2934203029
381
+ * Function Reference: https://github.com/joanrieu/astro-typed-links/blob/b3dc12c6fe8d672a2bc2ae2ccc57c8071bbd09fa/package/src/integration.ts#L16
382
+ */
383
+ function joinRouteSegments ( segments : RoutePart [ ] [ ] ) : string {
384
+ const parthArray = segments . map ( segment =>
385
+ segment . map ( routePart => ( routePart . dynamic ? `[${ routePart . content } ]` : routePart . content ) ) . join ( '' ) ,
386
+ ) ;
387
+
388
+ return `/${ parthArray . join ( '/' ) } ` ;
389
+ }
0 commit comments