diff --git a/lib/interceptor/cache.js b/lib/interceptor/cache.js index 295c566f255..093340240a8 100644 --- a/lib/interceptor/cache.js +++ b/lib/interceptor/cache.js @@ -233,7 +233,7 @@ function handleResult ( } let headers = { - ...normaliseHeaders(opts), + ...opts.headers, 'if-modified-since': new Date(result.cachedAt).toUTCString() } @@ -319,6 +319,11 @@ module.exports = (opts = {}) => { return dispatch(opts, handler) } + opts = { + ...opts, + headers: normaliseHeaders(opts) + } + const reqCacheControl = opts.headers?.['cache-control'] ? parseCacheControlHeader(opts.headers['cache-control']) : undefined diff --git a/lib/util/cache.js b/lib/util/cache.js index 17039709bb9..6f347936941 100644 --- a/lib/util/cache.js +++ b/lib/util/cache.js @@ -12,13 +12,11 @@ function makeCacheKey (opts) { throw new Error('opts.origin is undefined') } - const headers = normaliseHeaders(opts) - return { origin: opts.origin.toString(), method: opts.method, path: opts.path, - headers + headers: opts.headers } } diff --git a/test/issue-3904.js b/test/issue-3904.js new file mode 100644 index 00000000000..43c2881c0fd --- /dev/null +++ b/test/issue-3904.js @@ -0,0 +1,58 @@ +const { describe, test, after } = require('node:test') +const assert = require('node:assert') +const { createServer } = require('node:http') +const { once } = require('node:events') +const MemoryCacheStore = require('../lib/cache/memory-cache-store.js') +const { Agent, interceptors, request, setGlobalDispatcher } = require('..') + +describe('Cache with cache-control: no-store request header', () => { + [ + 'CACHE-CONTROL', + 'cache-control', + 'Cache-Control' + ].forEach(headerName => { + test(`should not cache response for request with header: "${headerName}: no-store`, async () => { + const store = new MemoryCacheStore() + let requestCount = 0 + const server = createServer({ joinDuplicateHeaders: true }, (req, res) => { + ++requestCount + res.setHeader('Vary', 'Accept-Encoding') + res.setHeader('Cache-Control', 'max-age=60') + res.end(`Request count: ${requestCount}`) + }) + + after(async () => { + server.close() + + await once(server, 'close') + }) + + await new Promise(resolve => server.listen(0, resolve)) + const { port } = server.address() + const url = `http://localhost:${port}` + + const agent = new Agent() + setGlobalDispatcher( + agent.compose( + interceptors.cache({ + store, + cacheByDefault: 1000, + methods: ['GET'] + }) + ) + ) + + const res1 = await request(url, { headers: { [headerName]: 'no-store' } }) + const body1 = await res1.body.text() + assert.strictEqual(body1, 'Request count: 1') + assert.strictEqual(requestCount, 1) + + const res2 = await request(url) + const body2 = await res2.body.text() + assert.strictEqual(body2, 'Request count: 2') + assert.strictEqual(requestCount, 2) + + await new Promise(resolve => server.close(resolve)) + }) + }) +})