feat(functions): inject env var function slug (#49617)

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Feature (self-hosted Edge Functions)

## What is the current behavior?

The self-hosted Edge Functions router
(`docker/volumes/functions/main/index.ts`) doesn't tell a function which
slug a request resolved to. As a result, `@supabase/server`'s
`withOAuthProtectedResource` can't derive its canonical resource URL and
falls back to reconstructing it from the request path against the
internal `api-gw` origin, so the advertised OAuth Protected Resource is
/wrong for self-hosted deployments.

## What is the new behavior?

`main/index.ts` now injects `SUPABASE_FUNCTION_SLUG: service_name` per
request (after the `Deno.env.toObject()` snapshot, so nothing in the
container env can shadow it).

Combined with the operator's `SUPABASE_PUBLIC_URL`, the advertised
resource is the correct external
`{SUPABASE_PUBLIC_URL}/functions/v1/{slug}`, not the internal
`http://api-gw:8000`.

Verified on the docker stack: the slug is injected per-function, the
resource origin resolves to `SUPABASE_PUBLIC_URL`, and the `401`
`www-authenticate` carries the right `resource_metadata`.

## Additional context

Fixes AI-1128

Companion to `@supabase/server` [PR
#117](https://github.com/supabase/server/pull/117) and the [CLI slug
injection](https://github.com/supabase/cli/pull/6345)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Edge workers now receive the correct function slug in their runtime
environment, improving per-function request handling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Raúl Barroso authored and GitHub committed 2026-08-28 12:32:30 +02:00
1 parent 29493e02d0
commit f5f897a29b
1 file changed
+4 -1
+4 -1
View File
@@ -151,7 +151,10 @@ Deno.serve(async (req: Request) => {
// Using a common Import Map for all functions
// to use a scope 'deno.json' it must be dinamically resolved base on the 'service_name'
const importMapPath = `/home/deno/functions/deno.jsonc`
const envVarsObj = Deno.env.toObject()
// SUPABASE_FUNCTION_SLUG is listed after the container env snapshot so
// nothing in it can shadow the value, and it is per-request because only this
// worker knows which function the request resolved to.
const envVarsObj = { ...Deno.env.toObject(), SUPABASE_FUNCTION_SLUG: service_name }
const envVars = Object.keys(envVarsObj).map((k) => [k, envVarsObj[k]])
try {