summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Arsh <69170106+lilnasy@users.noreply.github.com> 2024-01-31 06:07:25 +0000
committerGravatar GitHub <noreply@github.com> 2024-01-31 06:07:25 +0000
commit37369550ab57ca529fd6c796e5b0e96e897ca6e5 (patch)
treee03c132f84413694a209da512accd6f6cce2b66e
parenta8383173dac98d371a833c4c32de79f73bd9e9a4 (diff)
downloadastro-37369550ab57ca529fd6c796e5b0e96e897ca6e5.tar.gz
astro-37369550ab57ca529fd6c796e5b0e96e897ca6e5.tar.zst
astro-37369550ab57ca529fd6c796e5b0e96e897ca6e5.zip
fix(dev): prevent comma-separating multiple Set-Cookie headers (#9884)
* fix(dev): prevent comma-separating multiple Set-Cookie headers * add changeset * add test
-rw-r--r--.changeset/long-peaches-fetch.md5
-rw-r--r--packages/astro/src/vite-plugin-astro-server/response.ts10
-rw-r--r--packages/astro/test/units/vite-plugin-astro-server/response.test.js63
3 files changed, 70 insertions, 8 deletions
diff --git a/.changeset/long-peaches-fetch.md b/.changeset/long-peaches-fetch.md
new file mode 100644
index 000000000..810b067be
--- /dev/null
+++ b/.changeset/long-peaches-fetch.md
@@ -0,0 +1,5 @@
+---
+"astro": patch
+---
+
+Fixes an issue where multiple cookies were sent in a single Set-Cookie header in the dev mode.
diff --git a/packages/astro/src/vite-plugin-astro-server/response.ts b/packages/astro/src/vite-plugin-astro-server/response.ts
index ac36e703b..75649a714 100644
--- a/packages/astro/src/vite-plugin-astro-server/response.ts
+++ b/packages/astro/src/vite-plugin-astro-server/response.ts
@@ -62,16 +62,10 @@ export async function writeWebResponse(res: http.ServerResponse, webResponse: Re
res.setHeader('set-cookie', setCookieHeaders);
}
- const _headers = Object.fromEntries(headers.entries());
+ const _headers: http.OutgoingHttpHeaders = Object.fromEntries(headers.entries());
- // Undici 5.20.0+ includes a `getSetCookie` helper that returns an array of all the `set-cookies` headers.
- // Previously, `headers.entries()` would already have these merged, but it seems like this isn't the case anymore.
if (headers.has('set-cookie')) {
- if ('getSetCookie' in headers && typeof headers.getSetCookie === 'function') {
- _headers['set-cookie'] = headers.getSetCookie().toString();
- } else {
- _headers['set-cookie'] = headers.get('set-cookie')!;
- }
+ _headers['set-cookie'] = headers.getSetCookie();
}
res.writeHead(status, _headers);
diff --git a/packages/astro/test/units/vite-plugin-astro-server/response.test.js b/packages/astro/test/units/vite-plugin-astro-server/response.test.js
new file mode 100644
index 000000000..780a725f5
--- /dev/null
+++ b/packages/astro/test/units/vite-plugin-astro-server/response.test.js
@@ -0,0 +1,63 @@
+import {
+ createBasicSettings,
+ createFs,
+ createRequestAndResponse,
+ defaultLogger,
+} from '../test-utils.js';
+import { fileURLToPath } from 'node:url';
+import { expect } from 'chai';
+import { createContainer } from '../../../dist/core/dev/container.js';
+import testAdapter from '../../test-adapter.js';
+
+const root = new URL('../../fixtures/api-routes/', import.meta.url);
+const fileSystem = {
+ '/src/pages/index.js': `export const GET = () => {
+ const headers = new Headers();
+ headers.append('x-single', 'single');
+ headers.append('x-triple', 'one');
+ headers.append('x-triple', 'two');
+ headers.append('x-triple', 'three');
+ headers.append('Set-cookie', 'hello');
+ headers.append('Set-Cookie', 'world');
+ return new Response(null, { headers });
+ }`,
+};
+
+describe('endpoints', () => {
+ let container;
+ let settings;
+
+ before(async () => {
+ const fs = createFs(fileSystem, root);
+ settings = await createBasicSettings({
+ root: fileURLToPath(root),
+ output: 'server',
+ adapter: testAdapter(),
+ });
+ container = await createContainer({
+ fs,
+ settings,
+ logger: defaultLogger,
+ });
+ });
+
+ after(async () => {
+ await container.close();
+ });
+
+ it('Headers with multiple values (set-cookie special case)', async () => {
+ const { req, res, done } = createRequestAndResponse({
+ method: 'GET',
+ url: '/',
+ });
+ container.handle(req, res);
+ await done;
+ const headers = res.getHeaders();
+ expect(headers).to.deep.equal({
+ "access-control-allow-origin": "*",
+ 'x-single': 'single',
+ 'x-triple': 'one, two, three',
+ 'set-cookie': ['hello', 'world'],
+ });
+ });
+});