Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 9 additions & 27 deletions apps/docs/content/guides/functions/cors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ See the [example on GitHub](https://github.com/supabase/supabase/blob/master/exa

### Recommended setup

<Admonition type="tip">
We recommend adding a `cors.ts` file within a [`_shared` folder](/docs/guides/functions/quickstart#organizing-your-edge-functions) which makes it easy to reuse the CORS headers across functions:

**For `@supabase/supabase-js` v2.95.0 and later:** Import CORS headers directly from the SDK to ensure they stay synchronized with any new headers added to the client libraries.

</Admonition>
```ts cors.ts
export const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
```

Import `corsHeaders` from `@supabase/supabase-js/cors` to automatically get all required headers:
You can then import and use the CORS headers within your functions:

```ts index.ts
import { corsHeaders } from '@supabase/supabase-js/cors'
import { corsHeaders } from '../_shared/cors.ts'

console.log(`Function "browser-with-cors" up and running!`)

Expand Down Expand Up @@ -47,24 +50,3 @@ Deno.serve(async (req) => {
}
})
```

This approach ensures that when new headers are added to the Supabase SDK, your Edge Functions automatically include them, preventing CORS errors.

#### For versions before 2.95.0

If you're using `@supabase/supabase-js` before v2.95.0, you'll need to hardcode the CORS headers. Add a `cors.ts` file within a [`_shared` folder](/docs/guides/functions/quickstart#organizing-your-edge-functions):

```ts _shared/cors.ts
export const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
```

Then import it in your function:

```ts index.ts
import { corsHeaders } from '../_shared/cors.ts'

// ... rest of your function code
```
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ supabase functions new cloudflare-turnstile
And add the code to the `index.ts` file:

```ts index.ts
import { corsHeaders } from '@supabase/supabase-js/cors' // v2.95.0+
import { corsHeaders } from '../_shared/cors.ts'

console.log('Hello from Cloudflare Trunstile!')

Expand Down
21 changes: 10 additions & 11 deletions apps/docs/content/guides/functions/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,26 +112,25 @@ For invocation or CORS issues:

```tsx
// ✅ Proper CORS handling
import { corsHeaders } from '@supabase/supabase-js/cors' // v2.95.0+

Deno.serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
return new Response(null, {
status: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}

// Your function logic here
return new Response(JSON.stringify({ status: 'Success' }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
return new Response('Success', {
headers: { 'Access-Control-Allow-Origin': '*' },
})
})
```

<Admonition type="note">

For `@supabase/supabase-js` versions before v2.95.0, you'll need to hardcode the CORS headers. See the [CORS guide](/docs/guides/functions/cors) for details.

</Admonition>

There are two debugging tools available: Invocations and Logs. Invocations shows the Request and Response for each execution, while Logs shows any platform events, including deployments and errors.

---
Expand Down
142 changes: 0 additions & 142 deletions apps/docs/features/docs/__snapshots__/Reference.typeSpec.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -86865,66 +86865,6 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"name": "Options"
},
"isOptional": true
},
{
"name": "parameters",
"type": {
"type": "object",
"name": "FetchParameters",
"properties": [
{
"name": "cache",
"type": {
"type": "union",
"subTypes": [
{
"type": "literal",
"value": "default"
},
{
"type": "literal",
"value": "no-store"
},
{
"type": "literal",
"value": "reload"
},
{
"type": "literal",
"value": "no-cache"
},
{
"type": "literal",
"value": "force-cache"
},
{
"type": "literal",
"value": "only-if-cached"
}
]
},
"isOptional": true,
"comment": {
"shortText": "Controls how the request interacts with the browser's HTTP cache.\\n- 'default': Use standard cache behavior\\n- 'no-store': Bypass cache entirely (useful in Edge Functions)\\n- 'reload': Bypass cache but update it with response\\n- 'no-cache': Validate with server before using cached response\\n- 'force-cache': Use cache even if stale\\n- 'only-if-cached': Only use cache, fail if not cached"
}
},
{
"name": "signal",
"type": {
"type": "nameOnly",
"name": "AbortSignal"
},
"isOptional": true,
"comment": {
"shortText": "Pass in an AbortController's signal to cancel the request."
}
}
]
},
"isOptional": true,
"comment": {
"shortText": "Additional fetch parameters like signal for cancellation. Supports standard fetch options including cache control."
}
}
],
"ret": {
Expand All @@ -86946,16 +86886,6 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"id": "download-file-with-transformations",
"name": "Download file with transformations",
"code": "\`\`\`js\\nconst { data, error } = await supabase\\n .storage\\n .from('avatars')\\n .download('folder/avatar1.png', {\\n transform: {\\n width: 100,\\n height: 100,\\n quality: 80\\n }\\n })\\n\`\`\`"
},
{
"id": "download-with-cache-control-useful-in-edge-functions",
"name": "Download with cache control (useful in Edge Functions)",
"code": "\`\`\`js\\nconst { data, error } = await supabase\\n .storage\\n .from('avatars')\\n .download('folder/avatar1.png', {}, { cache: 'no-store' })\\n\`\`\`"
},
{
"id": "download-with-abort-signal",
"name": "Download with abort signal",
"code": "\`\`\`js\\nconst controller = new AbortController()\\nsetTimeout(() => controller.abort(), 5000)\\n\\nconst { data, error } = await supabase\\n .storage\\n .from('avatars')\\n .download('folder/avatar1.png', {}, { signal: controller.signal })\\n\`\`\`"
}
]
}
Expand Down Expand Up @@ -87371,42 +87301,6 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"type": "object",
"name": "FetchParameters",
"properties": [
{
"name": "cache",
"type": {
"type": "union",
"subTypes": [
{
"type": "literal",
"value": "default"
},
{
"type": "literal",
"value": "no-store"
},
{
"type": "literal",
"value": "reload"
},
{
"type": "literal",
"value": "no-cache"
},
{
"type": "literal",
"value": "force-cache"
},
{
"type": "literal",
"value": "only-if-cached"
}
]
},
"isOptional": true,
"comment": {
"shortText": "Controls how the request interacts with the browser's HTTP cache.\\n- 'default': Use standard cache behavior\\n- 'no-store': Bypass cache entirely (useful in Edge Functions)\\n- 'reload': Bypass cache but update it with response\\n- 'no-cache': Validate with server before using cached response\\n- 'force-cache': Use cache even if stale\\n- 'only-if-cached': Only use cache, fail if not cached"
}
},
{
"name": "signal",
"type": {
Expand Down Expand Up @@ -87768,42 +87662,6 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"type": "object",
"name": "FetchParameters",
"properties": [
{
"name": "cache",
"type": {
"type": "union",
"subTypes": [
{
"type": "literal",
"value": "default"
},
{
"type": "literal",
"value": "no-store"
},
{
"type": "literal",
"value": "reload"
},
{
"type": "literal",
"value": "no-cache"
},
{
"type": "literal",
"value": "force-cache"
},
{
"type": "literal",
"value": "only-if-cached"
}
]
},
"isOptional": true,
"comment": {
"shortText": "Controls how the request interacts with the browser's HTTP cache.\\n- 'default': Use standard cache behavior\\n- 'no-store': Bypass cache entirely (useful in Edge Functions)\\n- 'reload': Bypass cache but update it with response\\n- 'no-cache': Validate with server before using cached response\\n- 'force-cache': Use cache even if stale\\n- 'only-if-cached': Only use cache, fail if not cached"
}
},
{
"name": "signal",
"type": {
Expand Down
Loading
Loading