diff --git a/lib/cache/memory-cache-store.js b/lib/cache/memory-cache-store.js index dba29ae4de9..ea9c6cae7e9 100644 --- a/lib/cache/memory-cache-store.js +++ b/lib/cache/memory-cache-store.js @@ -138,7 +138,7 @@ class MemoryCacheStore extends EventEmitter { entry.size += chunk.byteLength - if (entry.size >= store.#maxEntrySize) { + if (entry.size > store.#maxEntrySize) { this.destroy() } else { entry.body.push(chunk) diff --git a/lib/cache/sqlite-cache-store.js b/lib/cache/sqlite-cache-store.js index f760a1d59dd..bf1e04b7917 100644 --- a/lib/cache/sqlite-cache-store.js +++ b/lib/cache/sqlite-cache-store.js @@ -325,7 +325,7 @@ module.exports = class SqliteCacheStore { write (chunk, encoding, callback) { size += chunk.byteLength - if (size < store.#maxEntrySize) { + if (size <= store.#maxEntrySize) { body.push(chunk) } else { this.destroy() diff --git a/test/cache-interceptor/cache-store-test-utils.js b/test/cache-interceptor/cache-store-test-utils.js index 54616b89744..4d5d44fe329 100644 --- a/test/cache-interceptor/cache-store-test-utils.js +++ b/test/cache-interceptor/cache-store-test-utils.js @@ -108,6 +108,45 @@ function cacheStoreTests (CacheStore, options) { } }) + test('caches streamed body at maxEntrySize boundary', options, async () => { + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} + */ + const key = { + origin: 'localhost', + path: '/', + method: 'GET', + headers: {} + } + + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue} + */ + const value = { + statusCode: 200, + statusMessage: '', + headers: { foo: 'bar' }, + cacheControlDirectives: {}, + cachedAt: Date.now(), + staleAt: Date.now() + 10000, + deleteAt: Date.now() + 20000 + } + + const body = [Buffer.from('asd'), Buffer.from('123')] + const store = new CacheStore({ maxEntrySize: 6 }) + const writable = store.createWriteStream(key, value) + + notEqual(writable, undefined) + + const finished = once(writable, 'finish') + writeBody(writable, body) + await finished + + const result = await store.get(structuredClone(key)) + notEqual(result, undefined) + await compareGetResults(result, value, body) + }) + test('returns stale response before deleteAt', options, async () => { const clock = FakeTimers.install({ shouldClearNativeTimers: true