@@ -22,7 +22,7 @@ type RoutingRuleBase = {
2222
2323type Match = {
2424 /** Regex */
25- path : string
25+ path ? : string
2626
2727 /** additional conditions */
2828 has ?: {
@@ -140,7 +140,10 @@ async function match(
140140 if ( prefix ) {
141141 console . log ( prefix , 'Evaluating rule:' , rule . description ?? JSON . stringify ( rule ) )
142142 }
143+
143144 if ( 'match' in rule ) {
145+ let matched = false
146+
144147 if ( 'type' in rule . match ) {
145148 if ( rule . match . type === 'static-asset-or-function' ) {
146149 let matchedType : 'static-asset' | 'function' | 'static-asset-alias' | null = null
@@ -171,6 +174,7 @@ async function match(
171174 ...maybeResponse ,
172175 response : await context . next ( currentRequest ) ,
173176 }
177+ matched = true
174178 }
175179 } else if ( rule . match . type === 'image-cdn' && pathname . startsWith ( '/.netlify/image/' ) ) {
176180 if ( prefix ) {
@@ -181,111 +185,117 @@ async function match(
181185 ...maybeResponse ,
182186 response : await context . next ( currentRequest ) ,
183187 }
188+ matched = true
184189 }
185190 } else if ( 'apply' in rule ) {
186- const sourceRegexp = new RegExp ( rule . match . path )
187- const sourceMatch = pathname . match ( sourceRegexp )
188- if ( sourceMatch ) {
189- // check additional conditions
190- if ( rule . match . has ) {
191- let hasAllMatch = true
192- for ( const condition of rule . match . has ) {
193- if ( condition . type === 'header' ) {
194- if ( typeof condition . value === 'undefined' ) {
195- if ( ! currentRequest . headers . has ( condition . key ) ) {
196- hasAllMatch = false
197- break
198- }
199- } else if ( currentRequest . headers . get ( condition . key ) !== condition . value ) {
200- hasAllMatch = false
201- break
202- }
191+ const replacements : Record < string , string > = { }
192+
193+ if ( rule . match . path ) {
194+ const sourceRegexp = new RegExp ( rule . match . path )
195+ const sourceMatch = pathname . match ( sourceRegexp )
196+ if ( sourceMatch ) {
197+ if ( sourceMatch . groups ) {
198+ for ( const [ key , value ] of Object . entries ( sourceMatch . groups ) ) {
199+ replacements [ `$${ key } ` ] = value
203200 }
204201 }
205-
206- if ( ! hasAllMatch ) {
207- continue
202+ for ( const [ index , element ] of sourceMatch . entries ( ) ) {
203+ replacements [ `$${ index } ` ] = element ?? ''
208204 }
205+ } else {
206+ continue
209207 }
208+ }
210209
211- const replacements : Record < string , string > = { }
212- if ( sourceMatch . groups ) {
213- for ( const [ key , value ] of Object . entries ( sourceMatch . groups ) ) {
214- replacements [ `$${ key } ` ] = value
210+ if ( rule . match . has ) {
211+ let hasAllMatch = true
212+ for ( const condition of rule . match . has ) {
213+ if ( condition . type === 'header' ) {
214+ if ( typeof condition . value === 'undefined' ) {
215+ if ( ! currentRequest . headers . has ( condition . key ) ) {
216+ hasAllMatch = false
217+ break
218+ }
219+ } else if ( currentRequest . headers . get ( condition . key ) !== condition . value ) {
220+ hasAllMatch = false
221+ break
222+ }
215223 }
216224 }
217- for ( const [ index , element ] of sourceMatch . entries ( ) ) {
218- replacements [ `$${ index } ` ] = element ?? ''
219- }
220225
221- if ( prefix ) {
222- console . log ( prefix , 'Matched rule' , pathname , rule , sourceMatch , replacements )
226+ if ( ! hasAllMatch ) {
227+ continue
223228 }
229+ }
224230
225- if ( rule . apply . headers ) {
226- maybeResponse = {
227- ...maybeResponse ,
228- headers : {
229- ...maybeResponse . headers ,
230- ...Object . fromEntries (
231- Object . entries ( rule . apply . headers ) . map ( ( [ key , value ] ) => {
232- return [ key , replaceGroupReferences ( value , replacements ) ]
233- } ) ,
234- ) ,
235- } ,
236- }
237- }
231+ if ( prefix ) {
232+ console . log ( prefix , 'Matched rule' , pathname , rule , replacements )
233+ }
238234
239- if ( rule . apply . type === 'rewrite' ) {
240- const replaced = replaceGroupReferences ( rule . apply . destination , replacements )
235+ if ( rule . apply . headers ) {
236+ maybeResponse = {
237+ ...maybeResponse ,
238+ headers : {
239+ ...maybeResponse . headers ,
240+ ...Object . fromEntries (
241+ Object . entries ( rule . apply . headers ) . map ( ( [ key , value ] ) => {
242+ return [ key , replaceGroupReferences ( value , replacements ) ]
243+ } ) ,
244+ ) ,
245+ } ,
246+ }
247+ }
241248
242- // pathname.replace(sourceRegexp, rule.apply.destination)
243- const destURL = new URL ( replaced , currentURL )
244- currentRequest = new Request ( destURL , currentRequest )
249+ if ( rule . apply . type === 'rewrite' ) {
250+ const replaced = replaceGroupReferences ( rule . apply . destination , replacements )
245251
246- if ( rule . apply . statusCode ) {
247- maybeResponse = {
248- ...maybeResponse ,
249- status : rule . apply . statusCode ,
250- }
251- }
252+ // pathname.replace(sourceRegexp, rule.apply.destination)
253+ const destURL = new URL ( replaced , currentURL )
254+ currentRequest = new Request ( destURL , currentRequest )
252255
253- if ( rule . apply . rerunRoutingPhases ) {
254- const { maybeResponse : updatedMaybeResponse } = await match (
255- currentRequest ,
256- context ,
257- selectRoutingPhasesRules ( routingRules , rule . apply . rerunRoutingPhases ) ,
258- allRoutingRules ,
259- outputs ,
260- prefix ,
261- maybeResponse ,
262- )
263- maybeResponse = updatedMaybeResponse
264- }
265- } else if ( rule . apply . type === 'redirect' ) {
266- const replaced = pathname . replace ( sourceRegexp , rule . apply . destination )
267- if ( prefix ) {
268- console . log ( prefix , `Redirecting ${ pathname } to ${ replaced } ` )
269- }
270- const status = rule . apply . statusCode ?? 307
256+ if ( rule . apply . statusCode ) {
271257 maybeResponse = {
272258 ...maybeResponse ,
273- status,
274- response : new Response ( null , {
275- status,
276- headers : {
277- Location : replaced ,
278- } ,
279- } ) ,
259+ status : rule . apply . statusCode ,
280260 }
281261 }
262+
263+ if ( rule . apply . rerunRoutingPhases ) {
264+ const { maybeResponse : updatedMaybeResponse } = await match (
265+ currentRequest ,
266+ context ,
267+ selectRoutingPhasesRules ( routingRules , rule . apply . rerunRoutingPhases ) ,
268+ allRoutingRules ,
269+ outputs ,
270+ prefix ,
271+ maybeResponse ,
272+ )
273+ maybeResponse = updatedMaybeResponse
274+ }
275+ } else if ( rule . apply . type === 'redirect' ) {
276+ const replaced = replaceGroupReferences ( rule . apply . destination , replacements )
277+ if ( prefix ) {
278+ console . log ( prefix , `Redirecting ${ pathname } to ${ replaced } ` )
279+ }
280+ const status = rule . apply . statusCode ?? 307
281+ maybeResponse = {
282+ ...maybeResponse ,
283+ status,
284+ response : new Response ( null , {
285+ status,
286+ headers : {
287+ Location : replaced ,
288+ } ,
289+ } ) ,
290+ }
282291 }
292+ matched = true
283293 }
284- }
285294
286- if ( maybeResponse ?. response && ! rule . continue ) {
287- // once hit a response short circuit
288- return { maybeResponse, currentRequest }
295+ if ( matched && ! rule . continue ) {
296+ // once hit a match short circuit
297+ return { maybeResponse, currentRequest }
298+ }
289299 }
290300 }
291301 return { maybeResponse, currentRequest }
0 commit comments