0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-23 21:53:55 -05:00

fix(dev): prevent comma-separating multiple Set-Cookie headers (#9884)

* fix(dev): prevent comma-separating multiple Set-Cookie headers

* add changeset

* add test
This commit is contained in:
Arsh 2024-01-31 06:07:25 +00:00 committed by GitHub
parent a8383173da
commit 37369550ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 70 additions and 8 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Fixes an issue where multiple cookies were sent in a single Set-Cookie header in the dev mode.

View file

@ -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);

View file

@ -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'],
});
});
});