diff --git a/dist/main/apicache.js b/dist/main/apicache.js deleted file mode 100644 index 94b9050..0000000 --- a/dist/main/apicache.js +++ /dev/null @@ -1,882 +0,0 @@ -'use strict' - -function MemoryCache() { - this.cache = {} - this.size = 0 -} - -MemoryCache.prototype.add = function (key, value, time, timeoutCallback) { - var old = this.cache[key] - var instance = this - - var entry = { - value: value, - expire: time + Date.now(), - timeout: setTimeout(function () { - instance.delete(key) - return timeoutCallback && typeof timeoutCallback === 'function' && timeoutCallback(value, key) - }, time), - } - - this.cache[key] = entry - this.size = Object.keys(this.cache).length - - return entry -} - -MemoryCache.prototype.delete = function (key) { - var entry = this.cache[key] - - if (entry) { - clearTimeout(entry.timeout) - } - - delete this.cache[key] - - this.size = Object.keys(this.cache).length - - return null -} - -MemoryCache.prototype.get = function (key) { - var entry = this.cache[key] - - return entry -} - -MemoryCache.prototype.getValue = function (key) { - var entry = this.get(key) - - return entry && entry.value -} - -MemoryCache.prototype.clear = function () { - Object.keys(this.cache).forEach(function (key) { - this.delete(key) - }, this) - - return true -} - -var name = 'apicache' -var version = '1.5.3' -var scripts = { - lint: 'eslint src', - test2: "nyc mocha $(find test -name '*_test.js') --recursive", - test: 'nyc jest --verbose', - dev: 'yarn test --watch', - coverage: 'nyc report --reporter=text-lcov | coveralls', - build: 'rollup -c', - build2: 'rollup src/index.js --format cjs --file dist/apicache.js', -} -var engines = { - node: '>=8', -} -var description = - 'An ultra-simplified API response caching middleware for Express/Node using plain-english durations.' -var main = 'dist/main/apicache.js' -var module$1 = 'dist/module/apicache.js' -var repository = { - type: 'git', - url: 'https://github.com/kwhitley/apicache.git', -} -var keywords = [ - 'cache', - 'API', - 'redis', - 'memcache', - 'response', - 'express', - 'JSON', - 'duration', - 'middleware', - 'memory', -] -var author = 'Kevin R. Whitley (http://krwhitley.com)' -var license = 'MIT' -var bugs = { - url: 'https://github.com/kwhitley/apicache/issues', - email: 'krwhitley@gmail.com', -} -var devDependencies = { - '@rollup/plugin-json': '^4.0.3', - chai: '^4.2.0', - compression: '^1.7.4', - coveralls: '^3.1.0', - eslint: '^7.0.0', - express: '^4.17.1', - fakeredis: '^2.0.0', - husky: '^4.2.5', - jest: '^26.0.1', - mocha: '^7.0.0', - nyc: '^15.0.1', - prettier: '^2.0.5', - 'pretty-quick': '^2.0.1', - restify: '^7.7.0', - 'restify-etag-cache': '^1.0.12', - rollup: '^2.10.2', - 'rollup-plugin-sourcemaps': '^0.6.2', - 'rollup-plugin-terser': '^5.3.0', - supertest: '^4.0.2', - 'yarn-release': '^1.10.2', -} -var dependencies = {} -var husky = { - hooks: { - 'pre-commit': 'pretty-quick --staged', - }, -} -var pkg = { - name: name, - version: version, - scripts: scripts, - engines: engines, - description: description, - main: main, - module: module$1, - repository: repository, - keywords: keywords, - author: author, - license: license, - bugs: bugs, - devDependencies: devDependencies, - dependencies: dependencies, - husky: husky, -} - -var t = { - ms: 1, - second: 1000, - minute: 60000, - hour: 3600000, - day: 3600000 * 24, - week: 3600000 * 24 * 7, - month: 3600000 * 24 * 30, -} - -var instances = [] - -var matches = function (a) { - return function (b) { - return a === b - } -} - -var doesntMatch = function (a) { - return function (b) { - return !matches(a)(b) - } -} - -var logDuration = function (d, prefix) { - var str = d > 1000 ? (d / 1000).toFixed(2) + 'sec' : d + 'ms' - return '\x1b[33m- ' + (prefix ? prefix + ' ' : '') + str + '\x1b[0m' -} - -function getSafeHeaders(res) { - return res.getHeaders ? res.getHeaders() : res._headers -} - -function ApiCache() { - var memCache = new MemoryCache() - - var globalOptions = { - debug: false, - defaultDuration: 3600000, - enabled: true, - appendKey: [], - jsonp: false, - redisClient: false, - headerBlacklist: [], - statusCodes: { - include: [], - exclude: [], - }, - events: { - expire: undefined, - }, - headers: { - // 'cache-control': 'no-cache' // example of header overwrite - }, - trackPerformance: false, - } - - var middlewareOptions = [] - var instance = this - var index = null - var timers = {} - var performanceArray = [] // for tracking cache hit rate - - instances.push(this) - this.id = instances.length - - function debug(a, b, c, d) { - var arr = ['\x1b[36m[apicache]\x1b[0m', a, b, c, d].filter(function (arg) { - return arg !== undefined - }) - var debugEnv = process.env.DEBUG && process.env.DEBUG.split(',').indexOf('apicache') !== -1 - - return (globalOptions.debug || debugEnv) && console.log.apply(null, arr) - } - - function shouldCacheResponse(request, response, toggle) { - var opt = globalOptions - var codes = opt.statusCodes - - if (!response) return false - - if (toggle && !toggle(request, response)) { - return false - } - - if (codes.exclude && codes.exclude.length && codes.exclude.indexOf(response.statusCode) !== -1) - return false - if (codes.include && codes.include.length && codes.include.indexOf(response.statusCode) === -1) - return false - - return true - } - - function addIndexEntries(key, req) { - var groupName = req.apicacheGroup - - if (groupName) { - debug('group detected "' + groupName + '"') - var group = (index.groups[groupName] = index.groups[groupName] || []) - group.unshift(key) - } - - index.all.unshift(key) - } - - function filterBlacklistedHeaders(headers) { - return Object.keys(headers) - .filter(function (key) { - return globalOptions.headerBlacklist.indexOf(key) === -1 - }) - .reduce(function (acc, header) { - acc[header] = headers[header] - return acc - }, {}) - } - - function createCacheObject(status, headers, data, encoding) { - return { - status: status, - headers: filterBlacklistedHeaders(headers), - data: data, - encoding: encoding, - timestamp: new Date().getTime() / 1000, // seconds since epoch. This is used to properly decrement max-age headers in cached responses. - } - } - - function cacheResponse(key, value, duration) { - var redis = globalOptions.redisClient - var expireCallback = globalOptions.events.expire - - if (redis && redis.connected) { - try { - redis.hset(key, 'response', JSON.stringify(value)) - redis.hset(key, 'duration', duration) - redis.expire(key, duration / 1000, expireCallback || function () {}) - } catch (err) { - debug('[apicache] error in redis.hset()') - } - } else { - memCache.add(key, value, duration, expireCallback) - } - - // add automatic cache clearing from duration, includes max limit on setTimeout - timers[key] = setTimeout(function () { - instance.clear(key, true) - }, Math.min(duration, 2147483647)) - } - - function accumulateContent(res, content) { - if (content) { - if (typeof content == 'string') { - res._apicache.content = (res._apicache.content || '') + content - } else if (Buffer.isBuffer(content)) { - var oldContent = res._apicache.content - - if (typeof oldContent === 'string') { - oldContent = !Buffer.from ? new Buffer(oldContent) : Buffer.from(oldContent) - } - - if (!oldContent) { - oldContent = !Buffer.alloc ? new Buffer(0) : Buffer.alloc(0) - } - - res._apicache.content = Buffer.concat( - [oldContent, content], - oldContent.length + content.length - ) - } else { - res._apicache.content = content - } - } - } - - function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) { - // monkeypatch res.end to create cache object - res._apicache = { - write: res.write, - writeHead: res.writeHead, - end: res.end, - cacheable: true, - content: undefined, - } - - // append header overwrites if applicable - Object.keys(globalOptions.headers).forEach(function (name) { - res.setHeader(name, globalOptions.headers[name]) - }) - - res.writeHead = function () { - // add cache control headers - if (!globalOptions.headers['cache-control']) { - if (shouldCacheResponse(req, res, toggle)) { - res.setHeader('cache-control', 'max-age=' + (duration / 1000).toFixed(0)) - } else { - res.setHeader('cache-control', 'no-cache, no-store, must-revalidate') - } - } - - res._apicache.headers = Object.assign({}, getSafeHeaders(res)) - return res._apicache.writeHead.apply(this, arguments) - } - - // patch res.write - res.write = function (content) { - accumulateContent(res, content) - return res._apicache.write.apply(this, arguments) - } - - // patch res.end - res.end = function (content, encoding) { - if (shouldCacheResponse(req, res, toggle)) { - accumulateContent(res, content) - - if (res._apicache.cacheable && res._apicache.content) { - addIndexEntries(key, req) - var headers = res._apicache.headers || getSafeHeaders(res) - var cacheObject = createCacheObject( - res.statusCode, - headers, - res._apicache.content, - encoding - ) - cacheResponse(key, cacheObject, duration) - - // display log entry - var elapsed = new Date() - req.apicacheTimer - debug('adding cache entry for "' + key + '" @ ' + strDuration, logDuration(elapsed)) - debug('_apicache.headers: ', res._apicache.headers) - debug('res.getHeaders(): ', getSafeHeaders(res)) - debug('cacheObject: ', cacheObject) - } - } - - return res._apicache.end.apply(this, arguments) - } - - next() - } - - function sendCachedResponse(request, response, cacheObject, toggle, next, duration) { - if (toggle && !toggle(request, response)) { - return next() - } - - var headers = getSafeHeaders(response) - - Object.assign(headers, filterBlacklistedHeaders(cacheObject.headers || {}), { - // set properly-decremented max-age header. This ensures that max-age is in sync with the cache expiration. - 'cache-control': - 'max-age=' + - Math.max( - 0, - (duration / 1000 - (new Date().getTime() / 1000 - cacheObject.timestamp)).toFixed(0) - ), - }) - - // only embed apicache headers when not in production environment - if (process.env.NODE_ENV !== 'production') { - Object.assign(headers, { - 'apicache-store': globalOptions.redisClient ? 'redis' : 'memory', - 'apicache-version': pkg.version, - }) - } - - // unstringify buffers - var data = cacheObject.data - if (data && data.type === 'Buffer') { - data = - typeof data.data === 'number' ? new Buffer.alloc(data.data) : new Buffer.from(data.data) - } - - // test Etag against If-None-Match for 304 - var cachedEtag = cacheObject.headers.etag - var requestEtag = request.headers['if-none-match'] - - if (requestEtag && cachedEtag === requestEtag) { - response.writeHead(304, headers) - return response.end() - } - - response.writeHead(cacheObject.status || 200, headers) - - return response.end(data, cacheObject.encoding) - } - - function syncOptions() { - for (var i in middlewareOptions) { - Object.assign(middlewareOptions[i].options, globalOptions, middlewareOptions[i].localOptions) - } - } - - this.clear = function (target, isAutomatic) { - var group = index.groups[target] - var redis = globalOptions.redisClient - - if (group) { - debug('clearing group "' + target + '"') - - group.forEach(function (key) { - debug('clearing cached entry for "' + key + '"') - clearTimeout(timers[key]) - delete timers[key] - if (!globalOptions.redisClient) { - memCache.delete(key) - } else { - try { - redis.del(key) - } catch (err) { - console.log('[apicache] error in redis.del("' + key + '")') - } - } - index.all = index.all.filter(doesntMatch(key)) - }) - - delete index.groups[target] - } else if (target) { - debug('clearing ' + (isAutomatic ? 'expired' : 'cached') + ' entry for "' + target + '"') - clearTimeout(timers[target]) - delete timers[target] - // clear actual cached entry - if (!redis) { - memCache.delete(target) - } else { - try { - redis.del(target) - } catch (err) { - console.log('[apicache] error in redis.del("' + target + '")') - } - } - - // remove from global index - index.all = index.all.filter(doesntMatch(target)) - - // remove target from each group that it may exist in - Object.keys(index.groups).forEach(function (groupName) { - index.groups[groupName] = index.groups[groupName].filter(doesntMatch(target)) - - // delete group if now empty - if (!index.groups[groupName].length) { - delete index.groups[groupName] - } - }) - } else { - debug('clearing entire index') - - if (!redis) { - memCache.clear() - } else { - // clear redis keys one by one from internal index to prevent clearing non-apicache entries - index.all.forEach(function (key) { - clearTimeout(timers[key]) - delete timers[key] - try { - redis.del(key) - } catch (err) { - console.log('[apicache] error in redis.del("' + key + '")') - } - }) - } - this.resetIndex() - } - - return this.getIndex() - } - - function parseDuration(duration, defaultDuration) { - if (typeof duration === 'number') return duration - - if (typeof duration === 'string') { - var split = duration.match(/^([\d\.,]+)\s?(\w+)$/) - - if (split.length === 3) { - var len = parseFloat(split[1]) - var unit = split[2].replace(/s$/i, '').toLowerCase() - if (unit === 'm') { - unit = 'ms' - } - - return (len || 1) * (t[unit] || 0) - } - } - - return defaultDuration - } - - this.getDuration = function (duration) { - return parseDuration(duration, globalOptions.defaultDuration) - } - - /** - * Return cache performance statistics (hit rate). Suitable for putting into a route: - * - * app.get('/api/cache/performance', (req, res) => { - * res.json(apicache.getPerformance()) - * }) - * - */ - this.getPerformance = function () { - return performanceArray.map(function (p) { - return p.report() - }) - } - - this.getIndex = function (group) { - if (group) { - return index.groups[group] - } else { - return index - } - } - - this.middleware = function cache(strDuration, middlewareToggle, localOptions) { - var duration = instance.getDuration(strDuration) - var opt = {} - - middlewareOptions.push({ - options: opt, - }) - - var options = function (localOptions) { - if (localOptions) { - middlewareOptions.find(function (middleware) { - return middleware.options === opt - }).localOptions = localOptions - } - - syncOptions() - - return opt - } - - options(localOptions) - - /** - * A Function for non tracking performance - */ - function NOOPCachePerformance() { - this.report = this.hit = this.miss = function () {} // noop; - } - - /** - * A function for tracking and reporting hit rate. These statistics are returned by the getPerformance() call above. - */ - function CachePerformance() { - /** - * Tracks the hit rate for the last 100 requests. - * If there have been fewer than 100 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast100 = new Uint8Array(100 / 4) // each hit is 2 bits - - /** - * Tracks the hit rate for the last 1000 requests. - * If there have been fewer than 1000 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast1000 = new Uint8Array(1000 / 4) // each hit is 2 bits - - /** - * Tracks the hit rate for the last 10000 requests. - * If there have been fewer than 10000 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast10000 = new Uint8Array(10000 / 4) // each hit is 2 bits - - /** - * Tracks the hit rate for the last 100000 requests. - * If there have been fewer than 100000 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast100000 = new Uint8Array(100000 / 4) // each hit is 2 bits - - /** - * The number of calls that have passed through the middleware since the server started. - */ - this.callCount = 0 - - /** - * The total number of hits since the server started - */ - this.hitCount = 0 - - /** - * The key from the last cache hit. This is useful in identifying which route these statistics apply to. - */ - this.lastCacheHit = null - - /** - * The key from the last cache miss. This is useful in identifying which route these statistics apply to. - */ - this.lastCacheMiss = null - - /** - * Return performance statistics - */ - this.report = function () { - return { - lastCacheHit: this.lastCacheHit, - lastCacheMiss: this.lastCacheMiss, - callCount: this.callCount, - hitCount: this.hitCount, - missCount: this.callCount - this.hitCount, - hitRate: this.callCount == 0 ? null : this.hitCount / this.callCount, - hitRateLast100: this.hitRate(this.hitsLast100), - hitRateLast1000: this.hitRate(this.hitsLast1000), - hitRateLast10000: this.hitRate(this.hitsLast10000), - hitRateLast100000: this.hitRate(this.hitsLast100000), - } - } - - /** - * Computes a cache hit rate from an array of hits and misses. - * @param {Uint8Array} array An array representing hits and misses. - * @returns a number between 0 and 1, or null if the array has no hits or misses - */ - this.hitRate = function (array) { - var hits = 0 - var misses = 0 - for (var i = 0; i < array.length; i++) { - var n8 = array[i] - for (var j = 0; j < 4; j++) { - switch (n8 & 3) { - case 1: - hits++ - break - case 2: - misses++ - break - } - n8 >>= 2 - } - } - var total = hits + misses - if (total == 0) return null - return hits / total - } - - /** - * Record a hit or miss in the given array. It will be recorded at a position determined - * by the current value of the callCount variable. - * @param {Uint8Array} array An array representing hits and misses. - * @param {boolean} hit true for a hit, false for a miss - * Each element in the array is 8 bits, and encodes 4 hit/miss records. - * Each hit or miss is encoded as to bits as follows: - * 00 means no hit or miss has been recorded in these bits - * 01 encodes a hit - * 10 encodes a miss - */ - this.recordHitInArray = function (array, hit) { - var arrayIndex = ~~(this.callCount / 4) % array.length - var bitOffset = (this.callCount % 4) * 2 // 2 bits per record, 4 records per uint8 array element - var clearMask = ~(3 << bitOffset) - var record = (hit ? 1 : 2) << bitOffset - array[arrayIndex] = (array[arrayIndex] & clearMask) | record - } - - /** - * Records the hit or miss in the tracking arrays and increments the call count. - * @param {boolean} hit true records a hit, false records a miss - */ - this.recordHit = function (hit) { - this.recordHitInArray(this.hitsLast100, hit) - this.recordHitInArray(this.hitsLast1000, hit) - this.recordHitInArray(this.hitsLast10000, hit) - this.recordHitInArray(this.hitsLast100000, hit) - if (hit) this.hitCount++ - this.callCount++ - } - - /** - * Records a hit event, setting lastCacheMiss to the given key - * @param {string} key The key that had the cache hit - */ - this.hit = function (key) { - this.recordHit(true) - this.lastCacheHit = key - } - - /** - * Records a miss event, setting lastCacheMiss to the given key - * @param {string} key The key that had the cache miss - */ - this.miss = function (key) { - this.recordHit(false) - this.lastCacheMiss = key - } - } - - var perf = globalOptions.trackPerformance ? new CachePerformance() : new NOOPCachePerformance() - - performanceArray.push(perf) - - var cache = function (req, res, next) { - function bypass() { - debug('bypass detected, skipping cache.') - return next() - } - - // initial bypass chances - if (!opt.enabled) return bypass() - if (req.headers['x-apicache-bypass'] || req.headers['x-apicache-force-fetch']) return bypass() - - // REMOVED IN 0.11.1 TO CORRECT MIDDLEWARE TOGGLE EXECUTE ORDER - // if (typeof middlewareToggle === 'function') { - // if (!middlewareToggle(req, res)) return bypass() - // } else if (middlewareToggle !== undefined && !middlewareToggle) { - // return bypass() - // } - - // embed timer - req.apicacheTimer = new Date() - - // In Express 4.x the url is ambigious based on where a router is mounted. originalUrl will give the full Url - var key = req.originalUrl || req.url - - // Remove querystring from key if jsonp option is enabled - if (opt.jsonp) { - key = url.parse(key).pathname - } - - // add appendKey (either custom function or response path) - if (typeof opt.appendKey === 'function') { - key += '$$appendKey=' + opt.appendKey(req, res) - } else if (opt.appendKey.length > 0) { - var appendKey = req - - for (var i = 0; i < opt.appendKey.length; i++) { - appendKey = appendKey[opt.appendKey[i]] - } - key += '$$appendKey=' + appendKey - } - - // attempt cache hit - var redis = opt.redisClient - var cached = !redis ? memCache.getValue(key) : null - - // send if cache hit from memory-cache - if (cached) { - var elapsed = new Date() - req.apicacheTimer - debug('sending cached (memory-cache) version of', key, logDuration(elapsed)) - - perf.hit(key) - return sendCachedResponse(req, res, cached, middlewareToggle, next, duration) - } - - // send if cache hit from redis - if (redis && redis.connected) { - try { - redis.hgetall(key, function (err, obj) { - if (!err && obj && obj.response) { - var elapsed = new Date() - req.apicacheTimer - debug('sending cached (redis) version of', key, logDuration(elapsed)) - - perf.hit(key) - return sendCachedResponse( - req, - res, - JSON.parse(obj.response), - middlewareToggle, - next, - duration - ) - } else { - perf.miss(key) - return makeResponseCacheable( - req, - res, - next, - key, - duration, - strDuration, - middlewareToggle - ) - } - }) - } catch (err) { - // bypass redis on error - perf.miss(key) - return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle) - } - } else { - perf.miss(key) - return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle) - } - } - - cache.options = options - - return cache - } - - this.options = function (options) { - if (options) { - Object.assign(globalOptions, options) - syncOptions() - - if ('defaultDuration' in options) { - // Convert the default duration to a number in milliseconds (if needed) - globalOptions.defaultDuration = parseDuration(globalOptions.defaultDuration, 3600000) - } - - if (globalOptions.trackPerformance) { - debug('WARNING: using trackPerformance flag can cause high memory usage!') - } - - return this - } else { - return globalOptions - } - } - - this.resetIndex = function () { - index = { - all: [], - groups: {}, - } - } - - this.newInstance = function (config) { - var instance = new ApiCache() - - if (config) { - instance.options(config) - } - - return instance - } - - this.clone = function () { - return this.newInstance(this.options()) - } - - // initialize index - this.resetIndex() -} - -var index = new ApiCache() - -module.exports = index -//# sourceMappingURL=apicache.js.map diff --git a/dist/main/apicache.js.map b/dist/main/apicache.js.map deleted file mode 100644 index 1007da1..0000000 --- a/dist/main/apicache.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"apicache.js","sources":["../../src/memory-cache.js","../../src/index.js"],"sourcesContent":["function MemoryCache() {\n this.cache = {}\n this.size = 0\n}\n\nMemoryCache.prototype.add = function(key, value, time, timeoutCallback) {\n var old = this.cache[key]\n var instance = this\n\n var entry = {\n value: value,\n expire: time + Date.now(),\n timeout: setTimeout(function() {\n instance.delete(key)\n return timeoutCallback && typeof timeoutCallback === 'function' && timeoutCallback(value, key)\n }, time),\n }\n\n this.cache[key] = entry\n this.size = Object.keys(this.cache).length\n\n return entry\n}\n\nMemoryCache.prototype.delete = function(key) {\n var entry = this.cache[key]\n\n if (entry) {\n clearTimeout(entry.timeout)\n }\n\n delete this.cache[key]\n\n this.size = Object.keys(this.cache).length\n\n return null\n}\n\nMemoryCache.prototype.get = function(key) {\n var entry = this.cache[key]\n\n return entry\n}\n\nMemoryCache.prototype.getValue = function(key) {\n var entry = this.get(key)\n\n return entry && entry.value\n}\n\nMemoryCache.prototype.clear = function() {\n Object.keys(this.cache).forEach(function(key) {\n this.delete(key)\n }, this)\n\n return true\n}\n\nexport default MemoryCache\n","import MemoryCache from './memory-cache'\nimport pkg from '../package.json'\n\nvar t = {\n ms: 1,\n second: 1000,\n minute: 60000,\n hour: 3600000,\n day: 3600000 * 24,\n week: 3600000 * 24 * 7,\n month: 3600000 * 24 * 30,\n}\n\nvar instances = []\n\nvar matches = function (a) {\n return function (b) {\n return a === b\n }\n}\n\nvar doesntMatch = function (a) {\n return function (b) {\n return !matches(a)(b)\n }\n}\n\nvar logDuration = function (d, prefix) {\n var str = d > 1000 ? (d / 1000).toFixed(2) + 'sec' : d + 'ms'\n return '\\x1b[33m- ' + (prefix ? prefix + ' ' : '') + str + '\\x1b[0m'\n}\n\nfunction getSafeHeaders(res) {\n return res.getHeaders ? res.getHeaders() : res._headers\n}\n\nfunction ApiCache() {\n var memCache = new MemoryCache()\n\n var globalOptions = {\n debug: false,\n defaultDuration: 3600000,\n enabled: true,\n appendKey: [],\n jsonp: false,\n redisClient: false,\n headerBlacklist: [],\n statusCodes: {\n include: [],\n exclude: [],\n },\n events: {\n expire: undefined,\n },\n headers: {\n // 'cache-control': 'no-cache' // example of header overwrite\n },\n trackPerformance: false,\n }\n\n var middlewareOptions = []\n var instance = this\n var index = null\n var timers = {}\n var performanceArray = [] // for tracking cache hit rate\n\n instances.push(this)\n this.id = instances.length\n\n function debug(a, b, c, d) {\n var arr = ['\\x1b[36m[apicache]\\x1b[0m', a, b, c, d].filter(function (arg) {\n return arg !== undefined\n })\n var debugEnv = process.env.DEBUG && process.env.DEBUG.split(',').indexOf('apicache') !== -1\n\n return (globalOptions.debug || debugEnv) && console.log.apply(null, arr)\n }\n\n function shouldCacheResponse(request, response, toggle) {\n var opt = globalOptions\n var codes = opt.statusCodes\n\n if (!response) return false\n\n if (toggle && !toggle(request, response)) {\n return false\n }\n\n if (codes.exclude && codes.exclude.length && codes.exclude.indexOf(response.statusCode) !== -1)\n return false\n if (codes.include && codes.include.length && codes.include.indexOf(response.statusCode) === -1)\n return false\n\n return true\n }\n\n function addIndexEntries(key, req) {\n var groupName = req.apicacheGroup\n\n if (groupName) {\n debug('group detected \"' + groupName + '\"')\n var group = (index.groups[groupName] = index.groups[groupName] || [])\n group.unshift(key)\n }\n\n index.all.unshift(key)\n }\n\n function filterBlacklistedHeaders(headers) {\n return Object.keys(headers)\n .filter(function (key) {\n return globalOptions.headerBlacklist.indexOf(key) === -1\n })\n .reduce(function (acc, header) {\n acc[header] = headers[header]\n return acc\n }, {})\n }\n\n function createCacheObject(status, headers, data, encoding) {\n return {\n status: status,\n headers: filterBlacklistedHeaders(headers),\n data: data,\n encoding: encoding,\n timestamp: new Date().getTime() / 1000, // seconds since epoch. This is used to properly decrement max-age headers in cached responses.\n }\n }\n\n function cacheResponse(key, value, duration) {\n var redis = globalOptions.redisClient\n var expireCallback = globalOptions.events.expire\n\n if (redis && redis.connected) {\n try {\n redis.hset(key, 'response', JSON.stringify(value))\n redis.hset(key, 'duration', duration)\n redis.expire(key, duration / 1000, expireCallback || function () {})\n } catch (err) {\n debug('[apicache] error in redis.hset()')\n }\n } else {\n memCache.add(key, value, duration, expireCallback)\n }\n\n // add automatic cache clearing from duration, includes max limit on setTimeout\n timers[key] = setTimeout(function () {\n instance.clear(key, true)\n }, Math.min(duration, 2147483647))\n }\n\n function accumulateContent(res, content) {\n if (content) {\n if (typeof content == 'string') {\n res._apicache.content = (res._apicache.content || '') + content\n } else if (Buffer.isBuffer(content)) {\n var oldContent = res._apicache.content\n\n if (typeof oldContent === 'string') {\n oldContent = !Buffer.from ? new Buffer(oldContent) : Buffer.from(oldContent)\n }\n\n if (!oldContent) {\n oldContent = !Buffer.alloc ? new Buffer(0) : Buffer.alloc(0)\n }\n\n res._apicache.content = Buffer.concat(\n [oldContent, content],\n oldContent.length + content.length\n )\n } else {\n res._apicache.content = content\n }\n }\n }\n\n function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) {\n // monkeypatch res.end to create cache object\n res._apicache = {\n write: res.write,\n writeHead: res.writeHead,\n end: res.end,\n cacheable: true,\n content: undefined,\n }\n\n // append header overwrites if applicable\n Object.keys(globalOptions.headers).forEach(function (name) {\n res.setHeader(name, globalOptions.headers[name])\n })\n\n res.writeHead = function () {\n // add cache control headers\n if (!globalOptions.headers['cache-control']) {\n if (shouldCacheResponse(req, res, toggle)) {\n res.setHeader('cache-control', 'max-age=' + (duration / 1000).toFixed(0))\n } else {\n res.setHeader('cache-control', 'no-cache, no-store, must-revalidate')\n }\n }\n\n res._apicache.headers = Object.assign({}, getSafeHeaders(res))\n return res._apicache.writeHead.apply(this, arguments)\n }\n\n // patch res.write\n res.write = function (content) {\n accumulateContent(res, content)\n return res._apicache.write.apply(this, arguments)\n }\n\n // patch res.end\n res.end = function (content, encoding) {\n if (shouldCacheResponse(req, res, toggle)) {\n accumulateContent(res, content)\n\n if (res._apicache.cacheable && res._apicache.content) {\n addIndexEntries(key, req)\n var headers = res._apicache.headers || getSafeHeaders(res)\n var cacheObject = createCacheObject(\n res.statusCode,\n headers,\n res._apicache.content,\n encoding\n )\n cacheResponse(key, cacheObject, duration)\n\n // display log entry\n var elapsed = new Date() - req.apicacheTimer\n debug('adding cache entry for \"' + key + '\" @ ' + strDuration, logDuration(elapsed))\n debug('_apicache.headers: ', res._apicache.headers)\n debug('res.getHeaders(): ', getSafeHeaders(res))\n debug('cacheObject: ', cacheObject)\n }\n }\n\n return res._apicache.end.apply(this, arguments)\n }\n\n next()\n }\n\n function sendCachedResponse(request, response, cacheObject, toggle, next, duration) {\n if (toggle && !toggle(request, response)) {\n return next()\n }\n\n var headers = getSafeHeaders(response)\n\n Object.assign(headers, filterBlacklistedHeaders(cacheObject.headers || {}), {\n // set properly-decremented max-age header. This ensures that max-age is in sync with the cache expiration.\n 'cache-control':\n 'max-age=' +\n Math.max(\n 0,\n (duration / 1000 - (new Date().getTime() / 1000 - cacheObject.timestamp)).toFixed(0)\n ),\n })\n\n // only embed apicache headers when not in production environment\n if (process.env.NODE_ENV !== 'production') {\n Object.assign(headers, {\n 'apicache-store': globalOptions.redisClient ? 'redis' : 'memory',\n 'apicache-version': pkg.version,\n })\n }\n\n // unstringify buffers\n var data = cacheObject.data\n if (data && data.type === 'Buffer') {\n data =\n typeof data.data === 'number' ? new Buffer.alloc(data.data) : new Buffer.from(data.data)\n }\n\n // test Etag against If-None-Match for 304\n var cachedEtag = cacheObject.headers.etag\n var requestEtag = request.headers['if-none-match']\n\n if (requestEtag && cachedEtag === requestEtag) {\n response.writeHead(304, headers)\n return response.end()\n }\n\n response.writeHead(cacheObject.status || 200, headers)\n\n return response.end(data, cacheObject.encoding)\n }\n\n function syncOptions() {\n for (var i in middlewareOptions) {\n Object.assign(middlewareOptions[i].options, globalOptions, middlewareOptions[i].localOptions)\n }\n }\n\n this.clear = function (target, isAutomatic) {\n var group = index.groups[target]\n var redis = globalOptions.redisClient\n\n if (group) {\n debug('clearing group \"' + target + '\"')\n\n group.forEach(function (key) {\n debug('clearing cached entry for \"' + key + '\"')\n clearTimeout(timers[key])\n delete timers[key]\n if (!globalOptions.redisClient) {\n memCache.delete(key)\n } else {\n try {\n redis.del(key)\n } catch (err) {\n console.log('[apicache] error in redis.del(\"' + key + '\")')\n }\n }\n index.all = index.all.filter(doesntMatch(key))\n })\n\n delete index.groups[target]\n } else if (target) {\n debug('clearing ' + (isAutomatic ? 'expired' : 'cached') + ' entry for \"' + target + '\"')\n clearTimeout(timers[target])\n delete timers[target]\n // clear actual cached entry\n if (!redis) {\n memCache.delete(target)\n } else {\n try {\n redis.del(target)\n } catch (err) {\n console.log('[apicache] error in redis.del(\"' + target + '\")')\n }\n }\n\n // remove from global index\n index.all = index.all.filter(doesntMatch(target))\n\n // remove target from each group that it may exist in\n Object.keys(index.groups).forEach(function (groupName) {\n index.groups[groupName] = index.groups[groupName].filter(doesntMatch(target))\n\n // delete group if now empty\n if (!index.groups[groupName].length) {\n delete index.groups[groupName]\n }\n })\n } else {\n debug('clearing entire index')\n\n if (!redis) {\n memCache.clear()\n } else {\n // clear redis keys one by one from internal index to prevent clearing non-apicache entries\n index.all.forEach(function (key) {\n clearTimeout(timers[key])\n delete timers[key]\n try {\n redis.del(key)\n } catch (err) {\n console.log('[apicache] error in redis.del(\"' + key + '\")')\n }\n })\n }\n this.resetIndex()\n }\n\n return this.getIndex()\n }\n\n function parseDuration(duration, defaultDuration) {\n if (typeof duration === 'number') return duration\n\n if (typeof duration === 'string') {\n var split = duration.match(/^([\\d\\.,]+)\\s?(\\w+)$/)\n\n if (split.length === 3) {\n var len = parseFloat(split[1])\n var unit = split[2].replace(/s$/i, '').toLowerCase()\n if (unit === 'm') {\n unit = 'ms'\n }\n\n return (len || 1) * (t[unit] || 0)\n }\n }\n\n return defaultDuration\n }\n\n this.getDuration = function (duration) {\n return parseDuration(duration, globalOptions.defaultDuration)\n }\n\n /**\n * Return cache performance statistics (hit rate). Suitable for putting into a route:\n * \n * app.get('/api/cache/performance', (req, res) => {\n * res.json(apicache.getPerformance())\n * })\n * \n */\n this.getPerformance = function () {\n return performanceArray.map(function (p) {\n return p.report()\n })\n }\n\n this.getIndex = function (group) {\n if (group) {\n return index.groups[group]\n } else {\n return index\n }\n }\n\n this.middleware = function cache(strDuration, middlewareToggle, localOptions) {\n var duration = instance.getDuration(strDuration)\n var opt = {}\n\n middlewareOptions.push({\n options: opt,\n })\n\n var options = function (localOptions) {\n if (localOptions) {\n middlewareOptions.find(function (middleware) {\n return middleware.options === opt\n }).localOptions = localOptions\n }\n\n syncOptions()\n\n return opt\n }\n\n options(localOptions)\n\n /**\n * A Function for non tracking performance\n */\n function NOOPCachePerformance() {\n this.report = this.hit = this.miss = function () {} // noop;\n }\n\n /**\n * A function for tracking and reporting hit rate. These statistics are returned by the getPerformance() call above.\n */\n function CachePerformance() {\n /**\n * Tracks the hit rate for the last 100 requests.\n * If there have been fewer than 100 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast100 = new Uint8Array(100 / 4) // each hit is 2 bits\n\n /**\n * Tracks the hit rate for the last 1000 requests.\n * If there have been fewer than 1000 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast1000 = new Uint8Array(1000 / 4) // each hit is 2 bits\n\n /**\n * Tracks the hit rate for the last 10000 requests.\n * If there have been fewer than 10000 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast10000 = new Uint8Array(10000 / 4) // each hit is 2 bits\n\n /**\n * Tracks the hit rate for the last 100000 requests.\n * If there have been fewer than 100000 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast100000 = new Uint8Array(100000 / 4) // each hit is 2 bits\n\n /**\n * The number of calls that have passed through the middleware since the server started.\n */\n this.callCount = 0\n\n /**\n * The total number of hits since the server started\n */\n this.hitCount = 0\n\n /**\n * The key from the last cache hit. This is useful in identifying which route these statistics apply to.\n */\n this.lastCacheHit = null\n\n /**\n * The key from the last cache miss. This is useful in identifying which route these statistics apply to.\n */\n this.lastCacheMiss = null\n\n /**\n * Return performance statistics\n */\n this.report = function () {\n return {\n lastCacheHit: this.lastCacheHit,\n lastCacheMiss: this.lastCacheMiss,\n callCount: this.callCount,\n hitCount: this.hitCount,\n missCount: this.callCount - this.hitCount,\n hitRate: this.callCount == 0 ? null : this.hitCount / this.callCount,\n hitRateLast100: this.hitRate(this.hitsLast100),\n hitRateLast1000: this.hitRate(this.hitsLast1000),\n hitRateLast10000: this.hitRate(this.hitsLast10000),\n hitRateLast100000: this.hitRate(this.hitsLast100000),\n }\n }\n\n /**\n * Computes a cache hit rate from an array of hits and misses.\n * @param {Uint8Array} array An array representing hits and misses.\n * @returns a number between 0 and 1, or null if the array has no hits or misses\n */\n this.hitRate = function (array) {\n var hits = 0\n var misses = 0\n for (var i = 0; i < array.length; i++) {\n var n8 = array[i]\n for (var j = 0; j < 4; j++) {\n switch (n8 & 3) {\n case 1:\n hits++\n break\n case 2:\n misses++\n break\n }\n n8 >>= 2\n }\n }\n var total = hits + misses\n if (total == 0) return null\n return hits / total\n }\n\n /**\n * Record a hit or miss in the given array. It will be recorded at a position determined\n * by the current value of the callCount variable.\n * @param {Uint8Array} array An array representing hits and misses.\n * @param {boolean} hit true for a hit, false for a miss\n * Each element in the array is 8 bits, and encodes 4 hit/miss records.\n * Each hit or miss is encoded as to bits as follows:\n * 00 means no hit or miss has been recorded in these bits\n * 01 encodes a hit\n * 10 encodes a miss\n */\n this.recordHitInArray = function (array, hit) {\n var arrayIndex = ~~(this.callCount / 4) % array.length\n var bitOffset = (this.callCount % 4) * 2 // 2 bits per record, 4 records per uint8 array element\n var clearMask = ~(3 << bitOffset)\n var record = (hit ? 1 : 2) << bitOffset\n array[arrayIndex] = (array[arrayIndex] & clearMask) | record\n }\n\n /**\n * Records the hit or miss in the tracking arrays and increments the call count.\n * @param {boolean} hit true records a hit, false records a miss\n */\n this.recordHit = function (hit) {\n this.recordHitInArray(this.hitsLast100, hit)\n this.recordHitInArray(this.hitsLast1000, hit)\n this.recordHitInArray(this.hitsLast10000, hit)\n this.recordHitInArray(this.hitsLast100000, hit)\n if (hit) this.hitCount++\n this.callCount++\n }\n\n /**\n * Records a hit event, setting lastCacheMiss to the given key\n * @param {string} key The key that had the cache hit\n */\n this.hit = function (key) {\n this.recordHit(true)\n this.lastCacheHit = key\n }\n\n /**\n * Records a miss event, setting lastCacheMiss to the given key\n * @param {string} key The key that had the cache miss\n */\n this.miss = function (key) {\n this.recordHit(false)\n this.lastCacheMiss = key\n }\n }\n\n var perf = globalOptions.trackPerformance ? new CachePerformance() : new NOOPCachePerformance()\n\n performanceArray.push(perf)\n\n var cache = function (req, res, next) {\n function bypass() {\n debug('bypass detected, skipping cache.')\n return next()\n }\n\n // initial bypass chances\n if (!opt.enabled) return bypass()\n if (req.headers['x-apicache-bypass'] || req.headers['x-apicache-force-fetch']) return bypass()\n\n // REMOVED IN 0.11.1 TO CORRECT MIDDLEWARE TOGGLE EXECUTE ORDER\n // if (typeof middlewareToggle === 'function') {\n // if (!middlewareToggle(req, res)) return bypass()\n // } else if (middlewareToggle !== undefined && !middlewareToggle) {\n // return bypass()\n // }\n\n // embed timer\n req.apicacheTimer = new Date()\n\n // In Express 4.x the url is ambigious based on where a router is mounted. originalUrl will give the full Url\n var key = req.originalUrl || req.url\n\n // Remove querystring from key if jsonp option is enabled\n if (opt.jsonp) {\n key = url.parse(key).pathname\n }\n\n // add appendKey (either custom function or response path)\n if (typeof opt.appendKey === 'function') {\n key += '$$appendKey=' + opt.appendKey(req, res)\n } else if (opt.appendKey.length > 0) {\n var appendKey = req\n\n for (var i = 0; i < opt.appendKey.length; i++) {\n appendKey = appendKey[opt.appendKey[i]]\n }\n key += '$$appendKey=' + appendKey\n }\n\n // attempt cache hit\n var redis = opt.redisClient\n var cached = !redis ? memCache.getValue(key) : null\n\n // send if cache hit from memory-cache\n if (cached) {\n var elapsed = new Date() - req.apicacheTimer\n debug('sending cached (memory-cache) version of', key, logDuration(elapsed))\n\n perf.hit(key)\n return sendCachedResponse(req, res, cached, middlewareToggle, next, duration)\n }\n\n // send if cache hit from redis\n if (redis && redis.connected) {\n try {\n redis.hgetall(key, function (err, obj) {\n if (!err && obj && obj.response) {\n var elapsed = new Date() - req.apicacheTimer\n debug('sending cached (redis) version of', key, logDuration(elapsed))\n\n perf.hit(key)\n return sendCachedResponse(\n req,\n res,\n JSON.parse(obj.response),\n middlewareToggle,\n next,\n duration\n )\n } else {\n perf.miss(key)\n return makeResponseCacheable(\n req,\n res,\n next,\n key,\n duration,\n strDuration,\n middlewareToggle\n )\n }\n })\n } catch (err) {\n // bypass redis on error\n perf.miss(key)\n return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle)\n }\n } else {\n perf.miss(key)\n return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle)\n }\n }\n\n cache.options = options\n\n return cache\n }\n\n this.options = function (options) {\n if (options) {\n Object.assign(globalOptions, options)\n syncOptions()\n\n if ('defaultDuration' in options) {\n // Convert the default duration to a number in milliseconds (if needed)\n globalOptions.defaultDuration = parseDuration(globalOptions.defaultDuration, 3600000)\n }\n\n if (globalOptions.trackPerformance) {\n debug('WARNING: using trackPerformance flag can cause high memory usage!')\n }\n\n return this\n } else {\n return globalOptions\n }\n }\n\n this.resetIndex = function () {\n index = {\n all: [],\n groups: {},\n }\n }\n\n this.newInstance = function (config) {\n var instance = new ApiCache()\n\n if (config) {\n instance.options(config)\n }\n\n return instance\n }\n\n this.clone = function () {\n return this.newInstance(this.options())\n }\n\n // initialize index\n this.resetIndex()\n}\n\nexport default new ApiCache()\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/module/apicache.js b/dist/module/apicache.js deleted file mode 100644 index 54f9cb0..0000000 --- a/dist/module/apicache.js +++ /dev/null @@ -1,880 +0,0 @@ -function MemoryCache() { - this.cache = {} - this.size = 0 -} - -MemoryCache.prototype.add = function (key, value, time, timeoutCallback) { - var old = this.cache[key] - var instance = this - - var entry = { - value: value, - expire: time + Date.now(), - timeout: setTimeout(function () { - instance.delete(key) - return timeoutCallback && typeof timeoutCallback === 'function' && timeoutCallback(value, key) - }, time), - } - - this.cache[key] = entry - this.size = Object.keys(this.cache).length - - return entry -} - -MemoryCache.prototype.delete = function (key) { - var entry = this.cache[key] - - if (entry) { - clearTimeout(entry.timeout) - } - - delete this.cache[key] - - this.size = Object.keys(this.cache).length - - return null -} - -MemoryCache.prototype.get = function (key) { - var entry = this.cache[key] - - return entry -} - -MemoryCache.prototype.getValue = function (key) { - var entry = this.get(key) - - return entry && entry.value -} - -MemoryCache.prototype.clear = function () { - Object.keys(this.cache).forEach(function (key) { - this.delete(key) - }, this) - - return true -} - -var name = 'apicache' -var version = '1.5.3' -var scripts = { - lint: 'eslint src', - test2: "nyc mocha $(find test -name '*_test.js') --recursive", - test: 'nyc jest --verbose', - dev: 'yarn test --watch', - coverage: 'nyc report --reporter=text-lcov | coveralls', - build: 'rollup -c', - build2: 'rollup src/index.js --format cjs --file dist/apicache.js', -} -var engines = { - node: '>=8', -} -var description = - 'An ultra-simplified API response caching middleware for Express/Node using plain-english durations.' -var main = 'dist/main/apicache.js' -var module = 'dist/module/apicache.js' -var repository = { - type: 'git', - url: 'https://github.com/kwhitley/apicache.git', -} -var keywords = [ - 'cache', - 'API', - 'redis', - 'memcache', - 'response', - 'express', - 'JSON', - 'duration', - 'middleware', - 'memory', -] -var author = 'Kevin R. Whitley (http://krwhitley.com)' -var license = 'MIT' -var bugs = { - url: 'https://github.com/kwhitley/apicache/issues', - email: 'krwhitley@gmail.com', -} -var devDependencies = { - '@rollup/plugin-json': '^4.0.3', - chai: '^4.2.0', - compression: '^1.7.4', - coveralls: '^3.1.0', - eslint: '^7.0.0', - express: '^4.17.1', - fakeredis: '^2.0.0', - husky: '^4.2.5', - jest: '^26.0.1', - mocha: '^7.0.0', - nyc: '^15.0.1', - prettier: '^2.0.5', - 'pretty-quick': '^2.0.1', - restify: '^7.7.0', - 'restify-etag-cache': '^1.0.12', - rollup: '^2.10.2', - 'rollup-plugin-sourcemaps': '^0.6.2', - 'rollup-plugin-terser': '^5.3.0', - supertest: '^4.0.2', - 'yarn-release': '^1.10.2', -} -var dependencies = {} -var husky = { - hooks: { - 'pre-commit': 'pretty-quick --staged', - }, -} -var pkg = { - name: name, - version: version, - scripts: scripts, - engines: engines, - description: description, - main: main, - module: module, - repository: repository, - keywords: keywords, - author: author, - license: license, - bugs: bugs, - devDependencies: devDependencies, - dependencies: dependencies, - husky: husky, -} - -var t = { - ms: 1, - second: 1000, - minute: 60000, - hour: 3600000, - day: 3600000 * 24, - week: 3600000 * 24 * 7, - month: 3600000 * 24 * 30, -} - -var instances = [] - -var matches = function (a) { - return function (b) { - return a === b - } -} - -var doesntMatch = function (a) { - return function (b) { - return !matches(a)(b) - } -} - -var logDuration = function (d, prefix) { - var str = d > 1000 ? (d / 1000).toFixed(2) + 'sec' : d + 'ms' - return '\x1b[33m- ' + (prefix ? prefix + ' ' : '') + str + '\x1b[0m' -} - -function getSafeHeaders(res) { - return res.getHeaders ? res.getHeaders() : res._headers -} - -function ApiCache() { - var memCache = new MemoryCache() - - var globalOptions = { - debug: false, - defaultDuration: 3600000, - enabled: true, - appendKey: [], - jsonp: false, - redisClient: false, - headerBlacklist: [], - statusCodes: { - include: [], - exclude: [], - }, - events: { - expire: undefined, - }, - headers: { - // 'cache-control': 'no-cache' // example of header overwrite - }, - trackPerformance: false, - } - - var middlewareOptions = [] - var instance = this - var index = null - var timers = {} - var performanceArray = [] // for tracking cache hit rate - - instances.push(this) - this.id = instances.length - - function debug(a, b, c, d) { - var arr = ['\x1b[36m[apicache]\x1b[0m', a, b, c, d].filter(function (arg) { - return arg !== undefined - }) - var debugEnv = process.env.DEBUG && process.env.DEBUG.split(',').indexOf('apicache') !== -1 - - return (globalOptions.debug || debugEnv) && console.log.apply(null, arr) - } - - function shouldCacheResponse(request, response, toggle) { - var opt = globalOptions - var codes = opt.statusCodes - - if (!response) return false - - if (toggle && !toggle(request, response)) { - return false - } - - if (codes.exclude && codes.exclude.length && codes.exclude.indexOf(response.statusCode) !== -1) - return false - if (codes.include && codes.include.length && codes.include.indexOf(response.statusCode) === -1) - return false - - return true - } - - function addIndexEntries(key, req) { - var groupName = req.apicacheGroup - - if (groupName) { - debug('group detected "' + groupName + '"') - var group = (index.groups[groupName] = index.groups[groupName] || []) - group.unshift(key) - } - - index.all.unshift(key) - } - - function filterBlacklistedHeaders(headers) { - return Object.keys(headers) - .filter(function (key) { - return globalOptions.headerBlacklist.indexOf(key) === -1 - }) - .reduce(function (acc, header) { - acc[header] = headers[header] - return acc - }, {}) - } - - function createCacheObject(status, headers, data, encoding) { - return { - status: status, - headers: filterBlacklistedHeaders(headers), - data: data, - encoding: encoding, - timestamp: new Date().getTime() / 1000, // seconds since epoch. This is used to properly decrement max-age headers in cached responses. - } - } - - function cacheResponse(key, value, duration) { - var redis = globalOptions.redisClient - var expireCallback = globalOptions.events.expire - - if (redis && redis.connected) { - try { - redis.hset(key, 'response', JSON.stringify(value)) - redis.hset(key, 'duration', duration) - redis.expire(key, duration / 1000, expireCallback || function () {}) - } catch (err) { - debug('[apicache] error in redis.hset()') - } - } else { - memCache.add(key, value, duration, expireCallback) - } - - // add automatic cache clearing from duration, includes max limit on setTimeout - timers[key] = setTimeout(function () { - instance.clear(key, true) - }, Math.min(duration, 2147483647)) - } - - function accumulateContent(res, content) { - if (content) { - if (typeof content == 'string') { - res._apicache.content = (res._apicache.content || '') + content - } else if (Buffer.isBuffer(content)) { - var oldContent = res._apicache.content - - if (typeof oldContent === 'string') { - oldContent = !Buffer.from ? new Buffer(oldContent) : Buffer.from(oldContent) - } - - if (!oldContent) { - oldContent = !Buffer.alloc ? new Buffer(0) : Buffer.alloc(0) - } - - res._apicache.content = Buffer.concat( - [oldContent, content], - oldContent.length + content.length - ) - } else { - res._apicache.content = content - } - } - } - - function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) { - // monkeypatch res.end to create cache object - res._apicache = { - write: res.write, - writeHead: res.writeHead, - end: res.end, - cacheable: true, - content: undefined, - } - - // append header overwrites if applicable - Object.keys(globalOptions.headers).forEach(function (name) { - res.setHeader(name, globalOptions.headers[name]) - }) - - res.writeHead = function () { - // add cache control headers - if (!globalOptions.headers['cache-control']) { - if (shouldCacheResponse(req, res, toggle)) { - res.setHeader('cache-control', 'max-age=' + (duration / 1000).toFixed(0)) - } else { - res.setHeader('cache-control', 'no-cache, no-store, must-revalidate') - } - } - - res._apicache.headers = Object.assign({}, getSafeHeaders(res)) - return res._apicache.writeHead.apply(this, arguments) - } - - // patch res.write - res.write = function (content) { - accumulateContent(res, content) - return res._apicache.write.apply(this, arguments) - } - - // patch res.end - res.end = function (content, encoding) { - if (shouldCacheResponse(req, res, toggle)) { - accumulateContent(res, content) - - if (res._apicache.cacheable && res._apicache.content) { - addIndexEntries(key, req) - var headers = res._apicache.headers || getSafeHeaders(res) - var cacheObject = createCacheObject( - res.statusCode, - headers, - res._apicache.content, - encoding - ) - cacheResponse(key, cacheObject, duration) - - // display log entry - var elapsed = new Date() - req.apicacheTimer - debug('adding cache entry for "' + key + '" @ ' + strDuration, logDuration(elapsed)) - debug('_apicache.headers: ', res._apicache.headers) - debug('res.getHeaders(): ', getSafeHeaders(res)) - debug('cacheObject: ', cacheObject) - } - } - - return res._apicache.end.apply(this, arguments) - } - - next() - } - - function sendCachedResponse(request, response, cacheObject, toggle, next, duration) { - if (toggle && !toggle(request, response)) { - return next() - } - - var headers = getSafeHeaders(response) - - Object.assign(headers, filterBlacklistedHeaders(cacheObject.headers || {}), { - // set properly-decremented max-age header. This ensures that max-age is in sync with the cache expiration. - 'cache-control': - 'max-age=' + - Math.max( - 0, - (duration / 1000 - (new Date().getTime() / 1000 - cacheObject.timestamp)).toFixed(0) - ), - }) - - // only embed apicache headers when not in production environment - if (process.env.NODE_ENV !== 'production') { - Object.assign(headers, { - 'apicache-store': globalOptions.redisClient ? 'redis' : 'memory', - 'apicache-version': pkg.version, - }) - } - - // unstringify buffers - var data = cacheObject.data - if (data && data.type === 'Buffer') { - data = - typeof data.data === 'number' ? new Buffer.alloc(data.data) : new Buffer.from(data.data) - } - - // test Etag against If-None-Match for 304 - var cachedEtag = cacheObject.headers.etag - var requestEtag = request.headers['if-none-match'] - - if (requestEtag && cachedEtag === requestEtag) { - response.writeHead(304, headers) - return response.end() - } - - response.writeHead(cacheObject.status || 200, headers) - - return response.end(data, cacheObject.encoding) - } - - function syncOptions() { - for (var i in middlewareOptions) { - Object.assign(middlewareOptions[i].options, globalOptions, middlewareOptions[i].localOptions) - } - } - - this.clear = function (target, isAutomatic) { - var group = index.groups[target] - var redis = globalOptions.redisClient - - if (group) { - debug('clearing group "' + target + '"') - - group.forEach(function (key) { - debug('clearing cached entry for "' + key + '"') - clearTimeout(timers[key]) - delete timers[key] - if (!globalOptions.redisClient) { - memCache.delete(key) - } else { - try { - redis.del(key) - } catch (err) { - console.log('[apicache] error in redis.del("' + key + '")') - } - } - index.all = index.all.filter(doesntMatch(key)) - }) - - delete index.groups[target] - } else if (target) { - debug('clearing ' + (isAutomatic ? 'expired' : 'cached') + ' entry for "' + target + '"') - clearTimeout(timers[target]) - delete timers[target] - // clear actual cached entry - if (!redis) { - memCache.delete(target) - } else { - try { - redis.del(target) - } catch (err) { - console.log('[apicache] error in redis.del("' + target + '")') - } - } - - // remove from global index - index.all = index.all.filter(doesntMatch(target)) - - // remove target from each group that it may exist in - Object.keys(index.groups).forEach(function (groupName) { - index.groups[groupName] = index.groups[groupName].filter(doesntMatch(target)) - - // delete group if now empty - if (!index.groups[groupName].length) { - delete index.groups[groupName] - } - }) - } else { - debug('clearing entire index') - - if (!redis) { - memCache.clear() - } else { - // clear redis keys one by one from internal index to prevent clearing non-apicache entries - index.all.forEach(function (key) { - clearTimeout(timers[key]) - delete timers[key] - try { - redis.del(key) - } catch (err) { - console.log('[apicache] error in redis.del("' + key + '")') - } - }) - } - this.resetIndex() - } - - return this.getIndex() - } - - function parseDuration(duration, defaultDuration) { - if (typeof duration === 'number') return duration - - if (typeof duration === 'string') { - var split = duration.match(/^([\d\.,]+)\s?(\w+)$/) - - if (split.length === 3) { - var len = parseFloat(split[1]) - var unit = split[2].replace(/s$/i, '').toLowerCase() - if (unit === 'm') { - unit = 'ms' - } - - return (len || 1) * (t[unit] || 0) - } - } - - return defaultDuration - } - - this.getDuration = function (duration) { - return parseDuration(duration, globalOptions.defaultDuration) - } - - /** - * Return cache performance statistics (hit rate). Suitable for putting into a route: - * - * app.get('/api/cache/performance', (req, res) => { - * res.json(apicache.getPerformance()) - * }) - * - */ - this.getPerformance = function () { - return performanceArray.map(function (p) { - return p.report() - }) - } - - this.getIndex = function (group) { - if (group) { - return index.groups[group] - } else { - return index - } - } - - this.middleware = function cache(strDuration, middlewareToggle, localOptions) { - var duration = instance.getDuration(strDuration) - var opt = {} - - middlewareOptions.push({ - options: opt, - }) - - var options = function (localOptions) { - if (localOptions) { - middlewareOptions.find(function (middleware) { - return middleware.options === opt - }).localOptions = localOptions - } - - syncOptions() - - return opt - } - - options(localOptions) - - /** - * A Function for non tracking performance - */ - function NOOPCachePerformance() { - this.report = this.hit = this.miss = function () {} // noop; - } - - /** - * A function for tracking and reporting hit rate. These statistics are returned by the getPerformance() call above. - */ - function CachePerformance() { - /** - * Tracks the hit rate for the last 100 requests. - * If there have been fewer than 100 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast100 = new Uint8Array(100 / 4) // each hit is 2 bits - - /** - * Tracks the hit rate for the last 1000 requests. - * If there have been fewer than 1000 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast1000 = new Uint8Array(1000 / 4) // each hit is 2 bits - - /** - * Tracks the hit rate for the last 10000 requests. - * If there have been fewer than 10000 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast10000 = new Uint8Array(10000 / 4) // each hit is 2 bits - - /** - * Tracks the hit rate for the last 100000 requests. - * If there have been fewer than 100000 requests, the hit rate just considers the requests that have happened. - */ - this.hitsLast100000 = new Uint8Array(100000 / 4) // each hit is 2 bits - - /** - * The number of calls that have passed through the middleware since the server started. - */ - this.callCount = 0 - - /** - * The total number of hits since the server started - */ - this.hitCount = 0 - - /** - * The key from the last cache hit. This is useful in identifying which route these statistics apply to. - */ - this.lastCacheHit = null - - /** - * The key from the last cache miss. This is useful in identifying which route these statistics apply to. - */ - this.lastCacheMiss = null - - /** - * Return performance statistics - */ - this.report = function () { - return { - lastCacheHit: this.lastCacheHit, - lastCacheMiss: this.lastCacheMiss, - callCount: this.callCount, - hitCount: this.hitCount, - missCount: this.callCount - this.hitCount, - hitRate: this.callCount == 0 ? null : this.hitCount / this.callCount, - hitRateLast100: this.hitRate(this.hitsLast100), - hitRateLast1000: this.hitRate(this.hitsLast1000), - hitRateLast10000: this.hitRate(this.hitsLast10000), - hitRateLast100000: this.hitRate(this.hitsLast100000), - } - } - - /** - * Computes a cache hit rate from an array of hits and misses. - * @param {Uint8Array} array An array representing hits and misses. - * @returns a number between 0 and 1, or null if the array has no hits or misses - */ - this.hitRate = function (array) { - var hits = 0 - var misses = 0 - for (var i = 0; i < array.length; i++) { - var n8 = array[i] - for (var j = 0; j < 4; j++) { - switch (n8 & 3) { - case 1: - hits++ - break - case 2: - misses++ - break - } - n8 >>= 2 - } - } - var total = hits + misses - if (total == 0) return null - return hits / total - } - - /** - * Record a hit or miss in the given array. It will be recorded at a position determined - * by the current value of the callCount variable. - * @param {Uint8Array} array An array representing hits and misses. - * @param {boolean} hit true for a hit, false for a miss - * Each element in the array is 8 bits, and encodes 4 hit/miss records. - * Each hit or miss is encoded as to bits as follows: - * 00 means no hit or miss has been recorded in these bits - * 01 encodes a hit - * 10 encodes a miss - */ - this.recordHitInArray = function (array, hit) { - var arrayIndex = ~~(this.callCount / 4) % array.length - var bitOffset = (this.callCount % 4) * 2 // 2 bits per record, 4 records per uint8 array element - var clearMask = ~(3 << bitOffset) - var record = (hit ? 1 : 2) << bitOffset - array[arrayIndex] = (array[arrayIndex] & clearMask) | record - } - - /** - * Records the hit or miss in the tracking arrays and increments the call count. - * @param {boolean} hit true records a hit, false records a miss - */ - this.recordHit = function (hit) { - this.recordHitInArray(this.hitsLast100, hit) - this.recordHitInArray(this.hitsLast1000, hit) - this.recordHitInArray(this.hitsLast10000, hit) - this.recordHitInArray(this.hitsLast100000, hit) - if (hit) this.hitCount++ - this.callCount++ - } - - /** - * Records a hit event, setting lastCacheMiss to the given key - * @param {string} key The key that had the cache hit - */ - this.hit = function (key) { - this.recordHit(true) - this.lastCacheHit = key - } - - /** - * Records a miss event, setting lastCacheMiss to the given key - * @param {string} key The key that had the cache miss - */ - this.miss = function (key) { - this.recordHit(false) - this.lastCacheMiss = key - } - } - - var perf = globalOptions.trackPerformance ? new CachePerformance() : new NOOPCachePerformance() - - performanceArray.push(perf) - - var cache = function (req, res, next) { - function bypass() { - debug('bypass detected, skipping cache.') - return next() - } - - // initial bypass chances - if (!opt.enabled) return bypass() - if (req.headers['x-apicache-bypass'] || req.headers['x-apicache-force-fetch']) return bypass() - - // REMOVED IN 0.11.1 TO CORRECT MIDDLEWARE TOGGLE EXECUTE ORDER - // if (typeof middlewareToggle === 'function') { - // if (!middlewareToggle(req, res)) return bypass() - // } else if (middlewareToggle !== undefined && !middlewareToggle) { - // return bypass() - // } - - // embed timer - req.apicacheTimer = new Date() - - // In Express 4.x the url is ambigious based on where a router is mounted. originalUrl will give the full Url - var key = req.originalUrl || req.url - - // Remove querystring from key if jsonp option is enabled - if (opt.jsonp) { - key = url.parse(key).pathname - } - - // add appendKey (either custom function or response path) - if (typeof opt.appendKey === 'function') { - key += '$$appendKey=' + opt.appendKey(req, res) - } else if (opt.appendKey.length > 0) { - var appendKey = req - - for (var i = 0; i < opt.appendKey.length; i++) { - appendKey = appendKey[opt.appendKey[i]] - } - key += '$$appendKey=' + appendKey - } - - // attempt cache hit - var redis = opt.redisClient - var cached = !redis ? memCache.getValue(key) : null - - // send if cache hit from memory-cache - if (cached) { - var elapsed = new Date() - req.apicacheTimer - debug('sending cached (memory-cache) version of', key, logDuration(elapsed)) - - perf.hit(key) - return sendCachedResponse(req, res, cached, middlewareToggle, next, duration) - } - - // send if cache hit from redis - if (redis && redis.connected) { - try { - redis.hgetall(key, function (err, obj) { - if (!err && obj && obj.response) { - var elapsed = new Date() - req.apicacheTimer - debug('sending cached (redis) version of', key, logDuration(elapsed)) - - perf.hit(key) - return sendCachedResponse( - req, - res, - JSON.parse(obj.response), - middlewareToggle, - next, - duration - ) - } else { - perf.miss(key) - return makeResponseCacheable( - req, - res, - next, - key, - duration, - strDuration, - middlewareToggle - ) - } - }) - } catch (err) { - // bypass redis on error - perf.miss(key) - return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle) - } - } else { - perf.miss(key) - return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle) - } - } - - cache.options = options - - return cache - } - - this.options = function (options) { - if (options) { - Object.assign(globalOptions, options) - syncOptions() - - if ('defaultDuration' in options) { - // Convert the default duration to a number in milliseconds (if needed) - globalOptions.defaultDuration = parseDuration(globalOptions.defaultDuration, 3600000) - } - - if (globalOptions.trackPerformance) { - debug('WARNING: using trackPerformance flag can cause high memory usage!') - } - - return this - } else { - return globalOptions - } - } - - this.resetIndex = function () { - index = { - all: [], - groups: {}, - } - } - - this.newInstance = function (config) { - var instance = new ApiCache() - - if (config) { - instance.options(config) - } - - return instance - } - - this.clone = function () { - return this.newInstance(this.options()) - } - - // initialize index - this.resetIndex() -} - -var index = new ApiCache() - -export default index -//# sourceMappingURL=apicache.js.map diff --git a/dist/module/apicache.js.map b/dist/module/apicache.js.map deleted file mode 100644 index c849f05..0000000 --- a/dist/module/apicache.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"apicache.js","sources":["../../src/memory-cache.js","../../src/index.js"],"sourcesContent":["function MemoryCache() {\n this.cache = {}\n this.size = 0\n}\n\nMemoryCache.prototype.add = function(key, value, time, timeoutCallback) {\n var old = this.cache[key]\n var instance = this\n\n var entry = {\n value: value,\n expire: time + Date.now(),\n timeout: setTimeout(function() {\n instance.delete(key)\n return timeoutCallback && typeof timeoutCallback === 'function' && timeoutCallback(value, key)\n }, time),\n }\n\n this.cache[key] = entry\n this.size = Object.keys(this.cache).length\n\n return entry\n}\n\nMemoryCache.prototype.delete = function(key) {\n var entry = this.cache[key]\n\n if (entry) {\n clearTimeout(entry.timeout)\n }\n\n delete this.cache[key]\n\n this.size = Object.keys(this.cache).length\n\n return null\n}\n\nMemoryCache.prototype.get = function(key) {\n var entry = this.cache[key]\n\n return entry\n}\n\nMemoryCache.prototype.getValue = function(key) {\n var entry = this.get(key)\n\n return entry && entry.value\n}\n\nMemoryCache.prototype.clear = function() {\n Object.keys(this.cache).forEach(function(key) {\n this.delete(key)\n }, this)\n\n return true\n}\n\nexport default MemoryCache\n","import MemoryCache from './memory-cache'\nimport pkg from '../package.json'\n\nvar t = {\n ms: 1,\n second: 1000,\n minute: 60000,\n hour: 3600000,\n day: 3600000 * 24,\n week: 3600000 * 24 * 7,\n month: 3600000 * 24 * 30,\n}\n\nvar instances = []\n\nvar matches = function (a) {\n return function (b) {\n return a === b\n }\n}\n\nvar doesntMatch = function (a) {\n return function (b) {\n return !matches(a)(b)\n }\n}\n\nvar logDuration = function (d, prefix) {\n var str = d > 1000 ? (d / 1000).toFixed(2) + 'sec' : d + 'ms'\n return '\\x1b[33m- ' + (prefix ? prefix + ' ' : '') + str + '\\x1b[0m'\n}\n\nfunction getSafeHeaders(res) {\n return res.getHeaders ? res.getHeaders() : res._headers\n}\n\nfunction ApiCache() {\n var memCache = new MemoryCache()\n\n var globalOptions = {\n debug: false,\n defaultDuration: 3600000,\n enabled: true,\n appendKey: [],\n jsonp: false,\n redisClient: false,\n headerBlacklist: [],\n statusCodes: {\n include: [],\n exclude: [],\n },\n events: {\n expire: undefined,\n },\n headers: {\n // 'cache-control': 'no-cache' // example of header overwrite\n },\n trackPerformance: false,\n }\n\n var middlewareOptions = []\n var instance = this\n var index = null\n var timers = {}\n var performanceArray = [] // for tracking cache hit rate\n\n instances.push(this)\n this.id = instances.length\n\n function debug(a, b, c, d) {\n var arr = ['\\x1b[36m[apicache]\\x1b[0m', a, b, c, d].filter(function (arg) {\n return arg !== undefined\n })\n var debugEnv = process.env.DEBUG && process.env.DEBUG.split(',').indexOf('apicache') !== -1\n\n return (globalOptions.debug || debugEnv) && console.log.apply(null, arr)\n }\n\n function shouldCacheResponse(request, response, toggle) {\n var opt = globalOptions\n var codes = opt.statusCodes\n\n if (!response) return false\n\n if (toggle && !toggle(request, response)) {\n return false\n }\n\n if (codes.exclude && codes.exclude.length && codes.exclude.indexOf(response.statusCode) !== -1)\n return false\n if (codes.include && codes.include.length && codes.include.indexOf(response.statusCode) === -1)\n return false\n\n return true\n }\n\n function addIndexEntries(key, req) {\n var groupName = req.apicacheGroup\n\n if (groupName) {\n debug('group detected \"' + groupName + '\"')\n var group = (index.groups[groupName] = index.groups[groupName] || [])\n group.unshift(key)\n }\n\n index.all.unshift(key)\n }\n\n function filterBlacklistedHeaders(headers) {\n return Object.keys(headers)\n .filter(function (key) {\n return globalOptions.headerBlacklist.indexOf(key) === -1\n })\n .reduce(function (acc, header) {\n acc[header] = headers[header]\n return acc\n }, {})\n }\n\n function createCacheObject(status, headers, data, encoding) {\n return {\n status: status,\n headers: filterBlacklistedHeaders(headers),\n data: data,\n encoding: encoding,\n timestamp: new Date().getTime() / 1000, // seconds since epoch. This is used to properly decrement max-age headers in cached responses.\n }\n }\n\n function cacheResponse(key, value, duration) {\n var redis = globalOptions.redisClient\n var expireCallback = globalOptions.events.expire\n\n if (redis && redis.connected) {\n try {\n redis.hset(key, 'response', JSON.stringify(value))\n redis.hset(key, 'duration', duration)\n redis.expire(key, duration / 1000, expireCallback || function () {})\n } catch (err) {\n debug('[apicache] error in redis.hset()')\n }\n } else {\n memCache.add(key, value, duration, expireCallback)\n }\n\n // add automatic cache clearing from duration, includes max limit on setTimeout\n timers[key] = setTimeout(function () {\n instance.clear(key, true)\n }, Math.min(duration, 2147483647))\n }\n\n function accumulateContent(res, content) {\n if (content) {\n if (typeof content == 'string') {\n res._apicache.content = (res._apicache.content || '') + content\n } else if (Buffer.isBuffer(content)) {\n var oldContent = res._apicache.content\n\n if (typeof oldContent === 'string') {\n oldContent = !Buffer.from ? new Buffer(oldContent) : Buffer.from(oldContent)\n }\n\n if (!oldContent) {\n oldContent = !Buffer.alloc ? new Buffer(0) : Buffer.alloc(0)\n }\n\n res._apicache.content = Buffer.concat(\n [oldContent, content],\n oldContent.length + content.length\n )\n } else {\n res._apicache.content = content\n }\n }\n }\n\n function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) {\n // monkeypatch res.end to create cache object\n res._apicache = {\n write: res.write,\n writeHead: res.writeHead,\n end: res.end,\n cacheable: true,\n content: undefined,\n }\n\n // append header overwrites if applicable\n Object.keys(globalOptions.headers).forEach(function (name) {\n res.setHeader(name, globalOptions.headers[name])\n })\n\n res.writeHead = function () {\n // add cache control headers\n if (!globalOptions.headers['cache-control']) {\n if (shouldCacheResponse(req, res, toggle)) {\n res.setHeader('cache-control', 'max-age=' + (duration / 1000).toFixed(0))\n } else {\n res.setHeader('cache-control', 'no-cache, no-store, must-revalidate')\n }\n }\n\n res._apicache.headers = Object.assign({}, getSafeHeaders(res))\n return res._apicache.writeHead.apply(this, arguments)\n }\n\n // patch res.write\n res.write = function (content) {\n accumulateContent(res, content)\n return res._apicache.write.apply(this, arguments)\n }\n\n // patch res.end\n res.end = function (content, encoding) {\n if (shouldCacheResponse(req, res, toggle)) {\n accumulateContent(res, content)\n\n if (res._apicache.cacheable && res._apicache.content) {\n addIndexEntries(key, req)\n var headers = res._apicache.headers || getSafeHeaders(res)\n var cacheObject = createCacheObject(\n res.statusCode,\n headers,\n res._apicache.content,\n encoding\n )\n cacheResponse(key, cacheObject, duration)\n\n // display log entry\n var elapsed = new Date() - req.apicacheTimer\n debug('adding cache entry for \"' + key + '\" @ ' + strDuration, logDuration(elapsed))\n debug('_apicache.headers: ', res._apicache.headers)\n debug('res.getHeaders(): ', getSafeHeaders(res))\n debug('cacheObject: ', cacheObject)\n }\n }\n\n return res._apicache.end.apply(this, arguments)\n }\n\n next()\n }\n\n function sendCachedResponse(request, response, cacheObject, toggle, next, duration) {\n if (toggle && !toggle(request, response)) {\n return next()\n }\n\n var headers = getSafeHeaders(response)\n\n Object.assign(headers, filterBlacklistedHeaders(cacheObject.headers || {}), {\n // set properly-decremented max-age header. This ensures that max-age is in sync with the cache expiration.\n 'cache-control':\n 'max-age=' +\n Math.max(\n 0,\n (duration / 1000 - (new Date().getTime() / 1000 - cacheObject.timestamp)).toFixed(0)\n ),\n })\n\n // only embed apicache headers when not in production environment\n if (process.env.NODE_ENV !== 'production') {\n Object.assign(headers, {\n 'apicache-store': globalOptions.redisClient ? 'redis' : 'memory',\n 'apicache-version': pkg.version,\n })\n }\n\n // unstringify buffers\n var data = cacheObject.data\n if (data && data.type === 'Buffer') {\n data =\n typeof data.data === 'number' ? new Buffer.alloc(data.data) : new Buffer.from(data.data)\n }\n\n // test Etag against If-None-Match for 304\n var cachedEtag = cacheObject.headers.etag\n var requestEtag = request.headers['if-none-match']\n\n if (requestEtag && cachedEtag === requestEtag) {\n response.writeHead(304, headers)\n return response.end()\n }\n\n response.writeHead(cacheObject.status || 200, headers)\n\n return response.end(data, cacheObject.encoding)\n }\n\n function syncOptions() {\n for (var i in middlewareOptions) {\n Object.assign(middlewareOptions[i].options, globalOptions, middlewareOptions[i].localOptions)\n }\n }\n\n this.clear = function (target, isAutomatic) {\n var group = index.groups[target]\n var redis = globalOptions.redisClient\n\n if (group) {\n debug('clearing group \"' + target + '\"')\n\n group.forEach(function (key) {\n debug('clearing cached entry for \"' + key + '\"')\n clearTimeout(timers[key])\n delete timers[key]\n if (!globalOptions.redisClient) {\n memCache.delete(key)\n } else {\n try {\n redis.del(key)\n } catch (err) {\n console.log('[apicache] error in redis.del(\"' + key + '\")')\n }\n }\n index.all = index.all.filter(doesntMatch(key))\n })\n\n delete index.groups[target]\n } else if (target) {\n debug('clearing ' + (isAutomatic ? 'expired' : 'cached') + ' entry for \"' + target + '\"')\n clearTimeout(timers[target])\n delete timers[target]\n // clear actual cached entry\n if (!redis) {\n memCache.delete(target)\n } else {\n try {\n redis.del(target)\n } catch (err) {\n console.log('[apicache] error in redis.del(\"' + target + '\")')\n }\n }\n\n // remove from global index\n index.all = index.all.filter(doesntMatch(target))\n\n // remove target from each group that it may exist in\n Object.keys(index.groups).forEach(function (groupName) {\n index.groups[groupName] = index.groups[groupName].filter(doesntMatch(target))\n\n // delete group if now empty\n if (!index.groups[groupName].length) {\n delete index.groups[groupName]\n }\n })\n } else {\n debug('clearing entire index')\n\n if (!redis) {\n memCache.clear()\n } else {\n // clear redis keys one by one from internal index to prevent clearing non-apicache entries\n index.all.forEach(function (key) {\n clearTimeout(timers[key])\n delete timers[key]\n try {\n redis.del(key)\n } catch (err) {\n console.log('[apicache] error in redis.del(\"' + key + '\")')\n }\n })\n }\n this.resetIndex()\n }\n\n return this.getIndex()\n }\n\n function parseDuration(duration, defaultDuration) {\n if (typeof duration === 'number') return duration\n\n if (typeof duration === 'string') {\n var split = duration.match(/^([\\d\\.,]+)\\s?(\\w+)$/)\n\n if (split.length === 3) {\n var len = parseFloat(split[1])\n var unit = split[2].replace(/s$/i, '').toLowerCase()\n if (unit === 'm') {\n unit = 'ms'\n }\n\n return (len || 1) * (t[unit] || 0)\n }\n }\n\n return defaultDuration\n }\n\n this.getDuration = function (duration) {\n return parseDuration(duration, globalOptions.defaultDuration)\n }\n\n /**\n * Return cache performance statistics (hit rate). Suitable for putting into a route:\n * \n * app.get('/api/cache/performance', (req, res) => {\n * res.json(apicache.getPerformance())\n * })\n * \n */\n this.getPerformance = function () {\n return performanceArray.map(function (p) {\n return p.report()\n })\n }\n\n this.getIndex = function (group) {\n if (group) {\n return index.groups[group]\n } else {\n return index\n }\n }\n\n this.middleware = function cache(strDuration, middlewareToggle, localOptions) {\n var duration = instance.getDuration(strDuration)\n var opt = {}\n\n middlewareOptions.push({\n options: opt,\n })\n\n var options = function (localOptions) {\n if (localOptions) {\n middlewareOptions.find(function (middleware) {\n return middleware.options === opt\n }).localOptions = localOptions\n }\n\n syncOptions()\n\n return opt\n }\n\n options(localOptions)\n\n /**\n * A Function for non tracking performance\n */\n function NOOPCachePerformance() {\n this.report = this.hit = this.miss = function () {} // noop;\n }\n\n /**\n * A function for tracking and reporting hit rate. These statistics are returned by the getPerformance() call above.\n */\n function CachePerformance() {\n /**\n * Tracks the hit rate for the last 100 requests.\n * If there have been fewer than 100 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast100 = new Uint8Array(100 / 4) // each hit is 2 bits\n\n /**\n * Tracks the hit rate for the last 1000 requests.\n * If there have been fewer than 1000 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast1000 = new Uint8Array(1000 / 4) // each hit is 2 bits\n\n /**\n * Tracks the hit rate for the last 10000 requests.\n * If there have been fewer than 10000 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast10000 = new Uint8Array(10000 / 4) // each hit is 2 bits\n\n /**\n * Tracks the hit rate for the last 100000 requests.\n * If there have been fewer than 100000 requests, the hit rate just considers the requests that have happened.\n */\n this.hitsLast100000 = new Uint8Array(100000 / 4) // each hit is 2 bits\n\n /**\n * The number of calls that have passed through the middleware since the server started.\n */\n this.callCount = 0\n\n /**\n * The total number of hits since the server started\n */\n this.hitCount = 0\n\n /**\n * The key from the last cache hit. This is useful in identifying which route these statistics apply to.\n */\n this.lastCacheHit = null\n\n /**\n * The key from the last cache miss. This is useful in identifying which route these statistics apply to.\n */\n this.lastCacheMiss = null\n\n /**\n * Return performance statistics\n */\n this.report = function () {\n return {\n lastCacheHit: this.lastCacheHit,\n lastCacheMiss: this.lastCacheMiss,\n callCount: this.callCount,\n hitCount: this.hitCount,\n missCount: this.callCount - this.hitCount,\n hitRate: this.callCount == 0 ? null : this.hitCount / this.callCount,\n hitRateLast100: this.hitRate(this.hitsLast100),\n hitRateLast1000: this.hitRate(this.hitsLast1000),\n hitRateLast10000: this.hitRate(this.hitsLast10000),\n hitRateLast100000: this.hitRate(this.hitsLast100000),\n }\n }\n\n /**\n * Computes a cache hit rate from an array of hits and misses.\n * @param {Uint8Array} array An array representing hits and misses.\n * @returns a number between 0 and 1, or null if the array has no hits or misses\n */\n this.hitRate = function (array) {\n var hits = 0\n var misses = 0\n for (var i = 0; i < array.length; i++) {\n var n8 = array[i]\n for (var j = 0; j < 4; j++) {\n switch (n8 & 3) {\n case 1:\n hits++\n break\n case 2:\n misses++\n break\n }\n n8 >>= 2\n }\n }\n var total = hits + misses\n if (total == 0) return null\n return hits / total\n }\n\n /**\n * Record a hit or miss in the given array. It will be recorded at a position determined\n * by the current value of the callCount variable.\n * @param {Uint8Array} array An array representing hits and misses.\n * @param {boolean} hit true for a hit, false for a miss\n * Each element in the array is 8 bits, and encodes 4 hit/miss records.\n * Each hit or miss is encoded as to bits as follows:\n * 00 means no hit or miss has been recorded in these bits\n * 01 encodes a hit\n * 10 encodes a miss\n */\n this.recordHitInArray = function (array, hit) {\n var arrayIndex = ~~(this.callCount / 4) % array.length\n var bitOffset = (this.callCount % 4) * 2 // 2 bits per record, 4 records per uint8 array element\n var clearMask = ~(3 << bitOffset)\n var record = (hit ? 1 : 2) << bitOffset\n array[arrayIndex] = (array[arrayIndex] & clearMask) | record\n }\n\n /**\n * Records the hit or miss in the tracking arrays and increments the call count.\n * @param {boolean} hit true records a hit, false records a miss\n */\n this.recordHit = function (hit) {\n this.recordHitInArray(this.hitsLast100, hit)\n this.recordHitInArray(this.hitsLast1000, hit)\n this.recordHitInArray(this.hitsLast10000, hit)\n this.recordHitInArray(this.hitsLast100000, hit)\n if (hit) this.hitCount++\n this.callCount++\n }\n\n /**\n * Records a hit event, setting lastCacheMiss to the given key\n * @param {string} key The key that had the cache hit\n */\n this.hit = function (key) {\n this.recordHit(true)\n this.lastCacheHit = key\n }\n\n /**\n * Records a miss event, setting lastCacheMiss to the given key\n * @param {string} key The key that had the cache miss\n */\n this.miss = function (key) {\n this.recordHit(false)\n this.lastCacheMiss = key\n }\n }\n\n var perf = globalOptions.trackPerformance ? new CachePerformance() : new NOOPCachePerformance()\n\n performanceArray.push(perf)\n\n var cache = function (req, res, next) {\n function bypass() {\n debug('bypass detected, skipping cache.')\n return next()\n }\n\n // initial bypass chances\n if (!opt.enabled) return bypass()\n if (req.headers['x-apicache-bypass'] || req.headers['x-apicache-force-fetch']) return bypass()\n\n // REMOVED IN 0.11.1 TO CORRECT MIDDLEWARE TOGGLE EXECUTE ORDER\n // if (typeof middlewareToggle === 'function') {\n // if (!middlewareToggle(req, res)) return bypass()\n // } else if (middlewareToggle !== undefined && !middlewareToggle) {\n // return bypass()\n // }\n\n // embed timer\n req.apicacheTimer = new Date()\n\n // In Express 4.x the url is ambigious based on where a router is mounted. originalUrl will give the full Url\n var key = req.originalUrl || req.url\n\n // Remove querystring from key if jsonp option is enabled\n if (opt.jsonp) {\n key = url.parse(key).pathname\n }\n\n // add appendKey (either custom function or response path)\n if (typeof opt.appendKey === 'function') {\n key += '$$appendKey=' + opt.appendKey(req, res)\n } else if (opt.appendKey.length > 0) {\n var appendKey = req\n\n for (var i = 0; i < opt.appendKey.length; i++) {\n appendKey = appendKey[opt.appendKey[i]]\n }\n key += '$$appendKey=' + appendKey\n }\n\n // attempt cache hit\n var redis = opt.redisClient\n var cached = !redis ? memCache.getValue(key) : null\n\n // send if cache hit from memory-cache\n if (cached) {\n var elapsed = new Date() - req.apicacheTimer\n debug('sending cached (memory-cache) version of', key, logDuration(elapsed))\n\n perf.hit(key)\n return sendCachedResponse(req, res, cached, middlewareToggle, next, duration)\n }\n\n // send if cache hit from redis\n if (redis && redis.connected) {\n try {\n redis.hgetall(key, function (err, obj) {\n if (!err && obj && obj.response) {\n var elapsed = new Date() - req.apicacheTimer\n debug('sending cached (redis) version of', key, logDuration(elapsed))\n\n perf.hit(key)\n return sendCachedResponse(\n req,\n res,\n JSON.parse(obj.response),\n middlewareToggle,\n next,\n duration\n )\n } else {\n perf.miss(key)\n return makeResponseCacheable(\n req,\n res,\n next,\n key,\n duration,\n strDuration,\n middlewareToggle\n )\n }\n })\n } catch (err) {\n // bypass redis on error\n perf.miss(key)\n return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle)\n }\n } else {\n perf.miss(key)\n return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle)\n }\n }\n\n cache.options = options\n\n return cache\n }\n\n this.options = function (options) {\n if (options) {\n Object.assign(globalOptions, options)\n syncOptions()\n\n if ('defaultDuration' in options) {\n // Convert the default duration to a number in milliseconds (if needed)\n globalOptions.defaultDuration = parseDuration(globalOptions.defaultDuration, 3600000)\n }\n\n if (globalOptions.trackPerformance) {\n debug('WARNING: using trackPerformance flag can cause high memory usage!')\n }\n\n return this\n } else {\n return globalOptions\n }\n }\n\n this.resetIndex = function () {\n index = {\n all: [],\n groups: {},\n }\n }\n\n this.newInstance = function (config) {\n var instance = new ApiCache()\n\n if (config) {\n instance.options(config)\n }\n\n return instance\n }\n\n this.clone = function () {\n return this.newInstance(this.options())\n }\n\n // initialize index\n this.resetIndex()\n}\n\nexport default new ApiCache()\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package.json b/package.json index 8a129f7..44f978f 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "scripts": { "lint": "eslint src", "test:old": "nyc mocha $(find test -name '*_test.js') --recursive", + "pretest": "yarn build", "test": "nyc jest --verbose", "dev": "yarn test --watch", "test:coverage": "yarn test && yarn coverage", diff --git a/src/index.js b/src/index.js index d123cb7..aa07179 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import MemoryCache from './memory-cache' import pkg from '../package.json' +import { setLongTimeout } from './utils/setLongTimeout' var t = { ms: 1, @@ -143,10 +144,10 @@ function ApiCache() { memCache.add(key, value, duration, expireCallback) } - // add automatic cache clearing from duration, includes max limit on setTimeout - timers[key] = setTimeout(function () { + // add automatic cache clearing from duration, includes max limit on setLongTimeout + timers[key] = setLongTimeout(function () { instance.clear(key, true) - }, Math.min(duration, 2147483647)) + }, duration) } function accumulateContent(res, content) { diff --git a/src/memory-cache.js b/src/memory-cache.js index 82d3aca..aff8dfa 100644 --- a/src/memory-cache.js +++ b/src/memory-cache.js @@ -1,16 +1,18 @@ +import { setLongTimeout } from './utils/setLongTimeout' + function MemoryCache() { this.cache = {} this.size = 0 } -MemoryCache.prototype.add = function(key, value, time, timeoutCallback) { +MemoryCache.prototype.add = function (key, value, time, timeoutCallback) { var old = this.cache[key] var instance = this var entry = { value: value, expire: time + Date.now(), - timeout: setTimeout(function() { + timeout: setLongTimeout(function () { instance.delete(key) return timeoutCallback && typeof timeoutCallback === 'function' && timeoutCallback(value, key) }, time), @@ -22,7 +24,7 @@ MemoryCache.prototype.add = function(key, value, time, timeoutCallback) { return entry } -MemoryCache.prototype.delete = function(key) { +MemoryCache.prototype.delete = function (key) { var entry = this.cache[key] if (entry) { @@ -36,20 +38,20 @@ MemoryCache.prototype.delete = function(key) { return null } -MemoryCache.prototype.get = function(key) { +MemoryCache.prototype.get = function (key) { var entry = this.cache[key] return entry } -MemoryCache.prototype.getValue = function(key) { +MemoryCache.prototype.getValue = function (key) { var entry = this.get(key) return entry && entry.value } -MemoryCache.prototype.clear = function() { - Object.keys(this.cache).forEach(function(key) { +MemoryCache.prototype.clear = function () { + Object.keys(this.cache).forEach(function (key) { this.delete(key) }, this) diff --git a/src/utils/setLongTimeout.js b/src/utils/setLongTimeout.js new file mode 100644 index 0000000..58f562f --- /dev/null +++ b/src/utils/setLongTimeout.js @@ -0,0 +1,14 @@ +export function setLongTimeout(fn, delay) { + var maxDelay = Math.pow(2, 31) - 1 + + if (delay > maxDelay) { + var args = arguments + args[1] -= maxDelay + + return setTimeout(function () { + setTimeout_.apply(undefined, args) + }, maxDelay) + } + + return setTimeout.apply(undefined, arguments) +}