mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
docs: update setAll callbacks to accept cache headers second argument (#44240)
## What Updates all `setAll` cookie handler implementations across docs and examples to accept the new `headers` second argument introduced in `@supabase/ssr` v0.10.0 ([supabase/ssr#176](https://github.com/supabase/ssr/pull/176)). ## Why `@supabase/ssr` v0.10.0 introduced a breaking change: `setAll` now receives a required second argument `headers: Record<string, string>` alongside the cookies array. When a token refresh occurs, the library passes cache headers (`Cache-Control`, `Expires`, `Pragma`) that must be applied to the HTTP response to prevent CDN caching of auth responses. Because TypeScript allows functions with fewer parameters to satisfy a type expecting more, existing `setAll` implementations do not produce a type error when the second argument is omitted. Users who copy an outdated snippet will silently miss the CDN protection. Root cause and context: [supabase/supabase-js#1682](https://github.com/supabase/supabase-js/issues/1682) ## Changes **Proxy/middleware contexts** (where token refreshes happen) now apply the cache headers to their response: - Next.js proxy files: `supabaseResponse.headers.set(key, value)` - SvelteKit hooks: `event.setHeaders(headers)` - Hono middleware: `c.header(key, value)` - Pages Router (Express-style): `ctx.res.setHeader(key, value)` - Remix/React Router loaders and actions: applied to response headers (outer `headers` variable renamed to `responseHeaders` to avoid naming conflict with the new param) **Server Component and API route contexts** (no response object available) accept `_headers` without applying them. ## Files updated - `apps/docs/content/guides/auth/server-side/creating-a-client.mdx` (inline Astro, Remix, React Router, Express snippets) - `apps/docs/content/_partials/oauth_pkce_flow.mdx` - `apps/docs/content/guides/auth/oauth-server/getting-started.mdx` - `apps/docs/content/guides/auth/passwords.mdx` - `apps/docs/content/troubleshooting/how-to-migrate-from-supabase-auth-helpers-to-ssr-package-5NRunM.mdx` - `examples/auth/nextjs/`, `examples/auth/nextjs-full/` (proxy + server) - `examples/auth/sveltekit/`, `examples/auth/sveltekit-full/` - `examples/auth/hono/`, `examples/auth/hono-full/` - `examples/user-management/nextjs-user-management/` (proxy + server) - `examples/user-management/sveltekit-user-management/` - `examples/realtime/nextjs-authorization-demo/` (proxy + server) - `examples/realtime/nextjs-auth-presence/` (pages router) - `examples/prompts/nextjs-supabase-auth.md`
This commit is contained in:
1 parent
edacf2413d
commit
41f9ddd70c
22 files changed
+105
-57
No files matched your search
@@ -39,8 +39,9 @@ export const supabaseMiddleware = (): MiddlewareHandler => {
|
||||
getAll() {
|
||||
return parseCookieHeader(c.req.header('Cookie') ?? '')
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, cacheHeaders) {
|
||||
cookiesToSet.forEach(({ name, value, options }) => setCookie(c, name, value, options))
|
||||
Object.entries(cacheHeaders).forEach(([key, value]) => c.header(key, value))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -38,8 +38,9 @@ export const supabaseMiddleware = (): MiddlewareHandler => {
|
||||
getAll() {
|
||||
return parseCookieHeader(c.req.header('Cookie') ?? '')
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, cacheHeaders) {
|
||||
cookiesToSet.forEach(({ name, value, options }) => setCookie(c, name, value, options))
|
||||
Object.entries(cacheHeaders).forEach(([key, value]) => c.header(key, value))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function updateSession(request: NextRequest) {
|
||||
getAll() {
|
||||
return request.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
|
||||
supabaseResponse = NextResponse.next({
|
||||
request,
|
||||
@@ -24,6 +24,9 @@ export async function updateSession(request: NextRequest) {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
)
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
supabaseResponse.headers.set(key, value)
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export async function createClient() {
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, _headers) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function updateSession(request: NextRequest) {
|
||||
getAll() {
|
||||
return request.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
|
||||
supabaseResponse = NextResponse.next({
|
||||
request,
|
||||
@@ -24,6 +24,9 @@ export async function updateSession(request: NextRequest) {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
)
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
supabaseResponse.headers.set(key, value)
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export async function createClient() {
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, _headers) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
|
||||
@@ -18,10 +18,13 @@ const supabase: Handle = async ({ event, resolve }) => {
|
||||
* the cookie options. Setting `path` to `/` replicates previous/
|
||||
* standard behavior.
|
||||
*/
|
||||
setAll: (cookiesToSet) => {
|
||||
setAll: (cookiesToSet, headers) => {
|
||||
cookiesToSet.forEach(({ name, value, options }) => {
|
||||
event.cookies.set(name, value, { ...options, path: '/' })
|
||||
})
|
||||
if (Object.keys(headers).length > 0) {
|
||||
event.setHeaders(headers)
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ export const handle: Handle = async ({ event, resolve }) => {
|
||||
getAll() {
|
||||
return event.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
/**
|
||||
* Note: You have to add the `path` variable to the
|
||||
* set and remove method due to sveltekit's cookie API
|
||||
@@ -18,6 +18,9 @@ export const handle: Handle = async ({ event, resolve }) => {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
event.cookies.set(name, value, { ...options, path: '/' })
|
||||
)
|
||||
if (Object.keys(headers).length > 0) {
|
||||
event.setHeaders(headers)
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -47,7 +47,7 @@ Instead, you MUST ALWAYS generate ONLY this pattern:
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
const response = NextResponse.next({
|
||||
request,
|
||||
})
|
||||
@@ -55,6 +55,9 @@ Instead, you MUST ALWAYS generate ONLY this pattern:
|
||||
cookiesToSet.forEach(({ name, value, options }) => {
|
||||
response.cookies.set(name, value, options)
|
||||
})
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
response.headers.set(key, value)
|
||||
)
|
||||
|
||||
return response
|
||||
}
|
||||
@@ -99,7 +102,7 @@ export async function createClient() {
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, _headers) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
@@ -135,14 +138,17 @@ export async function proxy(request: NextRequest) {
|
||||
getAll() {
|
||||
return request.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
|
||||
setAll(cookiesToSet, headers) {
|
||||
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
|
||||
supabaseResponse = NextResponse.next({
|
||||
request,
|
||||
})
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
)
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
supabaseResponse.headers.set(key, value)
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -66,12 +66,13 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
value: value ?? '',
|
||||
}))
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
const existing = ctx.res.getHeader('Set-Cookie') ?? []
|
||||
ctx.res.setHeader('Set-Cookie', [
|
||||
...(Array.isArray(existing) ? existing : [String(existing)]),
|
||||
...cookiesToSet.map(({ name, value, options }) => serialize(name, value, options)),
|
||||
])
|
||||
Object.entries(headers).forEach(([key, value]) => ctx.res.setHeader(key, value))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -28,12 +28,13 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
value: value ?? '',
|
||||
}))
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
const existing = ctx.res.getHeader('Set-Cookie') ?? []
|
||||
ctx.res.setHeader('Set-Cookie', [
|
||||
...(Array.isArray(existing) ? existing : [String(existing)]),
|
||||
...cookiesToSet.map(({ name, value, options }) => serialize(name, value, options)),
|
||||
])
|
||||
Object.entries(headers).forEach(([key, value]) => ctx.res.setHeader(key, value))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -15,12 +15,15 @@ export const updateSession = async (request: NextRequest) => {
|
||||
getAll() {
|
||||
return request.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, headers) {
|
||||
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
|
||||
supabaseResponse = NextResponse.next({ request })
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
)
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
supabaseResponse.headers.set(key, value)
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export const createClient = async () => {
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, _headers) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
|
||||
@@ -14,14 +14,17 @@ export async function updateSession(request: NextRequest) {
|
||||
getAll() {
|
||||
return request.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
|
||||
setAll(cookiesToSet, headers) {
|
||||
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
|
||||
supabaseResponse = NextResponse.next({
|
||||
request,
|
||||
})
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
)
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
supabaseResponse.headers.set(key, value)
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export async function createClient() {
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
setAll(cookiesToSet, _headers) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
|
||||
@@ -13,10 +13,13 @@ export const handle: Handle = async ({ event, resolve }) => {
|
||||
* requiring this to be set, setting the path to `/`
|
||||
* will replicate previous/standard behaviour (https://kit.svelte.dev/docs/types#public-types-cookies)
|
||||
*/
|
||||
setAll: (cookiesToSet) => {
|
||||
setAll: (cookiesToSet, headers) => {
|
||||
cookiesToSet.forEach(({ name, value, options }) => {
|
||||
event.cookies.set(name, value, { ...options, path: '/' })
|
||||
})
|
||||
if (Object.keys(headers).length > 0) {
|
||||
event.setHeaders(headers)
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user