diff --git a/src/lib/edge-functions/bootstrap.mjs b/src/lib/edge-functions/bootstrap.mjs index c21a26268cf..d37be10b591 100644 --- a/src/lib/edge-functions/bootstrap.mjs +++ b/src/lib/edge-functions/bootstrap.mjs @@ -1,5 +1,5 @@ import { env } from 'process' -const latestBootstrapURL = 'https://64c264287e9cbb0008621df3--edge.netlify.com/bootstrap/index-combined.ts' +const latestBootstrapURL = 'https://64e7783fce8cfe0008496c72--edge.netlify.com/bootstrap/index-combined.ts' export const getBootstrapURL = () => env.NETLIFY_EDGE_BOOTSTRAP || latestBootstrapURL diff --git a/src/lib/edge-functions/registry.mjs b/src/lib/edge-functions/registry.mjs index 22325f0049d..cae41fc5100 100644 --- a/src/lib/edge-functions/registry.mjs +++ b/src/lib/edge-functions/registry.mjs @@ -318,23 +318,38 @@ export class EdgeFunctionsRegistry { functions: this.#functions, featureFlags, }) - const invocationMetadata = { - function_config: manifest.function_config, - routes: manifest.routes.map((route) => ({ function: route.function, pattern: route.pattern })), - } const routes = [...manifest.routes, ...manifest.post_cache_routes].map((route) => ({ ...route, pattern: new RegExp(route.pattern), })) - const functionNames = routes - .filter(({ pattern }) => pattern.test(urlPath)) - .filter(({ function: name }) => { - const isExcluded = manifest.function_config[name]?.excluded_patterns?.some((pattern) => - new RegExp(pattern).test(urlPath), - ) - return !isExcluded - }) - .map((route) => route.function) + + /** @type string[] */ + const functionNames = [] + + /** @type number[] */ + const routeIndexes = [] + + routes.forEach((route, index) => { + if (!route.pattern.test(urlPath)) { + return + } + + const isExcluded = manifest.function_config[route.function]?.excluded_patterns?.some((pattern) => + new RegExp(pattern).test(urlPath), + ) + + if (isExcluded) { + return + } + + functionNames.push(route.function) + routeIndexes.push(index) + }) + const invocationMetadata = { + function_config: manifest.function_config, + req_routes: routeIndexes, + routes: manifest.routes.map((route) => ({ function: route.function, path: route.path, pattern: route.pattern })), + } const orphanedDeclarations = this.#matchURLPathAgainstOrphanedDeclarations(urlPath) return { functionNames, invocationMetadata, orphanedDeclarations } diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/netlify/edge-functions/context-with-params.ts b/tests/integration/__fixtures__/dev-server-with-edge-functions/netlify/edge-functions/context-with-params.ts new file mode 100644 index 00000000000..d32e5662390 --- /dev/null +++ b/tests/integration/__fixtures__/dev-server-with-edge-functions/netlify/edge-functions/context-with-params.ts @@ -0,0 +1,7 @@ +import { Config, Context } from 'https://edge.netlify.com' + +export default (_, context: Context) => Response.json(context) + +export const config: Config = { + path: '/categories/:category/products/:product', +} diff --git a/tests/integration/commands/dev/edge-functions.test.ts b/tests/integration/commands/dev/edge-functions.test.ts index 8d86f71a05c..7dd769ba168 100644 --- a/tests/integration/commands/dev/edge-functions.test.ts +++ b/tests/integration/commands/dev/edge-functions.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test } from 'vitest' +import { describe, expect, expectTypeOf, test } from 'vitest' import { FixtureTestContext, setupFixtureTests } from '../../utils/fixture.js' import got from '../../utils/got.cjs' @@ -16,15 +16,34 @@ describe('edge functions', () => { expect(response.body).toMatchSnapshot() }) - test('should provide geo location', async ({ devServer }) => { + test('should provide context properties', async ({ devServer }) => { const response = await got(`http://localhost:${devServer.port}/context`, { throwHttpErrors: false, retry: { limit: 0 }, }) - const { geo } = JSON.parse(response.body) + const { deploy, geo, ip, params, requestId, server, site } = JSON.parse(response.body) expect(geo.city).toEqual('Mock City') expect(geo.country.code).toEqual('DE') + expect(deploy).toEqual({ id: '0' }) + expectTypeOf(ip).toBeString() + expect(params).toEqual({}) + expectTypeOf(requestId).toBeString() + expect(server).toEqual({ region: 'local' }) + expect(site).toEqual({ id: 'foo' }) + }) + + test('should expose URL parameters', async ({ devServer }) => { + const response = await got(`http://localhost:${devServer.port}/categories/foo/products/bar`, { + throwHttpErrors: false, + retry: { limit: 0 }, + }) + + const { params } = JSON.parse(response.body) + expect(params).toEqual({ + category: 'foo', + product: 'bar', + }) }) })