diff --git a/apps/docs/content/guides/functions/cors.mdx b/apps/docs/content/guides/functions/cors.mdx index dc357aae63d..46d7c4375b7 100644 --- a/apps/docs/content/guides/functions/cors.mdx +++ b/apps/docs/content/guides/functions/cors.mdx @@ -10,19 +10,16 @@ See the [example on GitHub](https://github.com/supabase/supabase/blob/master/exa ### Recommended setup -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: + -```ts cors.ts -export const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', -} -``` +**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. -You can then import and use the CORS headers within your functions: + + +Import `corsHeaders` from `@supabase/supabase-js/cors` to automatically get all required headers: ```ts index.ts -import { corsHeaders } from '../_shared/cors.ts' +import { corsHeaders } from '@supabase/supabase-js/cors' console.log(`Function "browser-with-cors" up and running!`) @@ -50,3 +47,24 @@ 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 +``` diff --git a/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx b/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx index 5bb06cb71e8..8d6c208e3c3 100644 --- a/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx +++ b/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx @@ -23,7 +23,7 @@ supabase functions new cloudflare-turnstile And add the code to the `index.ts` file: ```ts index.ts -import { corsHeaders } from '../_shared/cors.ts' +import { corsHeaders } from '@supabase/supabase-js/cors' // v2.95.0+ console.log('Hello from Cloudflare Trunstile!') diff --git a/apps/docs/content/guides/functions/troubleshooting.mdx b/apps/docs/content/guides/functions/troubleshooting.mdx index 39fe091cca9..2c538c71797 100644 --- a/apps/docs/content/guides/functions/troubleshooting.mdx +++ b/apps/docs/content/guides/functions/troubleshooting.mdx @@ -112,25 +112,26 @@ 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(null, { - status: 200, - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Authorization', - }, - }) + return new Response('ok', { headers: corsHeaders }) } // Your function logic here - return new Response('Success', { - headers: { 'Access-Control-Allow-Origin': '*' }, + return new Response(JSON.stringify({ status: 'Success' }), { + headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }) }) ``` + + +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. + + + 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. --- diff --git a/examples/edge-functions/supabase/functions/_shared/cors.ts b/examples/edge-functions/supabase/functions/_shared/cors.ts index 2ac4d89b14a..a418716bcf4 100644 --- a/examples/edge-functions/supabase/functions/_shared/cors.ts +++ b/examples/edge-functions/supabase/functions/_shared/cors.ts @@ -1,3 +1,11 @@ +// NOTE: For @supabase/supabase-js v2.95.0 and later, you can import CORS headers +// directly from the SDK instead of hardcoding them: +// +// import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors' +// +// This ensures your CORS headers stay synchronized with any new headers added to the SDK. +// For versions before 2.95.0, use this hardcoded configuration: + export const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', diff --git a/examples/edge-functions/supabase/functions/browser-with-cors/index.ts b/examples/edge-functions/supabase/functions/browser-with-cors/index.ts index 8028c11592a..ae656f8859d 100644 --- a/examples/edge-functions/supabase/functions/browser-with-cors/index.ts +++ b/examples/edge-functions/supabase/functions/browser-with-cors/index.ts @@ -2,7 +2,11 @@ // https://deno.land/manual/getting_started/setup_your_environment // This enables autocomplete, go to definition, etc. -import { corsHeaders } from '../_shared/cors.ts' +// For @supabase/supabase-js v2.95.0+, import CORS headers directly from the SDK: +import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors' + +// For older versions, use a shared cors.ts file: +// import { corsHeaders } from '../_shared/cors.ts' console.log(`Function "browser-with-cors" up and running!`) diff --git a/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts b/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts index 5d94fe3404f..f877a1c59b6 100644 --- a/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts +++ b/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts @@ -3,7 +3,10 @@ // This enables autocomplete, go to definition, etc. import { createClient } from 'npm:supabase-js@2' -import { corsHeaders } from '../_shared/cors.ts' +// New approach (v2.95.0+) +import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors' +// For older versions: +// import { corsHeaders } from '../_shared/cors.ts' console.log(`Function "get-tshirt-competition" up and running!`) diff --git a/examples/edge-functions/supabase/functions/read-storage/index.ts b/examples/edge-functions/supabase/functions/read-storage/index.ts index db5ea0a3488..72e492898ad 100644 --- a/examples/edge-functions/supabase/functions/read-storage/index.ts +++ b/examples/edge-functions/supabase/functions/read-storage/index.ts @@ -3,11 +3,13 @@ // This enables autocomplete, go to definition, etc. import { createClient } from 'npm:supabase-js@2' - -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey', -} +// New approach (v2.95.0+) +import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors' +// For older versions, use hardcoded headers: +// const corsHeaders = { +// 'Access-Control-Allow-Origin': '*', +// 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', +// } Deno.serve(async (req) => { // read a text file from storage and print its contents diff --git a/examples/edge-functions/supabase/functions/restful-tasks/index.ts b/examples/edge-functions/supabase/functions/restful-tasks/index.ts index 3b6084f2d69..3addd3448e9 100644 --- a/examples/edge-functions/supabase/functions/restful-tasks/index.ts +++ b/examples/edge-functions/supabase/functions/restful-tasks/index.ts @@ -3,12 +3,14 @@ // This enables autocomplete, go to definition, etc. import { createClient, SupabaseClient } from 'npm:supabase-js@2' - -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey', - 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE', -} +// New approach (v2.95.0+) +import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors' +// For older versions, use hardcoded headers: +// const corsHeaders = { +// 'Access-Control-Allow-Origin': '*', +// 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', +// 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE', +// } interface Task { name: string diff --git a/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts b/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts index c344baafe63..118f4c4593f 100644 --- a/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts +++ b/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts @@ -3,7 +3,10 @@ // This enables autocomplete, go to definition, etc. import { createClient } from 'npm:supabase-js@2' -import { corsHeaders } from '../_shared/cors.ts' +// New approach (v2.95.0+) +import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors' +// For older versions: +// import { corsHeaders } from '../_shared/cors.ts' console.log(`Function "select-from-table-with-auth-rls" up and running!`)