Skip to content

Commit

Permalink
added status code white list and black listing
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Whitley committed Oct 22, 2016
1 parent fa26af4 commit 850a42d
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 133 deletions.
60 changes: 50 additions & 10 deletions lib/apicache.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
var message = require('debug')('apicache');
var memCache = require('memory-cache');
var url = require('url');
var _ = require('lodash');
var MemoryCache = require('./memory-cache');

var t = {
ms: 1,
second: 1000,
minute: 60000,
hour: 3600000,
Expand All @@ -13,24 +14,48 @@ var t = {
year: 3600000 * 24 * 365,
};

var instances = [];

function ApiCache() {
var memCache = new MemoryCache;

var globalOptions = {
debug: false,
defaultDuration: 3600000,
enabled: true,
appendKey: [],
jsonp: false,
redisClient: false
redisClient: false,
statusCodes: {
include: [],
exclude: [],
}
};

var instance = this;

var index = null;

instances.push(this);
this.id = instances.length;

function debug(msg) {
return globalOptions.debug ? console.log('[apicache]: ' + msg) : message(msg)
}

function shouldCacheResponse(response) {
var opt = globalOptions
var codes = opt.statusCodes

// console.log('shouldCacheResponse', response)
if (!response) return false

if (codes.exclude && codes.exclude.length && codes.exclude.indexOf(response.status) !== -1) return false
if (codes.include && codes.include.length && codes.include.indexOf(response.status) === -1) return false
// console.log('passed!')

return true
}

this.clear = function(target) {
var group = index.groups[target];

Expand All @@ -41,7 +66,7 @@ function ApiCache() {
debug('clearing cached entry for "' + key + '"');

if (!globalOptions.redisClient) {
memCache.del(key);
memCache.delete(key);
} else {
globalOptions.redisClient.del(key);
}
Expand All @@ -53,7 +78,7 @@ function ApiCache() {
debug('clearing cached entry for "' + target + '"');

if (!globalOptions.redisClient) {
memCache.del(target);
memCache.delete(target);
} else {
globalOptions.redisClient.del(target);
}
Expand Down Expand Up @@ -87,6 +112,9 @@ function ApiCache() {
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);
}
Expand Down Expand Up @@ -150,7 +178,7 @@ function ApiCache() {

if (!globalOptions.redisClient) {

debug('returning memCached version of "' + key + '"');
debug('returning memory-cached version of "' + key + '"');

res.statusCode = cached.status;
res.set(cached.headers);
Expand Down Expand Up @@ -206,7 +234,7 @@ function ApiCache() {
responseObj.body = !_.isUndefined(b) ? b : (!_.isNumber(a) ? a : null);

// last bypass attempt
if (!memCache.get(key) && !req.headers['x-apicache-bypass']) {
if (shouldCacheResponse(responseObj) && !memCache.get(key) && !req.headers['x-apicache-bypass']) {
if (req.apicacheGroup) {
debug('group detected "' + req.apicacheGroup + '"');

Expand All @@ -226,7 +254,7 @@ function ApiCache() {
});

if (!globalOptions.redisClient) {
memCache.put(key, responseObj, duration);
memCache.add(key, responseObj, duration);
} else {
globalOptions.redisClient.hset(key, "responseObj", JSON.stringify(responseObj));
globalOptions.redisClient.hset(key, "duration", duration);
Expand Down Expand Up @@ -260,10 +288,22 @@ function ApiCache() {
};
};

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();

return this;
}

module.exports = new ApiCache();
61 changes: 61 additions & 0 deletions lib/memory-cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
function MemoryCache() {
this.cache = {}
this.size = 0
}

MemoryCache.prototype.add = function(key, value, time, timeoutCallback) {
var old = this.cache[key]
var instance = this

if (old) {
clearTimeout(old.timeout)
}

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]

if (entry && entry.expire < Date.now()) {
return this.delete(key)
}

return entry
}

MemoryCache.prototype.clear = function() {
Object.keys(this.cache).forEach(function(key) {
this.delete(key)
})

return true
}

module.exports = MemoryCache

0 comments on commit 850a42d

Please sign in to comment.