diff --git a/src/utils/cookie.test.ts b/src/utils/cookie.test.ts index 84578a9c..d8ba7e51 100644 --- a/src/utils/cookie.test.ts +++ b/src/utils/cookie.test.ts @@ -30,6 +30,14 @@ describe('Parse cookie', () => { expect(cookie['tasty_cookie']).toBeUndefined() }) + it('Should parse one cookie specified by name even if it is not found', () => { + const cookieString = 'yummy_cookie=choco; tasty_cookie = strawberry ' + const cookie: Cookie = parse(cookieString, 'no_such_cookie') + expect(cookie['yummy_cookie']).toBeUndefined() + expect(cookie['tasty_cookie']).toBeUndefined() + expect(cookie['no_such_cookie']).toBeUndefined() + }) + it('Should parse cookies with no value', () => { const cookieString = 'yummy_cookie=; tasty_cookie = ; best_cookie= ; last_cookie=""' const cookie: Cookie = parse(cookieString) diff --git a/src/utils/cookie.ts b/src/utils/cookie.ts index 45797ddf..16986667 100644 --- a/src/utils/cookie.ts +++ b/src/utils/cookie.ts @@ -77,17 +77,22 @@ const validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/ const validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/ export const parse = (cookie: string, name?: string): Cookie => { + if (name && cookie.indexOf(name) === -1) { + // Fast-path: return immediately if the demanded-key is not in the cookie string + return {} + } const pairs = cookie.trim().split(';') - return pairs.reduce((parsedCookie, pairStr) => { + const parsedCookie: Cookie = {} + for (let pairStr of pairs) { pairStr = pairStr.trim() const valueStartPos = pairStr.indexOf('=') if (valueStartPos === -1) { - return parsedCookie + continue } const cookieName = pairStr.substring(0, valueStartPos).trim() if ((name && name !== cookieName) || !validCookieNameRegEx.test(cookieName)) { - return parsedCookie + continue } let cookieValue = pairStr.substring(valueStartPos + 1).trim() @@ -96,10 +101,13 @@ export const parse = (cookie: string, name?: string): Cookie => { } if (validCookieValueRegEx.test(cookieValue)) { parsedCookie[cookieName] = decodeURIComponent_(cookieValue) + if (name) { + // Fast-path: return only the demanded-key immediately. Other keys are not needed. + break + } } - - return parsedCookie - }, {} as Cookie) + } + return parsedCookie } export const parseSigned = async (