diff --git a/README.md b/README.md index 5f32e68..cddbcaf 100644 --- a/README.md +++ b/README.md @@ -154,4 +154,7 @@ This is your repo ;) > Note: We aim to be 100% code coverage, please consider it on your pull requests. ## Related projects -- fast-gateway (https://www.npmjs.com/package/fast-gateway) \ No newline at end of file +- fast-gateway (https://www.npmjs.com/package/fast-gateway) + +## Sponsors +- Kindly sponsored by [ShareNow](https://www.share-now.com/), a company that promotes innovation! \ No newline at end of file diff --git a/index.js b/index.js index 815f80a..cf05e23 100644 --- a/index.js +++ b/index.js @@ -13,96 +13,96 @@ const CACHE_CONTROL = 'cache-control' const CACHE_IF_NONE_MATCH = 'if-none-match' const middleware = (opts) => async (req, res, next) => { - opts = Object.assign({ - stores: [CacheManager.caching({ store: 'memory', max: 1000, ttl: 30 })] - }, opts) + try { + opts = Object.assign({ + stores: [CacheManager.caching({ store: 'memory', max: 1000, ttl: 30 })] + }, opts) - // creating multi-cache instance - const mcache = CacheManager.multiCaching(opts.stores) + // creating multi-cache instance + const mcache = CacheManager.multiCaching(opts.stores) - if (req.cacheDisabled) return next() + if (req.cacheDisabled) return next() - let { url, cacheAppendKey = req => '' } = req - cacheAppendKey = await cacheAppendKey(req) + let { url, cacheAppendKey = req => '' } = req + cacheAppendKey = await cacheAppendKey(req) - const key = req.method + url + cacheAppendKey - // ref cache key on req object - req.cacheKey = key + const key = req.method + url + cacheAppendKey + // ref cache key on req object + req.cacheKey = key - // try to retrieve cached response - const cached = await get(mcache, key) + // try to retrieve cached response + const cached = await get(mcache, key) - if (cached) { - // respond from cache if there is a hit - let { status, headers, data } = JSON.parse(cached) + if (cached) { + // respond from cache if there is a hit + let { status, headers, data } = JSON.parse(cached) - // pre-checking If-None-Match header - if (req.headers[CACHE_IF_NONE_MATCH] && req.headers[CACHE_IF_NONE_MATCH] === headers[CACHE_ETAG]) { - res.setHeader('content-length', '0') - res.statusCode = 304 - res.end() + // pre-checking If-None-Match header + if (req.headers[CACHE_IF_NONE_MATCH] && req.headers[CACHE_IF_NONE_MATCH] === headers[CACHE_ETAG]) { + res.setHeader('content-length', '0') + res.statusCode = 304 + res.end() - return // exit because client cache state matches - } + return // exit because client cache state matches + } - if (typeof data === 'object' && data.type === 'Buffer') { - data = Buffer.from(data.data) - } - headers[X_CACHE_HIT] = '1' + if (typeof data === 'object' && data.type === 'Buffer') { + data = Buffer.from(data.data) + } + headers[X_CACHE_HIT] = '1' - // set cached response headers - Object.keys(headers).forEach(header => res.setHeader(header, headers[header])) + // set cached response headers + Object.keys(headers).forEach(header => res.setHeader(header, headers[header])) - // send cached payload - req.cacheHit = true - res.statusCode = status - res.end(data) + // send cached payload + req.cacheHit = true + res.statusCode = status + res.end(data) - return - } + return + } - onEnd(res, (payload) => { - if (payload.headers[X_CACHE_EXPIRE]) { - // support service level expiration - const keysPattern = payload.headers[X_CACHE_EXPIRE].replace(/\s/g, '') - const patterns = keysPattern.split(',') - // delete keys on all cache tiers - patterns.forEach(pattern => opts.stores.forEach(store => getKeys(store, pattern).then(keys => mcache.del(keys)))) - } else if (payload.headers[X_CACHE_TIMEOUT] || payload.headers[CACHE_CONTROL]) { - // extract cache ttl - let ttl = 0 - if (payload.headers[CACHE_CONTROL]) { - ttl = cacheControl(payload.headers[CACHE_CONTROL]).maxAge - } - if (!ttl) { - if (payload.headers[X_CACHE_TIMEOUT]) { - ttl = Math.max(ms(payload.headers[X_CACHE_TIMEOUT]), 1000) / 1000 // min value: 1 second - } else { - return // no TTL found, we don't cache + onEnd(res, (payload) => { + if (payload.headers[X_CACHE_EXPIRE]) { + // support service level expiration + const keysPattern = payload.headers[X_CACHE_EXPIRE].replace(/\s/g, '') + const patterns = keysPattern.split(',') + // delete keys on all cache tiers + patterns.forEach(pattern => opts.stores.forEach(store => getKeys(store, pattern).then(keys => mcache.del(keys)))) + } else if (payload.headers[X_CACHE_TIMEOUT] || payload.headers[CACHE_CONTROL]) { + // extract cache ttl + let ttl = 0 + if (payload.headers[CACHE_CONTROL]) { + ttl = cacheControl(payload.headers[CACHE_CONTROL]).maxAge + } + if (!ttl) { + if (payload.headers[X_CACHE_TIMEOUT]) { + ttl = Math.max(ms(payload.headers[X_CACHE_TIMEOUT]), 1000) / 1000 // min value: 1 second + } else { + return // no TTL found, we don't cache + } } - } - // setting cache-control header if absent - if (!payload.headers[CACHE_CONTROL]) { - payload.headers[CACHE_CONTROL] = `private, no-cache, max-age=${ttl}` - } - // setting ETag if absent - if (!payload.headers[CACHE_ETAG]) { - payload.headers[CACHE_ETAG] = Math.random().toString(36).substring(2, 16) - } + // setting cache-control header if absent + if (!payload.headers[CACHE_CONTROL]) { + payload.headers[CACHE_CONTROL] = `private, no-cache, max-age=${ttl}` + } + // setting ETag if absent + if (!payload.headers[CACHE_ETAG]) { + payload.headers[CACHE_ETAG] = Math.random().toString(36).substring(2, 16) + } - // cache response - mcache.set(req.cacheKey, JSON.stringify(payload), { ttl }) - } - }) + // cache response + mcache.set(req.cacheKey, JSON.stringify(payload), { ttl }) + } + }) - return next() + return next() + } catch (err) { + return next(err) + } } -const get = (cache, key) => new Promise((resolve) => { - cache.getAndPassUp(key, (_, res) => { - resolve(res) - }) -}) +const get = (cache, key) => cache.getAndPassUp(key) module.exports = iu(middleware) diff --git a/package-lock.json b/package-lock.json index 5acd15a..a85d932 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "http-cache-middleware", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4145c2b..793d3aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-cache-middleware", - "version": "1.2.4", + "version": "1.2.5", "description": "HTTP Cache Middleware", "main": "index.js", "scripts": {