summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/shaggy-cats-film.md5
-rw-r--r--packages/astro/src/core/cookies/cookies.ts35
-rw-r--r--packages/astro/test/units/cookies/delete.test.js39
3 files changed, 57 insertions, 22 deletions
diff --git a/.changeset/shaggy-cats-film.md b/.changeset/shaggy-cats-film.md
new file mode 100644
index 000000000..4aaecea6c
--- /dev/null
+++ b/.changeset/shaggy-cats-film.md
@@ -0,0 +1,5 @@
+---
+"astro": minor
+---
+
+Adds the `httpOnly`, `sameSite`, and `secure` options when deleting a cookie
diff --git a/packages/astro/src/core/cookies/cookies.ts b/packages/astro/src/core/cookies/cookies.ts
index 862d86ff0..069afc796 100644
--- a/packages/astro/src/core/cookies/cookies.ts
+++ b/packages/astro/src/core/cookies/cookies.ts
@@ -2,22 +2,16 @@ import type { CookieSerializeOptions } from 'cookie';
import { parse, serialize } from 'cookie';
import { AstroError, AstroErrorData } from '../errors/index.js';
-export interface AstroCookieSetOptions {
- domain?: string;
- expires?: Date;
- httpOnly?: boolean;
- maxAge?: number;
- path?: string;
- sameSite?: boolean | 'lax' | 'none' | 'strict';
- secure?: boolean;
- encode?: (value: string) => string;
-}
+export type AstroCookieSetOptions = Pick<
+ CookieSerializeOptions,
+ 'domain' | 'path' | 'expires' | 'maxAge' | 'httpOnly' | 'sameSite' | 'secure' | 'encode'
+>;
export interface AstroCookieGetOptions {
decode?: (value: string) => string;
}
-type AstroCookieDeleteOptions = Pick<AstroCookieSetOptions, 'domain' | 'path'>;
+type AstroCookieDeleteOptions = Omit<AstroCookieSetOptions, 'expires' | 'maxAge' | 'encode'>;
interface AstroCookieInterface {
value: string;
@@ -78,17 +72,22 @@ class AstroCookies implements AstroCookiesInterface {
* @param options Options related to this deletion, such as the path of the cookie.
*/
delete(key: string, options?: AstroCookieDeleteOptions): void {
+ /**
+ * The `@ts-expect-error` is necessary because `maxAge` and `expires` properties
+ * must not appear in the AstroCookieDeleteOptions type.
+ */
+ const {
+ // @ts-expect-error
+ maxAge: _ignoredMaxAge,
+ // @ts-expect-error
+ expires: _ignoredExpires,
+ ...sanitizedOptions
+ } = options || {};
const serializeOptions: CookieSerializeOptions = {
expires: DELETED_EXPIRATION,
+ ...sanitizedOptions,
};
- if (options?.domain) {
- serializeOptions.domain = options.domain;
- }
- if (options?.path) {
- serializeOptions.path = options.path;
- }
-
// Set-Cookie: token=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT
this.#ensureOutgoingMap().set(key, [
DELETED_VALUE,
diff --git a/packages/astro/test/units/cookies/delete.test.js b/packages/astro/test/units/cookies/delete.test.js
index 4b5f188e1..39a5d7dae 100644
--- a/packages/astro/test/units/cookies/delete.test.js
+++ b/packages/astro/test/units/cookies/delete.test.js
@@ -47,26 +47,57 @@ describe('astro/src/core/cookies', () => {
assert.equal(cookies.has('foo'), false);
});
- it('can provide a path', () => {
+ it('deletes a cookie with attributes', () => {
let req = new Request('http://example.com/');
let cookies = new AstroCookies(req);
+
cookies.delete('foo', {
+ domain: 'example.com',
path: '/subpath/',
+ priority: 'high',
+ secure: true,
+ httpOnly: true,
+ sameSite: 'strict',
});
+
let headers = Array.from(cookies.headers());
assert.equal(headers.length, 1);
+ assert.equal(/foo=deleted/.test(headers[0]), true);
+ assert.equal(/Expires=Thu, 01 Jan 1970 00:00:00 GMT/.test(headers[0]), true);
+ assert.equal(/Domain=example.com/.test(headers[0]), true);
assert.equal(/Path=\/subpath\//.test(headers[0]), true);
+ assert.equal(/Priority=High/.test(headers[0]), true);
+ assert.equal(/Secure/.test(headers[0]), true);
+ assert.equal(/HttpOnly/.test(headers[0]), true);
+ assert.equal(/SameSite=Strict/.test(headers[0]), true);
+ });
+
+ it('ignores expires option', () => {
+ let req = new Request('http://example.com/');
+ let cookies = new AstroCookies(req);
+
+ cookies.delete('foo', {
+ expires: new Date(),
+ });
+
+ let headers = Array.from(cookies.headers());
+ assert.equal(headers.length, 1);
+ assert.equal(/foo=deleted/.test(headers[0]), true);
+ assert.equal(/Expires=Thu, 01 Jan 1970 00:00:00 GMT/.test(headers[0]), true);
});
- it('can provide a domain', () => {
+ it('ignores maxAge option', () => {
let req = new Request('http://example.com/');
let cookies = new AstroCookies(req);
+
cookies.delete('foo', {
- domain: '.example.com',
+ maxAge: 60,
});
+
let headers = Array.from(cookies.headers());
assert.equal(headers.length, 1);
- assert.equal(/Domain=\.example\.com/.test(headers[0]), true);
+ assert.equal(/foo=deleted/.test(headers[0]), true);
+ assert.equal(/Expires=Thu, 01 Jan 1970 00:00:00 GMT/.test(headers[0]), true);
});
});
});