Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,26 @@ function parseTokenList (str) {
var end = 0
var list = []
var start = 0
var inQuotes = false

// gather tokens
for (var i = 0, len = str.length; i < len; i++) {
switch (str.charCodeAt(i)) {
var code = str.charCodeAt(i)

// opaque-tag is DQUOTE *etagc DQUOTE (RFC 9110). etagc includes comma, so
// a comma inside quotes is part of the entity-tag, not a list separator.
if (code === 0x22) { /* " */
inQuotes = !inQuotes
end = i + 1
continue
}

if (inQuotes) {
end = i + 1
continue
}

switch (code) {
case 0x09: /* HTAB */
case 0x20: /* */
if (start === end) {
Expand Down
20 changes: 20 additions & 0 deletions test/fresh.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ describe('fresh(reqHeaders, resHeaders)', function () {
})
})

describe('when an entity-tag contains a comma', function () {
it('should be fresh on exact match', function () {
var reqHeaders = { 'if-none-match': 'W/"foo,bar"' }
var resHeaders = { etag: 'W/"foo,bar"' }
assert.ok(fresh(reqHeaders, resHeaders))
})

it('should still split on commas outside quotes', function () {
var reqHeaders = { 'if-none-match': 'W/"foo,bar", "baz"' }
var resHeaders = { etag: '"baz"' }
assert.ok(fresh(reqHeaders, resHeaders))
})

it('should be stale when only a split fragment would have matched', function () {
var reqHeaders = { 'if-none-match': 'W/"foo,bar"' }
var resHeaders = { etag: 'W/"foo' }
assert.ok(!fresh(reqHeaders, resHeaders))
})
})

describe('when etag is missing', function () {
it('should be stale', function () {
var reqHeaders = { 'if-none-match': '"foo"' }
Expand Down