Skip to content

Commit

Permalink
feat: add support for context.params in edge functions (#5964)
Browse files Browse the repository at this point in the history
Co-authored-by: Simon Knott <info@simonknott.de>
  • Loading branch information
eduardoboucas and Skn0tt committed Aug 29, 2023
1 parent 42478fd commit ed14e05
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/lib/edge-functions/bootstrap.mjs
Original file line number Diff line number Diff line change
@@ -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
41 changes: 28 additions & 13 deletions src/lib/edge-functions/registry.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
Original file line number Diff line number Diff line change
@@ -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',
}
25 changes: 22 additions & 3 deletions tests/integration/commands/dev/edge-functions.test.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -16,15 +16,34 @@ describe('edge functions', () => {
expect(response.body).toMatchSnapshot()
})

test<FixtureTestContext>('should provide geo location', async ({ devServer }) => {
test<FixtureTestContext>('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<FixtureTestContext>('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',
})
})
})

Expand Down

1 comment on commit ed14e05

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Benchmark results

  • Dependency count: 1,310
  • Package size: 273 MB

Please sign in to comment.