Set session cookies via NextResponse.cookies.set for reliability (handshake + sessions)

This commit is contained in:
Esdras Renan 2025-10-14 21:33:11 -03:00
parent f1f52f7c30
commit b703561a7e
2 changed files with 70 additions and 5 deletions

View file

@ -59,9 +59,41 @@ export async function POST(request: Request) {
if (single) setCookies.push(single)
}
for (const cookie of setCookies) {
// Usa append para não sobrescrever múltiplos cookies (authsession e assinatura, por exemplo)
response.headers.append("set-cookie", cookie)
// Converte os Set-Cookie recebidos em cookies do Next (maior compatibilidade)
const toPairs = (raw: string) => {
const [nameValue, ...attrs] = raw.split(/;\s*/)
const [name, ...v] = nameValue.split("=")
const value = v.join("=")
const record: Record<string, string | boolean> = { name, value }
for (const attr of attrs) {
const [k, ...vv] = attr.split("=")
const key = k.toLowerCase()
const val = vv.join("=")
if (!val && (key === "httponly" || key === "secure")) {
record[key] = true
} else if (val) {
record[key] = val
}
}
return record
}
for (const raw of setCookies) {
const rec = toPairs(raw)
const name = String(rec.name)
const value = String(rec.value)
const options: Parameters<typeof response.cookies.set>[1] = {
httpOnly: Boolean(rec["httponly"]) || /httponly/i.test(raw),
secure: /;\s*secure/i.test(raw),
path: typeof rec["path"] === "string" ? (rec["path"] as string) : "/",
}
if (typeof rec["samesite"] === "string") {
const s = String(rec["samesite"]).toLowerCase() as "lax" | "strict" | "none"
options.sameSite = s
}
if (typeof rec["domain"] === "string") options.domain = rec["domain"] as string
if (typeof rec["expires"] === "string") options.expires = new Date(rec["expires"] as string)
if (typeof rec["max-age"] === "string") options.maxAge = Number(rec["max-age"])
response.cookies.set(name, value, options)
}
const machineCookiePayload = {

View file

@ -65,8 +65,41 @@ export async function GET(request: NextRequest) {
if (single) setCookies = [single]
}
for (const cookie of setCookies) {
response.headers.append("set-cookie", cookie)
// Converte os Set-Cookie recebidos em cookies do Next (maior compatibilidade)
const toPairs = (raw: string) => {
const [nameValue, ...attrs] = raw.split(/;\s*/)
const [name, ...v] = nameValue.split("=")
const value = v.join("=")
const record: Record<string, string | boolean> = { name, value }
for (const attr of attrs) {
const [k, ...vv] = attr.split("=")
const key = k.toLowerCase()
const val = vv.join("=")
if (!val && (key === "httponly" || key === "secure")) {
record[key] = true
} else if (val) {
record[key] = val
}
}
return record
}
for (const raw of setCookies) {
const rec = toPairs(raw)
const name = String(rec.name)
const value = String(rec.value)
const options: Parameters<typeof response.cookies.set>[1] = {
httpOnly: Boolean(rec["httponly"]) || /httponly/i.test(raw),
secure: /;\s*secure/i.test(raw),
path: typeof rec["path"] === "string" ? (rec["path"] as string) : "/",
}
if (typeof rec["samesite"] === "string") {
const s = String(rec["samesite"]).toLowerCase() as "lax" | "strict" | "none"
options.sameSite = s
}
if (typeof rec["domain"] === "string") options.domain = rec["domain"] as string
if (typeof rec["expires"] === "string") options.expires = new Date(rec["expires"] as string)
if (typeof rec["max-age"] === "string") options.maxAge = Number(rec["max-age"])
response.cookies.set(name, value, options)
}
const machineCookiePayload = {