@@ -69,6 +69,43 @@ describe('sentryMiddleware', () => {
6969 expect ( resultFromNext ) . toStrictEqual ( nextResult ) ;
7070 } ) ;
7171
72+ it ( "sets source route if the url couldn't be decoded correctly" , async ( ) => {
73+ const middleware = handleRequest ( ) ;
74+ const ctx = {
75+ request : {
76+ method : 'GET' ,
77+ url : '/a%xx' ,
78+ headers : new Headers ( ) ,
79+ } ,
80+ url : { pathname : 'a%xx' , href : 'http://localhost:1234/a%xx' } ,
81+ params : { } ,
82+ } ;
83+ const next = vi . fn ( ( ) => nextResult ) ;
84+
85+ // @ts -expect-error, a partial ctx object is fine here
86+ const resultFromNext = middleware ( ctx , next ) ;
87+
88+ expect ( startSpanSpy ) . toHaveBeenCalledWith (
89+ {
90+ data : {
91+ method : 'GET' ,
92+ url : 'http://localhost:1234/a%xx' ,
93+ } ,
94+ metadata : {
95+ source : 'url' ,
96+ } ,
97+ name : 'GET a%xx' ,
98+ op : 'http.server' ,
99+ origin : 'auto.http.astro' ,
100+ status : 'ok' ,
101+ } ,
102+ expect . any ( Function ) , // the `next` function
103+ ) ;
104+
105+ expect ( next ) . toHaveBeenCalled ( ) ;
106+ expect ( resultFromNext ) . toStrictEqual ( nextResult ) ;
107+ } ) ;
108+
72109 it ( 'throws and sends an error to sentry if `next()` throws' , async ( ) => {
73110 const captureExceptionSpy = vi . spyOn ( SentryNode , 'captureException' ) ;
74111
@@ -299,15 +336,31 @@ describe('sentryMiddleware', () => {
299336
300337describe ( 'interpolateRouteFromUrlAndParams' , ( ) => {
301338 it . each ( [
339+ [ '/' , { } , '/' ] ,
302340 [ '/foo/bar' , { } , '/foo/bar' ] ,
303341 [ '/users/123' , { id : '123' } , '/users/[id]' ] ,
304342 [ '/users/123' , { id : '123' , foo : 'bar' } , '/users/[id]' ] ,
305343 [ '/lang/en-US' , { lang : 'en' , region : 'US' } , '/lang/[lang]-[region]' ] ,
306344 [ '/lang/en-US/posts' , { lang : 'en' , region : 'US' } , '/lang/[lang]-[region]/posts' ] ,
345+ // edge cases that astro doesn't support
346+ [ '/lang/-US' , { region : 'US' } , '/lang/-[region]' ] ,
347+ [ '/lang/en-' , { lang : 'en' } , '/lang/[lang]-' ] ,
307348 ] ) ( 'interpolates route from URL and params %s' , ( rawUrl , params , expectedRoute ) => {
308349 expect ( interpolateRouteFromUrlAndParams ( rawUrl , params ) ) . toEqual ( expectedRoute ) ;
309350 } ) ;
310351
352+ it . each ( [
353+ [ '/(a+)+/aaaaaaaaa!' , { id : '(a+)+' , slug : 'aaaaaaaaa!' } , '/[id]/[slug]' ] ,
354+ [ '/([a-zA-Z]+)*/aaaaaaaaa!' , { id : '([a-zA-Z]+)*' , slug : 'aaaaaaaaa!' } , '/[id]/[slug]' ] ,
355+ [ '/(a|aa)+/aaaaaaaaa!' , { id : '(a|aa)+' , slug : 'aaaaaaaaa!' } , '/[id]/[slug]' ] ,
356+ [ '/(a|a?)+/aaaaaaaaa!' , { id : '(a|a?)+' , slug : 'aaaaaaaaa!' } , '/[id]/[slug]' ] ,
357+ // with URL encoding
358+ [ '/(a%7Caa)+/aaaaaaaaa!' , { id : '(a|aa)+' , slug : 'aaaaaaaaa!' } , '/[id]/[slug]' ] ,
359+ [ '/(a%7Ca?)+/aaaaaaaaa!' , { id : '(a|a?)+' , slug : 'aaaaaaaaa!' } , '/[id]/[slug]' ] ,
360+ ] ) ( 'handles regex characters in param values correctly %s' , ( rawUrl , params , expectedRoute ) => {
361+ expect ( interpolateRouteFromUrlAndParams ( rawUrl , params ) ) . toEqual ( expectedRoute ) ;
362+ } ) ;
363+
311364 it ( 'handles params across multiple URL segments in catchall routes' , ( ) => {
312365 // Ideally, Astro would let us know that this is a catchall route so we can make the param [...catchall] but it doesn't
313366 expect (
@@ -324,4 +377,11 @@ describe('interpolateRouteFromUrlAndParams', () => {
324377 const expectedRoute = '/usernames/[name]' ;
325378 expect ( interpolateRouteFromUrlAndParams ( rawUrl , params ) ) . toEqual ( expectedRoute ) ;
326379 } ) ;
380+
381+ it ( 'handles set but undefined params' , ( ) => {
382+ const rawUrl = '/usernames/user' ;
383+ const params = { name : undefined , name2 : '' } ;
384+ const expectedRoute = '/usernames/user' ;
385+ expect ( interpolateRouteFromUrlAndParams ( rawUrl , params ) ) . toEqual ( expectedRoute ) ;
386+ } ) ;
327387} ) ;
0 commit comments