Skip to content

Commit

Permalink
fix: [#1570] Cookies with values that contains = should be supported (
Browse files Browse the repository at this point in the history
#1573)

* fix: [#1570] Cookie value support contain `=`

* chore: [#1570] Changed logic to improve performance

---------

Co-authored-by: David Ortner <david@ortner.se>
  • Loading branch information
btea and capricorn86 authored Nov 6, 2024
1 parent f5e1722 commit 1416396
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
16 changes: 10 additions & 6 deletions packages/happy-dom/src/cookie/urilities/CookieStringUtility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ export default class CookieStringUtility {
*/
public static stringToCookie(originURL: URL, cookieString: string): ICookie | null {
const parts = cookieString.split(';');
const [key, value] = parts.shift().split('=');
const part = parts.shift();
const index = part.indexOf('=');
const key = index !== -1 ? part.slice(0, index).trim() : part.trim();
const value = index !== -1 ? part.slice(index + 1).trim() : null;

const cookie: ICookie = {
// Required
key: key.trim(),
value: value ?? null,
key,
value,
originURL,

// Optional
Expand All @@ -38,9 +41,10 @@ export default class CookieStringUtility {
}

for (const part of parts) {
const keyAndValue = part.split('=');
const key = keyAndValue[0].trim().toLowerCase();
const value = keyAndValue[1];
const index = part.indexOf('=');
const key =
index !== -1 ? part.slice(0, index).trim().toLowerCase() : part.trim().toLowerCase();
const value = index !== -1 ? part.slice(index + 1).trim() : '';

switch (key) {
case 'expires':
Expand Down
31 changes: 20 additions & 11 deletions packages/happy-dom/test/cookie/CookieContainer.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import CookieContainer from '../../src/cookie/CookieContainer.js';
import ICookie from '../../src/cookie/types/ICookie.js';
import ICookieContainer from '../../src/cookie/types/ICookieContainer.js';
import ICookie from '../../src/cookie/ICookie.js';
import ICookieContainer from '../../src/cookie/ICookieContainer.js';
import CookieStringUtility from '../../src/cookie/urilities/CookieStringUtility.js';
import URL from '../../src/url/URL.js';
import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest';
Expand Down Expand Up @@ -29,7 +29,9 @@ describe('CookieContainer', () => {
`key1=value1; Expires=${new Date(expires).toString()};`
)
),
<ICookie>CookieStringUtility.stringToCookie(originURL, `key2=value2; Max-Age=${maxAge};`),
<ICookie>(
CookieStringUtility.stringToCookie(originURL, `key2 = value2 ; Max-Age=${maxAge};`)
),
<ICookie>CookieStringUtility.stringToCookie(originURL, `key3=value3; Domain=example.com;`),
<ICookie>CookieStringUtility.stringToCookie(originURL, `key4=value4; Domain=other.com;`),
<ICookie>(
Expand All @@ -50,30 +52,33 @@ describe('CookieContainer', () => {
<ICookie>(
CookieStringUtility.stringToCookie(originURL, `key10=value10; SameSite=None; Secure;`)
),
<ICookie>CookieStringUtility.stringToCookie(originURL, `key10;`)
<ICookie>CookieStringUtility.stringToCookie(originURL, `key10;`),
<ICookie>CookieStringUtility.stringToCookie(originURL, `key11=hello=world;`)
]);

expect(
CookieStringUtility.cookiesToString(
cookieContainer.getCookies(new URL('https://example.com/path/to/page/'), false)
)
).toBe(
'key1=value1; key2=value2; key3=value3; key7=value7; key8=value8; key9=value9; key10=value10; key10'
'key1=value1; key2=value2; key3=value3; key7=value7; key8=value8; key9=value9; key10=value10; key10; key11=hello=world'
);

expect(
CookieStringUtility.cookiesToString(
cookieContainer.getCookies(new URL('https://example.com/path/to/page/'), true)
)
).toBe(
'key1=value1; key2=value2; key3=value3; key7=value7; key9=value9; key10=value10; key10'
'key1=value1; key2=value2; key3=value3; key7=value7; key9=value9; key10=value10; key10; key11=hello=world'
);

expect(
CookieStringUtility.cookiesToString(
cookieContainer.getCookies(new URL('http://example.com/path/to/page/'), false)
)
).toBe('key1=value1; key2=value2; key3=value3; key7=value7; key8=value8; key10');
).toBe(
'key1=value1; key2=value2; key3=value3; key7=value7; key8=value8; key10; key11=hello=world'
);

expect(
CookieStringUtility.cookiesToString(
Expand All @@ -90,7 +95,7 @@ describe('CookieContainer', () => {
cookieContainer.getCookies(new URL('https://example.com/path/to/page/'), false)
)
).toBe(
'key1=value1; key2=value2; key3=value3; key7=value7; key8=value8; key9=value9; key10; key10=newValue10'
'key1=value1; key2=value2; key3=value3; key7=value7; key8=value8; key9=value9; key10; key11=hello=world; key10=newValue10'
);

expect(
Expand All @@ -105,7 +110,9 @@ describe('CookieContainer', () => {
CookieStringUtility.cookiesToString(
cookieContainer.getCookies(new URL('https://example.com/path/to/page/'), false)
)
).toBe('key3=value3; key7=value7; key8=value8; key9=value9; key10; key10=newValue10');
).toBe(
'key3=value3; key7=value7; key8=value8; key9=value9; key10; key11=hello=world; key10=newValue10'
);

cookieContainer.addCookies([
<ICookie>(
Expand All @@ -120,7 +127,9 @@ describe('CookieContainer', () => {
CookieStringUtility.cookiesToString(
cookieContainer.getCookies(new URL('https://example.com/path/to/page/'), false)
)
).toBe('key3=value3; key7=value7; key8=value8; key9=value9; key10=newValue10');
).toBe(
'key3=value3; key7=value7; key8=value8; key9=value9; key11=hello=world; key10=newValue10'
);

cookieContainer.addCookies([
<ICookie>(
Expand All @@ -135,7 +144,7 @@ describe('CookieContainer', () => {
CookieStringUtility.cookiesToString(
cookieContainer.getCookies(new URL('https://example.com/path/to/page/'), false)
)
).toBe('key3=value3; key7=value7; key8=value8; key9=value9');
).toBe('key3=value3; key7=value7; key8=value8; key9=value9; key11=hello=world');
});

it('Validates secure cookie keys.', () => {
Expand Down

0 comments on commit 1416396

Please sign in to comment.