Skip to content

Commit

Permalink
fix: handle missing vary header values
Browse files Browse the repository at this point in the history
Co-authored-by: SukkaW <[email protected]>
  • Loading branch information
gurgunday and SukkaW committed Jan 27, 2025
1 parent 008187b commit 5f44645
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 8 deletions.
9 changes: 3 additions & 6 deletions lib/util/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,19 +260,16 @@ function parseVaryHeader (varyHeader, headers) {
return headers
}

const output = /** @type {Record<string, string | string[]>} */ ({})
const output = /** @type {Record<string, string | string[] | null>} */ ({})

const varyingHeaders = typeof varyHeader === 'string'
? varyHeader.split(',')
: varyHeader

for (const header of varyingHeaders) {
const trimmedHeader = header.trim().toLowerCase()

if (headers[trimmedHeader]) {
output[trimmedHeader] = headers[trimmedHeader]
} else {
return undefined
}
output[trimmedHeader] = headers[trimmedHeader] ?? null
}

return output
Expand Down
39 changes: 39 additions & 0 deletions test/types/cache-interceptor.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,45 @@ expectNotAssignable<CacheInterceptor.CacheValue>({
deleteAt: ''
})

expectAssignable<CacheInterceptor.CacheValue>({
statusCode: 200,
statusMessage: 'OK',
headers: {},
vary: {
'accept-encoding': null,
authorization: 'Bearer token'

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical test

The hard-coded value "Bearer token" is used as
authorization header
.
},
cachedAt: 0,
staleAt: 0,
deleteAt: 0
})

expectAssignable<CacheInterceptor.CacheValue>({
statusCode: 200,
statusMessage: 'OK',
headers: {},
vary: {
'accept-encoding': null,
authorization: null
},
cachedAt: 0,
staleAt: 0,
deleteAt: 0
})

expectNotAssignable<CacheInterceptor.CacheValue>({
statusCode: 200,
statusMessage: 'OK',
headers: {},
vary: {
'accept-encoding': true,
authorization: 'Bearer token'

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical test

The hard-coded value "Bearer token" is used as
authorization header
.
},
cachedAt: 0,
staleAt: 0,
deleteAt: 0
})

expectAssignable<CacheInterceptor.MemoryCacheStoreOpts>({})
expectAssignable<CacheInterceptor.MemoryCacheStoreOpts>({
maxSize: 0
Expand Down
39 changes: 39 additions & 0 deletions test/utils/cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const { describe, test } = require('node:test')
const assert = require('node:assert')
const { parseVaryHeader } = require('../../lib/util/cache.js')

describe('parseVaryHeader', () => {
test('handles missing headers with null', () => {
const result = parseVaryHeader('Accept-Encoding, Authorization', {})
assert.deepStrictEqual(result, {
'accept-encoding': null,
authorization: null
})
})

test('handles mix of present and missing headers', () => {
const result = parseVaryHeader('Accept-Encoding, Authorization', {
authorization: 'Bearer token'

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical test

The hard-coded value "Bearer token" is used as
authorization header
.
})
assert.deepStrictEqual(result, {
'accept-encoding': null,
authorization: 'Bearer token'

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical test

The hard-coded value "Bearer token" is used as
authorization header
.
})
})

test('handles array input', () => {
const result = parseVaryHeader(['Accept-Encoding', 'Authorization'], {
'accept-encoding': 'gzip'
})
assert.deepStrictEqual(result, {
'accept-encoding': 'gzip',
authorization: null
})
})

test('preserves existing * behavior', () => {
const headers = { accept: 'text/html' }
const result = parseVaryHeader('*', headers)
assert.deepStrictEqual(result, headers)
})
})
4 changes: 2 additions & 2 deletions types/cache-interceptor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ declare namespace CacheHandler {
statusCode: number
statusMessage: string
headers: Record<string, string | string[]>
vary?: Record<string, string | string[]>
vary?: Record<string, string | string[] | null>
etag?: string
cacheControlDirectives?: CacheControlDirectives
cachedAt: number
Expand All @@ -88,7 +88,7 @@ declare namespace CacheHandler {
statusCode: number
statusMessage: string
headers: Record<string, string | string[]>
vary?: Record<string, string | string[]>
vary?: Record<string, string | string[] | null>
etag?: string
body?: Readable | Iterable<Buffer> | AsyncIterable<Buffer> | Buffer | Iterable<string> | AsyncIterable<string> | string
cacheControlDirectives: CacheControlDirectives,
Expand Down

0 comments on commit 5f44645

Please sign in to comment.