mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
qol(cookies): warn when cookies are set after the headers have been sent (#9627)
This commit is contained in:
parent
a4f90d95ff
commit
a700a20291
3 changed files with 28 additions and 2 deletions
5
.changeset/kind-waves-travel.md
Normal file
5
.changeset/kind-waves-travel.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Adds a warning when setting cookies will have no effect
|
|
@ -63,10 +63,12 @@ class AstroCookies implements AstroCookiesInterface {
|
||||||
#request: Request;
|
#request: Request;
|
||||||
#requestValues: Record<string, string> | null;
|
#requestValues: Record<string, string> | null;
|
||||||
#outgoing: Map<string, [string, string, boolean]> | null;
|
#outgoing: Map<string, [string, string, boolean]> | null;
|
||||||
|
#consumed: boolean;
|
||||||
constructor(request: Request) {
|
constructor(request: Request) {
|
||||||
this.#request = request;
|
this.#request = request;
|
||||||
this.#requestValues = null;
|
this.#requestValues = null;
|
||||||
this.#outgoing = null;
|
this.#outgoing = null;
|
||||||
|
this.#consumed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,6 +150,16 @@ class AstroCookies implements AstroCookiesInterface {
|
||||||
* @param options Options for the cookie, such as the path and security settings.
|
* @param options Options for the cookie, such as the path and security settings.
|
||||||
*/
|
*/
|
||||||
set(key: string, value: string | Record<string, any>, options?: AstroCookieSetOptions): void {
|
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;
|
let serializedValue: string;
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
serializedValue = value;
|
serializedValue = value;
|
||||||
|
@ -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> {
|
#ensureParsed(options: AstroCookieGetOptions | undefined = undefined): Record<string, string> {
|
||||||
if (!this.#requestValues) {
|
if (!this.#requestValues) {
|
||||||
this.#parse(options);
|
this.#parse(options);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { AstroCookies } from './cookies.js';
|
import { AstroCookies } from './cookies.js';
|
||||||
|
|
||||||
const astroCookiesSymbol = Symbol.for('astro.cookies');
|
const astroCookiesSymbol = Symbol.for('astro.cookies');
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export function* getSetCookiesFromResponse(response: Response): Generator<string
|
||||||
if (!cookies) {
|
if (!cookies) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
for (const headerValue of cookies.headers()) {
|
for (const headerValue of AstroCookies.consume(cookies)) {
|
||||||
yield headerValue;
|
yield headerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue