diff --git a/lib/util/cache.js b/lib/util/cache.js index 35c53512b2a..a4cba958bd4 100644 --- a/lib/util/cache.js +++ b/lib/util/cache.js @@ -260,19 +260,16 @@ function parseVaryHeader (varyHeader, headers) { return headers } - const output = /** @type {Record} */ ({}) + const output = /** @type {Record} */ ({}) 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 diff --git a/test/types/cache-interceptor.test-d.ts b/test/types/cache-interceptor.test-d.ts index 6fb66955de5..7dcad3c454c 100644 --- a/test/types/cache-interceptor.test-d.ts +++ b/test/types/cache-interceptor.test-d.ts @@ -78,6 +78,45 @@ expectNotAssignable({ deleteAt: '' }) +expectAssignable({ + statusCode: 200, + statusMessage: 'OK', + headers: {}, + vary: { + 'accept-encoding': null, + authorization: 'Bearer token' + }, + cachedAt: 0, + staleAt: 0, + deleteAt: 0 +}) + +expectAssignable({ + statusCode: 200, + statusMessage: 'OK', + headers: {}, + vary: { + 'accept-encoding': null, + authorization: null + }, + cachedAt: 0, + staleAt: 0, + deleteAt: 0 +}) + +expectNotAssignable({ + statusCode: 200, + statusMessage: 'OK', + headers: {}, + vary: { + 'accept-encoding': true, + authorization: 'Bearer token' + }, + cachedAt: 0, + staleAt: 0, + deleteAt: 0 +}) + expectAssignable({}) expectAssignable({ maxSize: 0 diff --git a/test/utils/cache.js b/test/utils/cache.js new file mode 100644 index 00000000000..c9f9cbc8be9 --- /dev/null +++ b/test/utils/cache.js @@ -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' + }) + assert.deepStrictEqual(result, { + 'accept-encoding': null, + authorization: 'Bearer token' + }) + }) + + 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) + }) +}) diff --git a/types/cache-interceptor.d.ts b/types/cache-interceptor.d.ts index 1713ca7e747..e53be60a611 100644 --- a/types/cache-interceptor.d.ts +++ b/types/cache-interceptor.d.ts @@ -70,7 +70,7 @@ declare namespace CacheHandler { statusCode: number statusMessage: string headers: Record - vary?: Record + vary?: Record etag?: string cacheControlDirectives?: CacheControlDirectives cachedAt: number @@ -88,7 +88,7 @@ declare namespace CacheHandler { statusCode: number statusMessage: string headers: Record - vary?: Record + vary?: Record etag?: string body?: Readable | Iterable | AsyncIterable | Buffer | Iterable | AsyncIterable | string cacheControlDirectives: CacheControlDirectives,