From 231f5bb0b798d86cf4ecc69235e81aa69fba69bf Mon Sep 17 00:00:00 2001 From: Talha Shafeeq Date: Sun, 11 Oct 2026 14:07:55 +0500 Subject: [PATCH] fix: preserve header tokens with whitespace preceding commas in vary parser Signed-off-by: Talha Shafeeq --- test/vary.test.js | 24 +++++++++++++++++++++++- vary.js | 35 +++++++++++++++-------------------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/test/vary.test.js b/test/vary.test.js index 4e5bce3..28fd1ab 100644 --- a/test/vary.test.js +++ b/test/vary.test.js @@ -195,8 +195,26 @@ test('Should ignore the header as value for vary if it is already in vary', t => }) }) +test('Should ignore the header as value for vary if it is already in vary with whitespace before comma', t => { + t.plan(1) + + const addOriginToVary = createAddFieldnameToVary('Origin') + const replyMock = { + getHeader () { + return 'Origin , Accept-Encoding' + }, + header () { + throw new Error('Should not be here') + } + } + + t.assert.doesNotThrow(() => { + addOriginToVary(replyMock) + }) +}) + test('parse', t => { - t.plan(18) + t.plan(22) t.assert.deepStrictEqual(parse(''), []) t.assert.deepStrictEqual(parse('a'), ['a']) t.assert.deepStrictEqual(parse('a,b'), ['a', 'b']) @@ -214,6 +232,10 @@ test('parse', t => { t.assert.deepStrictEqual(parse('a, b,c'), ['a', 'b', 'c']) t.assert.deepStrictEqual(parse('a, , b,c'), ['a', 'b', 'c']) t.assert.deepStrictEqual(parse('a, , b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a ,b'), ['a', 'b']) + t.assert.deepStrictEqual(parse('a , b'), ['a', 'b']) + t.assert.deepStrictEqual(parse('a\t,\tb'), ['a', 'b']) + t.assert.deepStrictEqual(parse('Origin , Accept-Encoding'), ['origin', 'accept-encoding']) // one for the cache t.assert.deepStrictEqual(parse('A,b,c'), ['a', 'b', 'c']) diff --git a/vary.js b/vary.js index 73b3551..d1a9cc3 100644 --- a/vary.js +++ b/vary.js @@ -36,31 +36,26 @@ function parse (header) { } else if (header.indexOf(',') === -1) { result.push(header) } else { - const il = header.length - let i = 0 - let pos = 0 - let char + const len = header.length + let start = 0 // tokenize the header - for (i; i < il; ++i) { - char = header[i] - // when we have whitespace set the pos to the next position - if (char === ' ') { - pos = i + 1 - // `,` is the separator of vary-values - } else if (char === ',') { - // if pos and current position are not the same we have a valid token - if (pos !== i) { - result.push(header.slice(pos, i)) + for (let i = 0; i <= len; ++i) { + if (i === len || header.charCodeAt(i) === 44) { + let tokenStart = start + let tokenEnd = i + while (tokenStart < tokenEnd && (header.charCodeAt(tokenStart) === 32 || header.charCodeAt(tokenStart) === 9)) { + tokenStart++ } - // reset the positions - pos = i + 1 + while (tokenEnd > tokenStart && (header.charCodeAt(tokenEnd - 1) === 32 || header.charCodeAt(tokenEnd - 1) === 9)) { + tokenEnd-- + } + if (tokenStart < tokenEnd) { + result.push(header.slice(tokenStart, tokenEnd)) + } + start = i + 1 } } - - if (pos !== i) { - result.push(header.slice(pos, i)) - } } return result