diff --git a/src/cookie/parse.ts b/src/cookie/parse.ts index e75e3a4..76fa800 100644 --- a/src/cookie/parse.ts +++ b/src/cookie/parse.ts @@ -19,9 +19,10 @@ export function parse( throw new TypeError("argument str must be a string"); } - const obj = {}; + const obj: Record = {}; const opt = options || {}; const dec = opt.decode || decode; + const allowMultiple = opt.allowMultiple || false; let index = 0; while (index < str.length) { @@ -48,16 +49,24 @@ export function parse( continue; } - // only assign once - if (undefined === obj[key as keyof typeof obj]) { - let val = str.slice(eqIdx + 1, endIdx).trim(); + let val = str.slice(eqIdx + 1, endIdx).trim(); - // quoted values - if (val.codePointAt(0) === 0x22) { - val = val.slice(1, -1); - } + // quoted values + if (val.codePointAt(0) === 0x22) { + val = val.slice(1, -1); + } - (obj as any)[key] = tryDecode(val, dec); + val = tryDecode(val, dec); + + // handle multiple values for the same key + // TODO: enable by default in v2 + if (allowMultiple) { + obj[key] = + obj[key] === undefined || obj[key] === "" ? val : `${obj[key]},${val}`; + } else { + if (obj[key] === undefined) { + obj[key] = val; + } } index = endIdx + 1; diff --git a/src/cookie/types.ts b/src/cookie/types.ts index 0f7e3da..358cd83 100644 --- a/src/cookie/types.ts +++ b/src/cookie/types.ts @@ -142,4 +142,8 @@ export interface CookieParseOptions { * Custom function to filter parsing specific keys. */ filter?(key: string): boolean; + /** + * Flag to allow to return multiple values when cookie is duplicated. + */ + allowMultiple?: boolean; } diff --git a/test/cookie-parse.test.ts b/test/cookie-parse.test.ts index 7b0eb55..da7a8c4 100644 --- a/test/cookie-parse.test.ts +++ b/test/cookie-parse.test.ts @@ -61,6 +61,27 @@ describe("cookie.parse(str)", () => { bar: "bar", }); }); + + it("should return duplicated cookies values if `allowMultiple` is set", () => { + expect( + parse("foo=%1;bar=bar;foo=boo", { allowMultiple: true }), + ).toMatchObject({ + foo: "%1,boo", + bar: "bar", + }); + expect( + parse("foo=false;bar=bar;foo=true", { allowMultiple: true }), + ).toMatchObject({ + foo: "false,true", + bar: "bar", + }); + expect( + parse("foo=;bar=bar;foo=boo", { allowMultiple: true }), + ).toMatchObject({ + foo: "boo", + bar: "bar", + }); + }); }); describe("cookie.parse(str, options)", () => {