diff --git a/src/parse-cookies.ts b/src/parse-cookies.ts index 8f9451f..2601869 100644 --- a/src/parse-cookies.ts +++ b/src/parse-cookies.ts @@ -1,13 +1,39 @@ const parseCookies = (s: string): { [key: string]: string } => { if (s.length === 0) return {}; const parsed: { [key: string]: string } = {}; - const pattern = new RegExp("\\s*;\\s*"); - s.split(pattern).forEach((i) => { - const [encodedKey, encodedValue] = i.split("="); - const key = decodeURIComponent(encodedKey); - const value = decodeURIComponent(encodedValue); - parsed[key] = value; - }); + const pairs = s.split(';') + + for (let i = 0; i < pairs.length; i++) { + const pair = pairs[i]; + const index = pair.indexOf('=') + + // skip things that don't look like key=value + if (index < 0) { + continue; + } + + const key = pair.substring(0, index).trim() + + // only assign once + if (undefined == parsed[key]) { + let val = pair.substring(index + 1, pair.length).trim() + + // quoted values + if (val[0] === '"') { + val = val.slice(1, -1) + } + + // catch error: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#catching_errors + try { + const _key = decodeURIComponent(key); + const _val = decodeURIComponent(val); + parsed[_key] = decodeURIComponent(_val); + } catch (error) { + parsed[key] = val + } + } + } + return parsed; }; diff --git a/test/parse-cookies.ts b/test/parse-cookies.ts index 5ebeddf..87c8974 100644 --- a/test/parse-cookies.ts +++ b/test/parse-cookies.ts @@ -10,6 +10,7 @@ const tests1: Test[] = group("parse-cookies > ", [ assert.deepEqual(parseCookies("a=1;b=2"), { a: "1", b: "2" }); assert.deepEqual(parseCookies("a=1;b=2;c=3"), { a: "1", b: "2", c: "3" }); assert.deepEqual(parseCookies("%3D=%3D"), { "=": "=" }); + assert.deepEqual(parseCookies("a=b=c;"), { a: "b=c"}); }), ]);