fix(nuxt): omit Set-Cookie header if value is null (#21072)

This commit is contained in:
Louis Haftmann 2023-05-26 21:42:12 +02:00 committed by GitHub
parent bd4f9acdbc
commit 92bc999d0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 3 deletions

View File

@ -2,7 +2,7 @@ import type { Ref } from 'vue'
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import type { CookieParseOptions, CookieSerializeOptions } from 'cookie-es' import type { CookieParseOptions, CookieSerializeOptions } from 'cookie-es'
import { parse, serialize } from 'cookie-es' import { parse, serialize } from 'cookie-es'
import { appendResponseHeader } from 'h3' import { deleteCookie, getCookie, setCookie } from 'h3'
import type { H3Event } from 'h3' import type { H3Event } from 'h3'
import destr from 'destr' import destr from 'destr'
import { isEqual } from 'ohash' import { isEqual } from 'ohash'
@ -80,7 +80,16 @@ function writeClientCookie (name: string, value: any, opts: CookieSerializeOptio
function writeServerCookie (event: H3Event, name: string, value: any, opts: CookieSerializeOptions = {}) { function writeServerCookie (event: H3Event, name: string, value: any, opts: CookieSerializeOptions = {}) {
if (event) { if (event) {
// TODO: Try to smart join with existing Set-Cookie headers // update if value is set
appendResponseHeader(event, 'Set-Cookie', serializeCookie(name, value, opts)) if (value !== null && value !== undefined) {
return setCookie(event, name, value, opts)
}
// delete if cookie exists in browser and value is null/undefined
if (getCookie(event, name) !== undefined) {
return deleteCookie(event, name, opts)
}
// else ignore if cookie doesn't exist in browser and value is null/undefined
} }
} }

View File

@ -399,6 +399,21 @@ describe('nuxt composables', () => {
const html = await $fetch('/url') const html = await $fetch('/url')
expect(html).toContain('path: /url') expect(html).toContain('path: /url')
}) })
it('sets cookies correctly', async () => {
const res = await fetch('/cookies', {
headers: {
cookie: Object.entries({
'browser-accessed-but-not-used': 'provided-by-browser',
'browser-accessed-with-default-value': 'provided-by-browser',
'browser-set': 'provided-by-browser',
'browser-set-to-null': 'provided-by-browser',
'browser-set-to-null-with-default': 'provided-by-browser'
}).map(([key, value]) => `${key}=${value}`).join('; ')
}
})
const cookies = res.headers.get('set-cookie')
expect(cookies).toMatchInlineSnapshot('"set-in-plugin=true; Path=/, set=set; Path=/, browser-set=set; Path=/, browser-set-to-null=; Max-Age=0; Path=/, browser-set-to-null-with-default=; Max-Age=0; Path=/"')
})
}) })
describe('rich payloads', () => { describe('rich payloads', () => {

19
test/fixtures/basic/pages/cookies.vue vendored Normal file
View File

@ -0,0 +1,19 @@
<script setup>
useCookie('accessed-but-not-used')
useCookie('accessed-with-default-value', () => 'default')
useCookie('set').value = 'set'
useCookie('set-to-null').value = null
useCookie('set-to-null-with-default', () => 'default').value = null
// the next set are all sent by browser
useCookie('browser-accessed-but-not-used')
useCookie('browser-accessed-with-default-value', () => 'default')
useCookie('browser-set').value = 'set'
useCookie('browser-set-to-null').value = null
useCookie('browser-set-to-null-with-default', () => 'default').value = null
</script>
<template>
<div>
<div>cookies testing page</div>
</div>
</template>