diff --git a/src/index.js b/src/index.js index 0746826..5510ff2 100644 --- a/src/index.js +++ b/src/index.js @@ -15,6 +15,9 @@ module.exports = function (req, res, logFacilities, config, next) { const cacheVaryHeadersConfigured = config.cacheVaryHeaders ? config.cacheVaryHeaders : []; + const cacheIgnoreHeadersConfigured = config.cacheIgnoreHeaders + ? config.cacheIgnoreHeaders + : []; const maximumCachedResponseSize = config.maximumCachedResponseSize ? config.maximumCachedResponseSize : null; @@ -174,6 +177,12 @@ module.exports = function (req, res, logFacilities, config, next) { .join("\n"); varyCache.set(cacheKey, processedVary); + + // Ignore headers + cacheIgnoreHeadersConfigured.forEach((header) => { + delete writtenHeaders[header.toLowerCase()]; + }); + cache.set(cacheKeyWithVary, { body: responseBody, headers: writtenHeaders, @@ -259,6 +268,9 @@ module.exports.configValidators = { cacheVaryHeaders: (value) => Array.isArray(value) && value.every((element) => typeof element === "string"), + cacheIgnoreHeaders: (value) => + Array.isArray(value) && + value.every((element) => typeof element === "string"), maximumCachedResponseSize: (value) => typeof value === "number" || value === null }; diff --git a/tests/index.test.js b/tests/index.test.js index ea14a95..7e2bbbc 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -40,6 +40,7 @@ describe("SVR.JS Cache mod", () => { config = { cacheVaryHeaders: ["accept"], + cacheIgnoreHeaders: [], maximumCachedResponseSize: 1024 }; @@ -120,15 +121,76 @@ describe("SVR.JS Cache mod", () => { expect(next).not.toHaveBeenCalled(); // No middleware should be called }); + test("should cache the response and serve it on subsequent requests, while ignoring some headers", () => { + req.headers.host = "ignore.test.com"; + req.headers.accept = "application/json"; + + // Headers to ignore + config.cacheIgnoreHeaders = ["x-header-ignored"]; + + parseCacheControl.mockReturnValue({}); + parseVary.mockReturnValue(["accept"]); + shouldCacheResponse.mockReturnValue(true); + + // Mock cache-control headers + res.getHeaders.mockReturnValue({ "cache-control": "max-age=300" }); + + // First request: cache the response + mod(req, res, logFacilities, config, next); + + // Simulate the first response + res.writeHead(200, { + "content-type": "application/json", + "x-header-ignored": "no" + }); + res.end("cached response body"); + + // Assertions for the first request + expect(next).toHaveBeenCalled(); // Proceed to next middleware during first request + + // Reset mocks for the second invocation + jest.clearAllMocks(); + next.mockReset(); + res.setHeader = jest.fn(); + res.removeHeader = jest.fn(); + res.writeHead = jest.fn(); + res.write = jest.fn(); + res.end = jest.fn(); + + // Second request: retrieve from cache + parseCacheControl.mockReturnValue({}); + isCacheValid.mockReturnValue(true); // Simulate a valid cache entry + + mod(req, res, logFacilities, config, next); + + // Assertions for the second request + expect(logFacilities.resmessage).toHaveBeenCalledWith( + "The response is cached." + ); + expect(res.setHeader).toHaveBeenCalledWith("X-SVRJS-Cache", "HIT"); + expect(res.writeHead).toHaveBeenCalledWith(200, { + "cache-control": "max-age=300", + "content-type": "application/json" + }); + expect(res.end).toHaveBeenCalledWith( + Buffer.from("cached response body", "latin1") + ); + expect(next).not.toHaveBeenCalled(); // No middleware should be called + }); + test("should validate config values correctly", () => { const validConfig = { cacheVaryHeaders: ["accept", "user-agent"], + cacheIgnoreHeaders: ["set-cookie"], maximumCachedResponseSize: 2048 }; expect( mod.configValidators.cacheVaryHeaders(validConfig.cacheVaryHeaders) ).toBe(true); + expect( + mod.configValidators.cacheIgnoreHeaders(validConfig.cacheIgnoreHeaders) + ).toBe(true); expect( mod.configValidators.maximumCachedResponseSize( validConfig.maximumCachedResponseSize @@ -137,12 +199,16 @@ describe("SVR.JS Cache mod", () => { const invalidConfig = { cacheVaryHeaders: "invalid", + cacheIgnoreHeaders: "invalid", maximumCachedResponseSize: "invalid" }; expect( mod.configValidators.cacheVaryHeaders(invalidConfig.cacheVaryHeaders) ).toBe(false); + expect( + mod.configValidators.cacheIgnoreHeaders(invalidConfig.cacheIgnoreHeaders) + ).toBe(false); expect( mod.configValidators.maximumCachedResponseSize( invalidConfig.maximumCachedResponseSize