Skip to content

Commit ed14e05

Browse files
feat: add support for context.params in edge functions (#5964)
Co-authored-by: Simon Knott <[email protected]>
1 parent 42478fd commit ed14e05

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

src/lib/edge-functions/bootstrap.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { env } from 'process'
22

3-
const latestBootstrapURL = 'https://64c264287e9cbb0008621df3--edge.netlify.com/bootstrap/index-combined.ts'
3+
const latestBootstrapURL = 'https://64e7783fce8cfe0008496c72--edge.netlify.com/bootstrap/index-combined.ts'
44

55
export const getBootstrapURL = () => env.NETLIFY_EDGE_BOOTSTRAP || latestBootstrapURL

src/lib/edge-functions/registry.mjs

+28-13
Original file line numberDiff line numberDiff line change
@@ -318,23 +318,38 @@ export class EdgeFunctionsRegistry {
318318
functions: this.#functions,
319319
featureFlags,
320320
})
321-
const invocationMetadata = {
322-
function_config: manifest.function_config,
323-
routes: manifest.routes.map((route) => ({ function: route.function, pattern: route.pattern })),
324-
}
325321
const routes = [...manifest.routes, ...manifest.post_cache_routes].map((route) => ({
326322
...route,
327323
pattern: new RegExp(route.pattern),
328324
}))
329-
const functionNames = routes
330-
.filter(({ pattern }) => pattern.test(urlPath))
331-
.filter(({ function: name }) => {
332-
const isExcluded = manifest.function_config[name]?.excluded_patterns?.some((pattern) =>
333-
new RegExp(pattern).test(urlPath),
334-
)
335-
return !isExcluded
336-
})
337-
.map((route) => route.function)
325+
326+
/** @type string[] */
327+
const functionNames = []
328+
329+
/** @type number[] */
330+
const routeIndexes = []
331+
332+
routes.forEach((route, index) => {
333+
if (!route.pattern.test(urlPath)) {
334+
return
335+
}
336+
337+
const isExcluded = manifest.function_config[route.function]?.excluded_patterns?.some((pattern) =>
338+
new RegExp(pattern).test(urlPath),
339+
)
340+
341+
if (isExcluded) {
342+
return
343+
}
344+
345+
functionNames.push(route.function)
346+
routeIndexes.push(index)
347+
})
348+
const invocationMetadata = {
349+
function_config: manifest.function_config,
350+
req_routes: routeIndexes,
351+
routes: manifest.routes.map((route) => ({ function: route.function, path: route.path, pattern: route.pattern })),
352+
}
338353
const orphanedDeclarations = this.#matchURLPathAgainstOrphanedDeclarations(urlPath)
339354

340355
return { functionNames, invocationMetadata, orphanedDeclarations }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Config, Context } from 'https://edge.netlify.com'
2+
3+
export default (_, context: Context) => Response.json(context)
4+
5+
export const config: Config = {
6+
path: '/categories/:category/products/:product',
7+
}

tests/integration/commands/dev/edge-functions.test.ts

+22-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, expect, test } from 'vitest'
1+
import { describe, expect, expectTypeOf, test } from 'vitest'
22

33
import { FixtureTestContext, setupFixtureTests } from '../../utils/fixture.js'
44
import got from '../../utils/got.cjs'
@@ -16,15 +16,34 @@ describe('edge functions', () => {
1616
expect(response.body).toMatchSnapshot()
1717
})
1818

19-
test<FixtureTestContext>('should provide geo location', async ({ devServer }) => {
19+
test<FixtureTestContext>('should provide context properties', async ({ devServer }) => {
2020
const response = await got(`http://localhost:${devServer.port}/context`, {
2121
throwHttpErrors: false,
2222
retry: { limit: 0 },
2323
})
2424

25-
const { geo } = JSON.parse(response.body)
25+
const { deploy, geo, ip, params, requestId, server, site } = JSON.parse(response.body)
2626
expect(geo.city).toEqual('Mock City')
2727
expect(geo.country.code).toEqual('DE')
28+
expect(deploy).toEqual({ id: '0' })
29+
expectTypeOf(ip).toBeString()
30+
expect(params).toEqual({})
31+
expectTypeOf(requestId).toBeString()
32+
expect(server).toEqual({ region: 'local' })
33+
expect(site).toEqual({ id: 'foo' })
34+
})
35+
36+
test<FixtureTestContext>('should expose URL parameters', async ({ devServer }) => {
37+
const response = await got(`http://localhost:${devServer.port}/categories/foo/products/bar`, {
38+
throwHttpErrors: false,
39+
retry: { limit: 0 },
40+
})
41+
42+
const { params } = JSON.parse(response.body)
43+
expect(params).toEqual({
44+
category: 'foo',
45+
product: 'bar',
46+
})
2847
})
2948
})
3049

0 commit comments

Comments
 (0)