New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

catbox

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

catbox - npm Package Compare versions

Comparing version 0.0.2 to 0.1.0

examples/mongo.js

17

lib/index.js

@@ -6,5 +6,4 @@ // Load modules

var Stale = require('./stale');
var Redis = require('./redis');
var Mongo = require('./mongo');
var Memory = require('./memory');
// Mongo and Redis are loaded below depending on the configuration

@@ -41,6 +40,6 @@

if (engine === 'redis') {
factory = Redis;
factory = require('./redis');
}
else if (engine === 'mongodb') {
factory = Mongo;
factory = require('./mongo');
}

@@ -270,2 +269,3 @@ else if (engine === 'memory') {

* mode: 'server+client',
* privacy: 'public',
* expiresIn: 30000,

@@ -292,2 +292,4 @@ * expiresAt: '13:00',

Hoek.assert(['none', 'client', 'server'].indexOf(mode) !== -1, 'Unknown cache mode: ' + mode);
if (mode !== 'none') {

@@ -299,3 +301,3 @@ rule.mode[mode] = true;

if (Object.keys(rule.mode).length === 0) {
Hoek.assert(!config.expiresIn && !config.expiresAt && !config.staleIn && !config.staleTimeout, 'Cannot configure cache rules when mode is none');
Hoek.assert(!Hoek.matchKeys(config, ['expiresIn','expiresAt','staleIn','staleTimeout','privacy','segment']).length, 'Cannot configure cache rules when mode is none');
return rule;

@@ -312,2 +314,3 @@ }

Hoek.assert(!config.staleTimeout || !config.expiresIn || config.staleTimeout < (config.expiresIn - config.staleIn), 'staleTimeout must be less than the delta between expiresIn and staleIn');
Hoek.assert(!config.privacy || ['default', 'public', 'private'].indexOf(config.privacy) !== -1, 'Unknown privacy: ' + config.privacy);

@@ -347,2 +350,6 @@ // Strict mode

// Privacy
rule.privacy = config.privacy || 'default';
return rule;

@@ -349,0 +356,0 @@ };

@@ -110,2 +110,3 @@ // Load modules

envelope.byteSize = internals.itemByteSize(value);
envelope.byteSize += internals.itemByteSize(key);

@@ -186,5 +187,5 @@ if (self.byteSize + envelope.byteSize > this.settings.maxByteSize) {

var size = 8; // Initial object overhead
size += keys.length * 2;
for (var i = 0, il = keys.length; i < il; ++i) {
size += internals.itemByteSize(keys[i]);
size += internals.itemByteSize(object[keys[i]]);

@@ -191,0 +192,0 @@ }

{
"name": "catbox",
"description": "Multi-strategy object caching service",
"version": "0.0.2",
"version": "0.1.0",
"author": "Eran Hammer <eran@hueniverse.com> (http://hueniverse.com)",

@@ -22,10 +22,9 @@ "contributors":[

"dependencies": {
"hoek": "0.0.x",
"redis": "0.8.x",
"mongodb": "1.1.x"
"hoek": "0.1.x"
},
"devDependencies": {
"redis": "0.8.x",
"mongodb": "1.1.x",
"mocha": "1.x.x",
"chai": "1.2.x",
"hapi": "0.x.x"
"chai": "1.2.x"
},

@@ -41,2 +40,2 @@ "scripts": {

]
}
}

@@ -8,1 +8,86 @@ <a href="/walmartlabs/blammo"><img src="https://raw.github.com/walmartlabs/blammo/master/images/from.png" align="right" /></a>

The provided implementation includes support for Redis, MongoDB, and an experimental memory store (each must be manually installed and configured). _'Catbox'_ is useful for conveniently managing item cache rules and storage.
### Installing the appropriate module dependency
The _'mongodb'_ and _'redis'_ modules are currently used only in a development environment. Therefore, to use _'Catbox'_ in production you will need to manually install the _'mongodb'_ or _'redis'_ modules. One way that these modules can be installed is by running the command `npm install mongodb` or `npm install redis`. Another way to install the modules is to add the appropriate one to the applications _'package.json'_ `dependencies` section and then by running `npm install`.
### Client
Catbox has a _'Client'_ constructor that takes the following options.
* `engine` - the cache server implementation. Options are redis, mongodb, and memory. (required)
* `partition` - the partition name used to isolate the cached results across different servers. (required)
##### Mongo Specific
* `host` - the cache server hostname. Defaults to _'127.0.0.1'_.
* `port` - the cache server port. Defaults to _'27017'_.
* `username` - when the mongo server requires authentication. Defaults to no authentication.
* `password` - used for authentication.
* `poolSize` - number of connections to leave open that can be used for catbox. Defaults to _'5'_.
##### Redis Specific
* `host` - the cache server hostname. Defaults to _'127.0.0.1'_.
* `port` - the cache server port. Defaults to _'6479'_.
##### Memory Specific
This is an experimental engine and should be avoided in production environments.
* `maxByteSize` - Sets an upper limit on the number of bytes that can be consumed by the total of everything cached in the memory engine. Once this limit is reached no more items will be added to the cache. Defaults to no limit.
#### Client Interface
After constructing a cache client the following methods are available. After each method description is the method signature. Please note that _'start'_ should be called before calling any of these methods.
* `start` - creates a connection to the cache server. (`function (callback)`)
* `stop` - terminates the connection to the cache server. (`function ()`)
* `get` - retrieve an item from the cache engine if its stored. (`function (key, callback)`)
* `set` - store an item in the cache at the given key for a specified length of time. (`function (key, value, ttl, callback)`)
* `drop` - remove the item from cache found at the given key. (`function (key, callback)`)
_'key'_ is an object with the following properties:
* `segment` - the parent category to store the item under
* `id` - should be unique across the segment, used to identify the stored item
### Policy
Instead of dealing directly with the client interface using the _'Policy'_ interface is often preferred. It provides several helper methods like _'getOrGenerate'_ that will handle retrieving an item from cache when available or generating a new item and storing it in cache. _'Policy'_ is also useful for creating cache rules for different items and having them enforced. To construct a new _'Policy'_ the constructor takes the following parameters:
* `config`
* `mode` - determines if the item is cached on the server, client, or both. (required)
* `server+client` - Caches the item on the server and client
* `client` - Won't store the item on the server
* `server` - Caches the item on the server only
* `none` - Disable cache for the item on both the client and server
* `segment` - Required segment name, used to isolate cached items within the cache partition. (required)
* `expiresIn` - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used together with `expiresAt`.
* `expiresAt` - time of day expressed in 24h notation using the 'MM:HH' format, at which point all cache records for the route expire. Cannot be used together with `expiresIn`.
* `staleIn` - number of milliseconds to mark an item stored in cache as stale and reload it. Must be less than _'expiresIn'_.
* `staleTimeout` - number of milliseconds to wait before checking if an item is stale
* `privacy` - optional cache control override for setting _'public'_ or _'private'_ mode. Defaults to _'default'_ (HTTP protocol cache-control defaults).
* `cache` - a cache client that has been started
#### Policy Interface
After a _'Policy'_ is constructed the following methods are available.
* `isMode` - determines if the policy supports the given mode. (`function (mode)`)
* `isEnabled` - determines if the policy has a mode enabled. (`function ()`)
* `get` - retrieve an item from the cache engine if its stored. (`function (key, callback)`)
* `set` - store an item in the cache at the given key for a specified length of time. (`function (key, value, ttl, callback)`)
* `drop` - remove the item from cache found at the given key. (`function (key, callback)`)
* `ttl` - get the number of milliseconds that an item has left before it is expired from a given time. (`function (created)`)
* `getOrGenerate` - get and item from cache if it exists, or generate it and store it in cache. (`function (key, logFunc, generateFunc, callback)`)
As a result of the _'Policy'_ constructor taking the segment, the key used should just be the item ID instead of the object used in the cache _'Client'_ previously used.
### Examples
For examples of creating a server that uses one of the above engines look in the _'examples'_ folder.

@@ -5,5 +5,3 @@ // Load modules

var Net = require('net');
var NodeUtil = require('util');
var Events = require('events');
var Hapi = require('hapi');
var Server = require('./server');
var Catbox = require(libPath);

@@ -22,3 +20,2 @@ var Defaults = require(libPath + 'defaults');

module.exports = Hapi;
module.exports.Catbox = Catbox;

@@ -32,10 +29,5 @@ module.exports.Catbox.Defaults = Defaults;

module.exports.Server = function (host, port, settings) {
module.exports.Server = function (settings) {
var server = new Hapi.server(host, port, settings);
if (settings.cache) {
server.cache = new Catbox.Client(settings.cache);
}
return server;
return new Server(settings);
};

@@ -89,21 +81,2 @@

});
};
internals.Logger = function () {
Events.EventEmitter.call(this);
return this;
};
NodeUtil.inherits(internals.Logger, Events.EventEmitter);
module.exports._TEST = internals.logger = new internals.Logger();
// Override Log's console method
Hapi.log.console = function (message) {
internals.logger.emit('log', message);
};

@@ -21,67 +21,29 @@ // Load modules

var _server = null;
var _serverUrl = 'http://127.0.0.1:17785';
var profileHandler = function (request) {
var activeItemGenerator = function () {
request.reply({
'id': 'fa0dbda9b1b',
'name': 'John Doe'
});
};
var activeItemHandler = function (request) {
request.reply({
return {
'id': '55cf687663',
'name': 'Active Item'
});
};
};
var cacheItemHandler = function (request) {
var badGenerator = function () {
var cacheable = new Helpers.Response.Text('hello');
cacheable._code = 200;
request.reply(cacheable);
return new Stream();
};
var badHandler = function (request) {
var errorGenerator = function () {
request.reply(new Stream());
return new Error('myerror');
};
var errorHandler = function (request) {
var error = new Error('myerror');
error.code = 500;
request.reply(error);
};
var notCacheableHandler = function (request) {
var response = new Helpers.Response.Direct(request)
.type('text/plain')
.bytes(13)
.ttl(1000)
.write('!hola ')
.write('amigos!');
request.reply(response);
};
function setupServer(done) {
_server = new Helpers.Server('0.0.0.0', 17785, { cache: { engine: 'memory' } });
_server = Helpers.Server({ engine: 'memory' });
_server.addRoutes([
{ method: 'GET', path: '/profile', config: { handler: profileHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/item', config: { handler: activeItemHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/item2', config: { handler: activeItemHandler, cache: { mode: 'none' } } },
{ method: 'GET', path: '/item3', config: { handler: activeItemHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/bad', config: { handler: badHandler, cache: { expiresIn: 120000 } } },
{ method: 'GET', path: '/cache', config: { handler: cacheItemHandler, cache: { expiresIn: 120000, strict: true } } },
{ method: 'GET', path: '/error', config: { handler: errorHandler, cache: { expiresIn: 120000, strict: true } } },
{ method: 'GET', path: '/notcacheablenostrict', config: { handler: notCacheableHandler, cache: { expiresIn: 120000, strict: false } } }
]);
_server.addRoute('/item', activeItemGenerator, { mode: 'server', expiresIn: 120000, segment: '/item' });
_server.addRoute('/error', errorGenerator, { mode: 'server', expiresIn: 120000, strict: true, segment: '/error' });
_server.addRoute('/empty', badGenerator, { mode: 'server', expiresIn: 120000, segment: '/empty' });
_server.addRoute('/expired', activeItemGenerator, { mode: 'server', expiresIn: 10, segment: '/expired' });

@@ -91,77 +53,10 @@ done();

var makeRequest = function (path, callback) {
var next = function (res) {
return callback(res);
};
_server.inject({
method: 'get',
url: _serverUrl + path
}, next);
};
var parseHeaders = function (res) {
var headersObj = {};
var headers = res._header.split('\r\n');
for (var i = 0, il = headers.length; i < il; i++) {
var header = headers[i].split(':');
var headerValue = header[1] ? header[1].trim() : '';
headersObj[header[0]] = headerValue;
}
return headersObj;
};
before(setupServer);
it('returns max-age value when route uses default cache rules', function (done) {
makeRequest('/profile', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.equal('max-age=120, must-revalidate');
done();
});
});
it('returns max-age value when route uses client cache mode', function (done) {
makeRequest('/profile', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.equal('max-age=120, must-revalidate');
done();
});
});
it('doesn\'t return max-age value when route is not cached', function (done) {
makeRequest('/item2', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.not.equal('max-age=120, must-revalidate');
done();
});
});
it('throws error when returning a stream in a cached endpoint handler', function (done) {
function test() {
makeRequest('/bad', function (rawRes) { });
}
expect(test).to.throw(Error);
done();
});
it('doesn\'t cache error responses', function (done) {
makeRequest('/error', function () {
_server.getResponse('/error', function () {
_server.cache.get({ segment: '/error', id: '/error' }, function (err, cached) {
_server.client.get({ segment: '/error', id: '/error' }, function (err, cached) {

@@ -174,17 +69,9 @@ expect(cached).to.not.exist;

it('doesn\'t send cache headers for responses with status codes other than 200', function (done) {
makeRequest('/nocache', function (res) {
it('caches non-error responses', function (done) {
expect(res.headers['Cache-Control']).to.equal('no-cache');
done();
});
});
_server.getResponse('/item', function () {
it('caches responses with status codes of 200', function (done) {
_server.client.get({ segment: '/item', id: '/item' }, function (err, cached) {
makeRequest('/cache', function () {
_server.cache.get({ segment: '/cache', id: '/cache' }, function (err, cached) {
expect(cached).to.exist;

@@ -196,7 +83,20 @@ done();

it('doesn\'t throw an error when requesting a non-strict route that is not cacheable', function (done) {
it('handles situation where item from cache is expired', function (done) {
makeRequest('/notcacheablenostrict', function (res) {
var get = _server.client.connection.get;
_server.client.connection.get = function (options, callback) {
expect(res.statusCode).to.equal(200);
var now = Date.now();
callback(null, {
item: 'myValue',
stored: now - 20,
ttl: 1
});
_server.client.connection.get = get;
};
_server.getResponse('/expired', function (result) {
expect(result.id).to.equal(activeItemGenerator().id);
done();

@@ -206,18 +106,10 @@ });

it('throws an error when requesting a strict cached route that is not cacheable', function (done) {
it('doesn\'t throw an error caching empty streams', function (done) {
var server = new Helpers.Server('0.0.0.0', 18885, { cache: { engine: 'memory' } });
server.addRoute({ method: 'GET', path: '/notcacheable', config: { handler: notCacheableHandler, cache: { expiresIn: 120000, strict: true } } });
_server.getResponse('/empty', function (result) {
var fn = function () {
server.inject({
method: 'get',
url: 'http://127.0.0.1:18885/notcacheable'
});
};
expect(fn).to.throw(Error, 'Attempted to cache non-cacheable item');
done();
expect(result).to.not.be.instanceOf(Error);
done();
});
});
});

@@ -27,152 +27,47 @@ // Load modules

var _server = null;
var _serverUrl = 'http://127.0.0.1:17786';
var profileHandler = function (request) {
var activeItemGenerator = function () {
request.reply({
'id': 'fa0dbda9b1b',
'name': 'John Doe'
});
};
var activeItemHandler = function (request) {
request.reply({
return {
'id': '55cf687663',
'name': 'Active Item'
});
};
};
var cacheItemHandler = function (request) {
var badGenerator = function () {
var cacheable = new Helpers.Response.Text('hello');
cacheable._code = 200;
request.reply(cacheable);
return new Stream();
};
var badHandler = function (request) {
var errorGenerator = function () {
request.reply(new Stream());
return new Error('myerror');
};
var errorHandler = function (request) {
var error = new Error('myerror');
error.code = 500;
request.reply(error);
};
var notCacheableHandler = function (request) {
var response = new Helpers.Response.Direct(request)
.type('text/plain')
.bytes(13)
.ttl(1000)
.write('!hola ')
.write('amigos!');
request.reply(response);
};
function setupServer(done) {
_server = new Helpers.Server('0.0.0.0', 17786, { cache: { engine: 'mongodb', partition: 'catbox-test' } });
_server = Helpers.Server({ engine: 'mongodb', partition: 'catbox-test' });
_server.addRoutes([
{ method: 'GET', path: '/profile', config: { handler: profileHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/item', config: { handler: activeItemHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/item2', config: { handler: activeItemHandler, cache: { mode: 'none' } } },
{ method: 'GET', path: '/item3', config: { handler: activeItemHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/bad', config: { handler: badHandler, cache: { expiresIn: 120000 } } },
{ method: 'GET', path: '/cache', config: { handler: cacheItemHandler, cache: { expiresIn: 120000, strict: true } } },
{ method: 'GET', path: '/error', config: { handler: errorHandler, cache: { expiresIn: 120000, strict: true } } },
{ method: 'GET', path: '/notcacheablenostrict', config: { handler: notCacheableHandler, cache: { expiresIn: 120000, strict: false } } }
]);
_server.addRoute('/item', activeItemGenerator, { mode: 'server', expiresIn: 120000, segment: '/item' });
_server.addRoute('/error', errorGenerator, { mode: 'server', expiresIn: 120000, strict: true, segment: '/error' });
_server.addRoute('/empty', badGenerator, { mode: 'server', expiresIn: 120000, segment: '/empty' });
done();
_server.client.start(done);
}
var makeRequest = function (path, callback) {
var next = function (res) {
return callback(res);
};
_server.inject({
method: 'get',
url: _serverUrl + path
}, next);
};
var parseHeaders = function (res) {
var headersObj = {};
var headers = res._header.split('\r\n');
for (var i = 0, il = headers.length; i < il; i++) {
var header = headers[i].split(':');
var headerValue = header[1] ? header[1].trim() : '';
headersObj[header[0]] = headerValue;
}
return headersObj;
};
before(setupServer);
it('returns max-age value when route uses default cache rules', function (done) {
it('doesn\'t throw an error when calling start when connection already started', function (done) {
makeRequest('/profile', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.equal('max-age=120, must-revalidate');
done();
});
_server.client.start(done);
});
it('returns max-age value when route uses client cache mode', function (done) {
makeRequest('/profile', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.equal('max-age=120, must-revalidate');
done();
});
});
it('doesn\'t return max-age value when route is not cached', function (done) {
makeRequest('/item2', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.not.equal('max-age=120, must-revalidate');
done();
});
});
it('throws error when returning a stream in a cached endpoint handler', function (done) {
function test() {
makeRequest('/bad', function (rawRes) { });
}
expect(test).to.throw(Error);
done();
});
it('doesn\'t cache error responses', function (done) {
makeRequest('/error', function () {
_server.getResponse('/error', function () {
_server.cache.start(function() {
_server.client.get({ segment: '/error', id: '/error' }, function (err, cached) {
_server.cache.get({ segment: '/error', id: '/error' }, function (err, cached) {
expect(cached).to.not.exist;
done();
});
expect(cached).to.not.exist;
done();
});

@@ -182,22 +77,11 @@ });

it('doesn\'t send cache headers for responses with status codes other than 200', function (done) {
makeRequest('/nocache', function (res) {
it('caches non-error responses', function (done) {
expect(res.headers['Cache-Control']).to.equal('no-cache');
done();
});
});
_server.getResponse('/item', function () {
it('caches responses with status codes of 200', function (done) {
_server.client.get({ segment: '/item', id: '/item' }, function (err, cached) {
makeRequest('/cache', function () {
_server.cache.start(function() {
_server.cache.get({ segment: '/cache', id: '/cache' }, function (err, cached) {
expect(cached).to.exist;
done();
});
expect(cached).to.exist;
done();
});

@@ -207,28 +91,11 @@ });

it('doesn\'t throw an error when requesting a non-strict route that is not cacheable', function (done) {
it('doesn\'t throw an error caching empty streams', function (done) {
makeRequest('/notcacheablenostrict', function (res) {
_server.getResponse('/empty', function (result) {
expect(res.statusCode).to.equal(200);
expect(result).to.not.be.instanceOf(Error);
done();
});
});
it('throws an error when requesting a strict cached route that is not cacheable', function (done) {
var server = new Helpers.Server('0.0.0.0', 18885, { cache: { engine: 'memory' } });
server.addRoute({ method: 'GET', path: '/notcacheable', config: { handler: notCacheableHandler, cache: { expiresIn: 120000, strict: true } } });
var fn = function () {
server.inject({
method: 'get',
url: 'http://127.0.0.1:18885/notcacheable'
});
};
expect(fn).to.throw(Error, 'Attempted to cache non-cacheable item');
done();
});
});
});

@@ -27,141 +27,42 @@ // Load modules

var _server = null;
var _serverUrl = 'http://127.0.0.1:17787';
var profileHandler = function (request) {
var activeItemGenerator = function () {
request.reply({
'id': 'fa0dbda9b1b',
'name': 'John Doe'
});
};
var activeItemHandler = function (request) {
request.reply({
return {
'id': '55cf687663',
'name': 'Active Item'
});
};
};
var cacheItemHandler = function (request) {
var badGenerator = function () {
var cacheable = new Helpers.Response.Text('hello');
cacheable._code = 200;
request.reply(cacheable);
return new Stream();
};
var badHandler = function (request) {
var errorGenerator = function () {
request.reply(new Stream());
return new Error('myerror');
};
var errorHandler = function (request) {
var error = new Error('myerror');
error.code = 500;
request.reply(error);
};
var notCacheableHandler = function (request) {
var response = new Helpers.Response.Direct(request)
.type('text/plain')
.bytes(13)
.ttl(1000)
.write('!hola ')
.write('amigos!');
request.reply(response);
};
function setupServer(done) {
_server = new Helpers.Server('0.0.0.0', 17787, { cache: { engine: 'redis', partition: 'catbox-test' } });
_server = Helpers.Server({ engine: 'redis', partition: 'catbox-test' });
_server.addRoutes([
{ method: 'GET', path: '/profile', config: { handler: profileHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/item', config: { handler: activeItemHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/item2', config: { handler: activeItemHandler, cache: { mode: 'none' } } },
{ method: 'GET', path: '/item3', config: { handler: activeItemHandler, cache: { mode: 'client', expiresIn: 120000 } } },
{ method: 'GET', path: '/bad', config: { handler: badHandler, cache: { expiresIn: 120000 } } },
{ method: 'GET', path: '/cache', config: { handler: cacheItemHandler, cache: { expiresIn: 120000, strict: true } } },
{ method: 'GET', path: '/error', config: { handler: errorHandler, cache: { expiresIn: 120000, strict: true } } },
{ method: 'GET', path: '/notcacheablenostrict', config: { handler: notCacheableHandler, cache: { expiresIn: 120000, strict: false } } }
]);
_server.addRoute('/item', activeItemGenerator, { mode: 'server', expiresIn: 120000, segment: '/item' });
_server.addRoute('/error', errorGenerator, { mode: 'server', expiresIn: 120000, strict: true, segment: '/error' });
_server.addRoute('/empty', badGenerator, { mode: 'server', expiresIn: 120000, segment: '/empty' });
done();
_server.client.start(done);
}
var makeRequest = function (path, callback) {
var next = function (res) {
return callback(res);
};
_server.inject({
method: 'get',
url: _serverUrl + path
}, next);
};
var parseHeaders = function (res) {
var headersObj = {};
var headers = res._header.split('\r\n');
for (var i = 0, il = headers.length; i < il; i++) {
var header = headers[i].split(':');
var headerValue = header[1] ? header[1].trim() : '';
headersObj[header[0]] = headerValue;
}
return headersObj;
};
before(setupServer);
it('returns max-age value when route uses default cache rules', function (done) {
makeRequest('/profile', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.equal('max-age=120, must-revalidate');
done();
});
});
it('returns max-age value when route uses client cache mode', function (done) {
makeRequest('/profile', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.equal('max-age=120, must-revalidate');
done();
});
});
it('doesn\'t return max-age value when route is not cached', function (done) {
makeRequest('/item2', function (rawRes) {
var headers = parseHeaders(rawRes.raw.res);
expect(headers['Cache-Control']).to.not.equal('max-age=120, must-revalidate');
done();
});
});
it('doesn\'t cache error responses', function (done) {
makeRequest('/error', function () {
_server.getResponse('/error', function () {
_server.cache.start(function() {
_server.client.get({ segment: '/error', id: '/error' }, function (err, cached) {
_server.cache.get({ segment: '/error', id: '/error' }, function (err, cached) {
expect(cached).to.not.exist;
done();
});
expect(cached).to.not.exist;
done();
});

@@ -171,22 +72,11 @@ });

it('doesn\'t send cache headers for responses with status codes other than 200', function (done) {
makeRequest('/nocache', function (res) {
it('caches non-error responses', function (done) {
expect(res.headers['Cache-Control']).to.equal('no-cache');
done();
});
});
_server.getResponse('/item', function () {
it('caches responses with status codes of 200', function (done) {
_server.client.get({ segment: '/item', id: '/item' }, function (err, cached) {
makeRequest('/cache', function () {
_server.cache.start(function() {
_server.cache.get({ segment: '/cache', id: '/cache' }, function (err, cached) {
expect(cached).to.exist;
done();
});
expect(cached).to.exist;
done();
});

@@ -196,28 +86,11 @@ });

it('doesn\'t throw an error when requesting a non-strict route that is not cacheable', function (done) {
it('doesn\'t throw an error caching empty streams', function (done) {
makeRequest('/notcacheablenostrict', function (res) {
_server.getResponse('/empty', function (result) {
expect(res.statusCode).to.equal(200);
expect(result).to.not.be.instanceOf(Error);
done();
});
});
it('throws an error when requesting a strict cached route that is not cacheable', function (done) {
var server = new Helpers.Server('0.0.0.0', 18885, { cache: { engine: 'memory' } });
server.addRoute({ method: 'GET', path: '/notcacheable', config: { handler: notCacheableHandler, cache: { expiresIn: 120000, strict: true } } });
var fn = function () {
server.inject({
method: 'get',
url: 'http://127.0.0.1:18885/notcacheable'
});
};
expect(fn).to.throw(Error, 'Attempted to cache non-cacheable item');
done();
});
});
});

@@ -22,7 +22,6 @@ // Load modules

var options = {
cache: {
expiresIn: 100,
staleIn: 20,
staleTimeout: 5
}
expiresIn: 100,
staleIn: 20,
staleTimeout: 5,
segment: 'user'
};

@@ -39,3 +38,3 @@

var server = new Helpers.Server('0.0.0.0', 8097, { cache: 'memory' });
var server = Helpers.Server({ engine: 'memory' });
server.addHelper('user', method, options);

@@ -68,7 +67,6 @@

var options = {
cache: {
expiresIn: 100,
staleIn: 20,
staleTimeout: 5
}
expiresIn: 100,
staleIn: 20,
staleTimeout: 5,
segment: 'user'
};

@@ -91,3 +89,3 @@

var server = new Helpers.Server('0.0.0.0', 8097, { cache: 'memory' });
var server = Helpers.Server({ engine: 'memory' });
server.addHelper('user', method, options);

@@ -125,7 +123,6 @@

var options = {
cache: {
expiresIn: 100,
staleIn: 20,
staleTimeout: 10
}
expiresIn: 100,
staleIn: 20,
staleTimeout: 10,
segment: 'user'
};

@@ -139,3 +136,3 @@

var server = new Helpers.Server('0.0.0.0', 8097, { cache: 'memory' });
var server = Helpers.Server({ engine: 'memory' });
server.addHelper('user', method, options);

@@ -168,6 +165,6 @@

var server = new Helpers.Server('0.0.0.0', 8097, { cache: 'memory' });
server.cache.stop();
var server = Helpers.Server({ engine: 'memory' });
server.client.stop();
var gen = 0;
server.addHelper('user', function (id, next) { return next({ id: id, gen: ++gen }); }, { cache: { expiresIn: 2000 } });
server.addHelper('user', function (id, next) { return next({ id: id, gen: ++gen }); }, { expiresIn: 2000, segment: 'user' });
var id = Math.random();

@@ -190,7 +187,6 @@ server.helpers.user(id, function (result1) {

var options = {
cache: {
expiresIn: 30,
staleIn: 20,
staleTimeout: 5
}
expiresIn: 30,
staleIn: 20,
staleTimeout: 5,
segment: 'user'
};

@@ -210,3 +206,3 @@

var server = new Helpers.Server('0.0.0.0', 8097, { cache: 'memory' });
var server = Helpers.Server({ engine: 'memory' });
server.addHelper('user', method, options);

@@ -213,0 +209,0 @@

@@ -159,3 +159,3 @@ // Load modules

var memory = new Memory.Connection({ maxByteSize: 6 });
var memory = new Memory.Connection({ maxByteSize: 30 });
expect(memory.cache).to.not.exist;

@@ -202,3 +202,3 @@

expect(memory.cache[key1.segment][key1.id].byteSize).to.equal(66);
expect(memory.cache[key1.segment][key1.id].byteSize).to.equal(102);
expect(memory.cache[key1.segment][key1.id].item.my).to.exist;

@@ -234,7 +234,7 @@ done();

expect(memory.cache[key1.segment][key1.id].byteSize).to.equal(68);
expect(memory.cache[key1.segment][key1.id].byteSize).to.equal(111);
expect(memory.cache[key1.segment][key1.id].item.my).to.exist;
memory.set(key1, itemToStore, 10, function () {
expect(memory.cache[key1.segment][key1.id].byteSize).to.equal(68);
expect(memory.cache[key1.segment][key1.id].byteSize).to.equal(111);
expect(memory.cache[key1.segment][key1.id].item.my).to.exist;

@@ -241,0 +241,0 @@ done();

@@ -310,3 +310,94 @@ // Load modules

});
it('stores fresh copy when generation takes longer than ttl to return value', function (done) {
var key = { id: 'test', segment: 'test' };
var cache = new Cache.Memory.Connection();
var isGetTtlCalled = false;
cache.rule = {
staleTimeout: 1
};
cache.isMode = function () {
return true;
};
cache.get = function (key, callback) {
callback(null, { item: 'testitem', isStale: true, ttl: 3 });
};
cache.set = function (key) {
expect(key.id).to.equal('test');
};
var generateFunc = function (callback) {
setTimeout(function () {
callback(null, { getTtl: function () {
isGetTtlCalled = true;
return 2;
}});
}, 10);
};
var logFunc = function (tags, data) {
};
cache.start(function () {
Cache.Stale.process(cache, key, logFunc, ['test'], generateFunc, function (result) {
expect(result).to.equal('testitem');
done();
});
});
});
it('drops cached item when generation takes longer than ttl and returns an error', function (done) {
var key = { id: 'test', segment: 'test' };
var cache = new Cache.Memory.Connection();
var isGetTtlCalled = false;
cache.rule = {
staleTimeout: 1
};
cache.isMode = function () {
return true;
};
cache.get = function (key, callback) {
callback(null, { item: 'testitem', isStale: true, ttl: 3 });
};
cache.drop = function (key, callback) {
expect(key.id).to.equal('test');
callback();
};
var generateFunc = function (callback) {
setTimeout(function () {
callback(new Error());
}, 10);
};
var logFunc = function (tags, data) {
};
cache.start(function () {
Cache.Stale.process(cache, key, logFunc, ['test'], generateFunc, function (result) {
expect(result).to.equal('testitem');
done();
});
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc