Skip to content

Commit 0438780

Browse files
committed
fix rule evaluation continuation
1 parent 2e15e26 commit 0438780

File tree

1 file changed

+93
-83
lines changed

1 file changed

+93
-83
lines changed

src/adapter/run/routing.ts

Lines changed: 93 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type RoutingRuleBase = {
2222

2323
type 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

Comments
 (0)