Skip to content

Commit

Permalink
qol(cookies): warn when cookies are set after the headers have been s…
Browse files Browse the repository at this point in the history
…ent (#9627)
  • Loading branch information
lilnasy authored Jan 10, 2024
1 parent a4f90d9 commit a700a20
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-waves-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Adds a warning when setting cookies will have no effect
21 changes: 21 additions & 0 deletions packages/astro/src/core/cookies/cookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@ class AstroCookies implements AstroCookiesInterface {
#request: Request;
#requestValues: Record<string, string> | null;
#outgoing: Map<string, [string, string, boolean]> | null;
#consumed: boolean;
constructor(request: Request) {
this.#request = request;
this.#requestValues = null;
this.#outgoing = null;
this.#consumed = false;
}

/**
Expand Down Expand Up @@ -148,6 +150,16 @@ class AstroCookies implements AstroCookiesInterface {
* @param options Options for the cookie, such as the path and security settings.
*/
set(key: string, value: string | Record<string, any>, options?: AstroCookieSetOptions): void {
if (this.#consumed) {
const warning = new Error(
'Astro.cookies.set() was called after the cookies had already been sent to the browser.\n' +
'This may have happened if this method was called in an imported component.\n' +
'Please make sure that Astro.cookies.set() is only called in the frontmatter of the main page.'
);
warning.name = "Warning";
// eslint-disable-next-line no-console
console.warn(warning);
}
let serializedValue: string;
if (typeof value === 'string') {
serializedValue = value;
Expand Down Expand Up @@ -193,6 +205,15 @@ class AstroCookies implements AstroCookiesInterface {
}
}

/**
* Behaves the same as AstroCookies.prototype.headers(),
* but allows a warning when cookies are set after the instance is consumed.
*/
static consume(cookies: AstroCookies): Generator<string, void, unknown> {
cookies.#consumed = true;
return cookies.headers();
}

#ensureParsed(options: AstroCookieGetOptions | undefined = undefined): Record<string, string> {
if (!this.#requestValues) {
this.#parse(options);
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/cookies/response.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AstroCookies } from './cookies.js';
import { AstroCookies } from './cookies.js';

const astroCookiesSymbol = Symbol.for('astro.cookies');

Expand All @@ -24,7 +24,7 @@ export function* getSetCookiesFromResponse(response: Response): Generator<string
if (!cookies) {
return [];
}
for (const headerValue of cookies.headers()) {
for (const headerValue of AstroCookies.consume(cookies)) {
yield headerValue;
}

Expand Down

0 comments on commit a700a20

Please sign in to comment.