diff --git a/.changeset/nervous-beans-roll.md b/.changeset/nervous-beans-roll.md new file mode 100644 index 000000000000..fe958273bab0 --- /dev/null +++ b/.changeset/nervous-beans-roll.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': minor +--- + +feat: add `cookies.getAll` diff --git a/packages/kit/src/runtime/server/cookie.js b/packages/kit/src/runtime/server/cookie.js index 249dd15963d6..c1bb5adec5cc 100644 --- a/packages/kit/src/runtime/server/cookie.js +++ b/packages/kit/src/runtime/server/cookie.js @@ -98,6 +98,25 @@ export function get_cookies(request, url, trailing_slash) { } }, + /** + * @param {import('cookie').CookieParseOptions} opts + */ + getAll(opts) { + const decoder = opts?.decode || decodeURIComponent; + const cookies = parse(header, { decode: decoder }); + + for (const c of Object.values(new_cookies)) { + if ( + domain_matches(url.hostname, c.options.domain) && + path_matches(url.pathname, c.options.path) + ) { + cookies[c.name] = c.value; + } + } + + return Object.entries(cookies).map(([name, value]) => ({ name, value })); + }, + /** * @param {string} name * @param {string} value diff --git a/packages/kit/src/runtime/server/cookie.spec.js b/packages/kit/src/runtime/server/cookie.spec.js index 77581abacdfa..d8a4eab18abd 100644 --- a/packages/kit/src/runtime/server/cookie.spec.js +++ b/packages/kit/src/runtime/server/cookie.spec.js @@ -181,4 +181,18 @@ test('warns if cookie exceeds 4,129 bytes', () => { globalThis.__SVELTEKIT_DEV__ = false; }); +test('get all cookies from header and set calls', () => { + const { cookies } = cookies_setup(); + assert.equal(cookies.getAll(), [{ name: 'a', value: 'b' }]); + + cookies.set('a', 'foo'); + cookies.set('a', 'bar'); + cookies.set('b', 'baz'); + + assert.equal(cookies.getAll(), [ + { name: 'a', value: 'bar' }, + { name: 'b', value: 'baz' } + ]); +}); + test.run(); diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 96201c6d3e59..58027c9c872b 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -198,7 +198,13 @@ export interface Cookies { get(name: string, opts?: import('cookie').CookieParseOptions): string | undefined; /** - * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` during the current request. + * Gets all cookies that were previously set with `cookies.set`, or from the request headers. + * @param opts the options, passed directily to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) + */ + getAll(opts?: import('cookie').CookieParseOptions): Array<{ name: string; value: string }>; + + /** + * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request. * * The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`. *