cache-manager-express-mw
Advanced tools
Comparing version 0.2.1 to 0.3.3
{ | ||
"name": "cache-manager-express-mw", | ||
"version": "0.2.1", | ||
"version": "0.3.3", | ||
"description": "Middleware for Express that uses cache-manager to add a caching layer in front of your application.", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"test": "grunt" | ||
}, | ||
"author": "Cimpress-MCP", | ||
"license": "MIT", | ||
"repository": { | ||
@@ -18,4 +16,2 @@ "type": "git", | ||
], | ||
"author": "Cimpress-MCP", | ||
"license": "MIT", | ||
"bugs": { | ||
@@ -25,18 +21,32 @@ "url": "https://github.com/Cimpress-MCP/cache-manager-express-mw/issues" | ||
"homepage": "https://github.com/Cimpress-MCP/cache-manager-express-mw#readme", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"test": "nyc --reporter=text --reporter=html --check-coverage --lines 100 --functions 90 --branches 90 mocha ./src/test/**/*.js --timeout=30000", | ||
"pretest": "jshint ./src && jscs ./src && depcheck ." | ||
}, | ||
"dependencies": { | ||
"bluebird": "^3.4.1", | ||
"lodash": "^4.15.0" | ||
"lodash.defaults": "^4.2.0", | ||
"lodash.endswith": "^4.2.1", | ||
"lodash.get": "^4.4.2", | ||
"lodash.isempty": "^4.4.0", | ||
"lodash.isnil": "^4.0.0", | ||
"lodash.isstring": "^4.0.1", | ||
"lodash.keys": "^4.2.0", | ||
"lodash.map": "^4.6.0", | ||
"lodash.omitby": "^4.6.0", | ||
"lodash.tointeger": "^4.0.4", | ||
"lodash.tolower": "^4.1.2", | ||
"lodash.trim": "^4.5.1" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"chai-spies": "^0.7.1", | ||
"grunt": "^1.0.1", | ||
"grunt-contrib-jshint": "^1.0.0", | ||
"grunt-jscs": "^3.0.1", | ||
"grunt-mocha-istanbul": "^5.0.2", | ||
"grunt-mocha-test": "^0.13.2", | ||
"mocha": "^3.0.2", | ||
"mocha-istanbul": "^0.3.0", | ||
"node-uuid": "^1.4.7" | ||
"chai": "^4.1.2", | ||
"chai-spies": "^1.0.0", | ||
"depcheck": "^0.6.9", | ||
"jscs": "^3.0.7", | ||
"jshint": "^2.9.5", | ||
"mocha": "^5.0.4", | ||
"nyc": "^11.6.0", | ||
"uuid": "^3.2.1" | ||
} | ||
} |
@@ -23,3 +23,3 @@ # cache-manager-express-mw | ||
var cacheManagerExpress = require("cache-manager-express-mw"); | ||
app.use(cacheManagerExpress(cache)); | ||
app.use(cacheManagerExpress({ cache })); | ||
``` | ||
@@ -29,3 +29,3 @@ | ||
```js | ||
app.get("/", cacheManagerExpress(cache), function(req, res) { | ||
app.get("/", cacheManagerExpress({ cache }), (req, res) => { | ||
// ... | ||
@@ -38,3 +38,3 @@ }); | ||
var cacheManagerExpress = require("cache-manager-express-mw"); | ||
app.use(cacheManagerExpress(cache, { prefix: "MyApp" })); | ||
app.use(cacheManagerExpress({ cache, options: { prefix: "MyApp" } })); | ||
``` | ||
@@ -49,4 +49,5 @@ | ||
| prefix | undefined | A prefix to append to the front of the generated cache key in case differentiation is needed. | | ||
| defaults | undefined | An object containing query string default values so that a missing query string value and the specified default resolve to the same cache key. For example, ```{ defaults: { val: "abc" } }``` will ensure that the routes ```/a/b/c``` and ```/a/b/c?val=abc``` resolve to the same cache key.| | ||
| callbacks | undefined | An object containing one or more callback functions (see [Callbacks](#callbacks) below). | ||
| defaults | undefined | An object containing query string default values so that a missing query string value and the specified default resolve to the same cache key. For example, ```{ defaults: { val: "abc" } }``` will ensure that the routes ```/a/b/c``` and ```/a/b/c?val=abc``` resolve to the same cache key. | | ||
| headers | undefined | A list of headers whose values should be included in the cache key. For example, { headers: [ "Authorization" ] } will include the value of the "Authorization" header in the cache key, so calls made with different Authorization headers won't result in cache hits, but calls with the same Authorization headers will. | | ||
| callbacks | undefined | An object containing one or more callback functions (see [Callbacks](#callbacks) below). | | ||
@@ -53,0 +54,0 @@ ## Callbacks |
@@ -5,26 +5,21 @@ { | ||
"description": "An sample app that shows how to use the cache-manager-express-mw npm package.", | ||
"author": "Cimpress-MCP", | ||
"license": "MIT", | ||
"main": "src/app.js", | ||
"scripts": { | ||
"start": "grunt develop", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"start": "node src/app.js", | ||
"test": "", | ||
"pretest": "jshint ./src && jscs ./src && depcheck ." | ||
}, | ||
"author": "Anthony Frasso", | ||
"license": "MIT", | ||
"dependencies": { | ||
"cache-manager": "^2.1.2", | ||
"cache-manager-express-mw": "file:..", | ||
"cache-manager-redis": "^0.2.4", | ||
"express": "^4.14.0" | ||
"express": "^4.14.0", | ||
"lodash.toupper": "^4.1.2" | ||
}, | ||
"devDependencies": { | ||
"grunt": "^1.0.1", | ||
"grunt-concurrent": "^2.3.1", | ||
"grunt-contrib-jshint": "^1.0.0", | ||
"grunt-jscs": "^3.0.1", | ||
"grunt-mocha-istanbul": "^5.0.2", | ||
"grunt-mocha-test": "^0.13.2", | ||
"grunt-node-inspector": "^0.4.2", | ||
"grunt-nodemon": "^0.4.2", | ||
"mocha": "^3.0.2" | ||
"depcheck": "^0.6.9", | ||
"jscs": "^3.0.7", | ||
"jshint": "^2.9.5" | ||
} | ||
} |
@@ -1,33 +0,22 @@ | ||
var _ = require("lodash"), | ||
cacheManager = require("cache-manager"), | ||
cacheManagerExpress = require("../../src/index.js"), | ||
express = require("express"), | ||
redisStore = require("cache-manager-redis"); | ||
const _toUpper = require("lodash.toupper"), | ||
cacheManager = require("cache-manager"), | ||
cacheManagerExpress = require("cache-manager-express-mw"), | ||
express = require("express"); | ||
var app = express(); | ||
var cacheOptions = { | ||
store: redisStore, | ||
retry_strategy: function() { // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers | ||
return; | ||
} | ||
const app = express(); | ||
const cacheOptions = { | ||
store: "memory", | ||
retry_strategy: () => {} // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers | ||
}; | ||
var cache = cacheManager.caching(cacheOptions); | ||
const cache = cacheManager.caching(cacheOptions); | ||
var callbacks = { | ||
onHit: function(key, value) { | ||
console.log(`Cache hit! key=${key}, value=${value.body}`); | ||
}, | ||
onMiss: function(key) { | ||
console.log(`Cache miss! key=${key}`); | ||
}, | ||
onError: function(err, key) { | ||
console.log(`Cache error! err=${err}, key=${key}`); | ||
}, | ||
onAttempt: function(key) { | ||
console.log(`Cache attempt! key=${key}`); | ||
} | ||
const callbacks = { | ||
onHit: (key, value) => console.log(`Cache hit! key=${key}, value=${value.body}`), | ||
onMiss: key => console.log(`Cache miss! key=${key}`), | ||
onError: (err, key) => console.log(`Cache error! err=${err}, key=${key}`), | ||
onAttempt: key => console.log(`Cache attempt! key=${key}`) | ||
}; | ||
var options = { defaults: { toUpper: false }, callbacks: callbacks }; | ||
const options = { defaults: { toUpper: false }, callbacks: callbacks }; | ||
app.get("/", cacheManagerExpress(cache, options), function(req, res) { | ||
app.get("/", cacheManagerExpress({ cache, options }), (req, res) => { | ||
res.set("cache-control", `private, max-age=300`); | ||
@@ -37,7 +26,7 @@ return res.send("Hello World!"); | ||
app.get("/echo", cacheManagerExpress(cache, options), function(req, res) { | ||
app.get("/echo", cacheManagerExpress({ cache, options }), (req, res) => { | ||
if (req.query.message) { | ||
var message = req.query.message; | ||
let message = req.query.message; | ||
if (req.query.toUpper) { | ||
message = _.toUpper(message); | ||
message = _toUpper(message); | ||
} | ||
@@ -50,4 +39,2 @@ res.set("cache-control", `private, max-age=300`); | ||
app.listen(3000, function() { | ||
console.log("Example app listening on port 3000!"); | ||
}); | ||
app.listen(3000, () => console.log("Example app listening on port 3000!")); |
@@ -1,8 +0,17 @@ | ||
var _ = require("lodash"); | ||
const _defaults = require("lodash.defaults"), | ||
_endsWith = require("lodash.endswith"), | ||
_isEmpty = require("lodash.isempty"), | ||
_isNil = require("lodash.isnil"), | ||
_isString = require("lodash.isstring"), | ||
_keys = require("lodash.keys"), | ||
_map = require("lodash.map"), | ||
_omitBy = require("lodash.omitby"), | ||
_toLower = require("lodash.tolower"), | ||
_trim = require("lodash.trim"); | ||
var getCacheKey = function(request, prefix, defaults) { | ||
var cachePrefix = prefix; | ||
const getCacheKey = ({ request, options: { prefix, headers, defaults } = {} }) => { | ||
let cachePrefix = prefix; | ||
if (cachePrefix) { | ||
cachePrefix = _.trim(cachePrefix); | ||
if (!_.isEmpty(cachePrefix) && !_.endsWith(cachePrefix, ":")) { | ||
cachePrefix = _trim(cachePrefix); | ||
if (!_isEmpty(cachePrefix) && !_endsWith(cachePrefix, ":")) { | ||
cachePrefix += ":"; | ||
@@ -14,15 +23,32 @@ } | ||
var sortedQueryString = ""; | ||
const headerInfix = getHeaderInfix(request, headers); | ||
let sortedQueryString = ""; | ||
if (request.query) { | ||
var query = _.omitBy(request.query, _.isNil); | ||
query = _.defaults(query, defaults); | ||
if (!_.isEmpty(query)) { | ||
sortedQueryString = "?" + _(query).keys().sortBy().map(key => `${key}=${query[key]}`).join("&"); | ||
let query = _omitBy(request.query, _isNil); | ||
query = _defaults(query, defaults); | ||
if (!_isEmpty(query)) { | ||
sortedQueryString = "?" + _map(_keys(query).sort(), key => `${key}=${query[key]}`).join("&"); | ||
} | ||
} | ||
var cacheKey = `${cachePrefix}${request.method}:${request.path}${sortedQueryString}`; | ||
const cacheKey = `${cachePrefix}${request.method}${headerInfix}:${request.path}${sortedQueryString}`; | ||
return cacheKey; | ||
}; | ||
const getHeaderInfix = (request, headers) => { | ||
if (!headers) { | ||
return ""; | ||
} | ||
if (_isString(headers)) { | ||
headers = [ headers ]; | ||
} | ||
let headerInfix = | ||
_map(_map(headers.sort(), header => _toLower(header)), header => `${header}:${request.get(header)}`).join(":"); | ||
return `:${headerInfix}`; | ||
}; | ||
module.exports = getCacheKey; |
@@ -1,9 +0,11 @@ | ||
var _ = require("lodash"); | ||
const _toInteger = require("lodash.tointeger"), | ||
_toLower = require("lodash.tolower"), | ||
_trim = require("lodash.trim"); | ||
var getCachingStrategy = function(res) { | ||
var cacheControlHeader = res.get("cache-control"); | ||
const getCachingStrategy = ({ response }) => { | ||
const cacheControlHeader = response.get("cache-control"); | ||
if (!cacheControlHeader) { | ||
return; | ||
} | ||
var match = cacheControlHeader.match(/((.*),\s+?)?max-age=(\d+).*/); | ||
const match = cacheControlHeader.match(/((.*),\s+?)?max-age=(\d+).*/); | ||
if (!match || match.length !== 4) { | ||
@@ -13,5 +15,5 @@ return; | ||
var result = { maxAge: _.toInteger(match[3]) }; | ||
const result = { maxAge: _toInteger(match[3]) }; | ||
var accessibility = _.toLower(_.trim(match[2])); | ||
const accessibility = _toLower(_trim(match[2])); | ||
if (accessibility === "public" || accessibility === "private") { | ||
@@ -18,0 +20,0 @@ result.accessibility = accessibility; |
@@ -1,16 +0,14 @@ | ||
var _ = require("lodash"), | ||
getCacheKey = require("./helpers/getcachekey.js"), | ||
getCachingStrategy = require("./helpers/getcachingstrategy.js"), | ||
Promise = require("bluebird"); | ||
const _get = require("lodash.get"), | ||
getCacheKey = require("./helpers/getcachekey.js"), | ||
getCachingStrategy = require("./helpers/getcachingstrategy.js"), | ||
P = require("bluebird"); | ||
var caching = function(cache, options) { | ||
var isProduction = function() { | ||
return process.env.NODE_ENV === "production"; | ||
}; | ||
const caching = ({ cache, options }) => { | ||
const isProduction = () => process.env.NODE_ENV === "production"; | ||
var getValue = function(key) { | ||
if (_.get(options, "callbacks.onAttempt")) { | ||
const getValue = key => { | ||
if (_get(options, "callbacks.onAttempt")) { | ||
options.callbacks.onAttempt(key); | ||
} | ||
var cacheGet = Promise.promisify(cache.get); | ||
const cacheGet = P.promisify(cache.get); | ||
return cacheGet(key) | ||
@@ -21,3 +19,3 @@ .catch(err => { | ||
} | ||
if (_.get(options, "callbacks.onError")) { | ||
if (_get(options, "callbacks.onError")) { | ||
options.callbacks.onError(err, key); | ||
@@ -28,7 +26,7 @@ } | ||
var getTtl = function(key) { | ||
const getTtl = key => { | ||
if (typeof cache.ttl !== "function") { | ||
return Promise.resolve(); | ||
return P.resolve(); | ||
} | ||
var cacheTtl = Promise.promisify(cache.ttl); | ||
const cacheTtl = P.promisify(cache.ttl); | ||
return cacheTtl(key) | ||
@@ -39,3 +37,3 @@ .catch(err => { | ||
} | ||
if (_.get(options, "callbacks.onError")) { | ||
if (_get(options, "callbacks.onError")) { | ||
options.callbacks.onError(err, key); | ||
@@ -46,3 +44,3 @@ } | ||
var setCacheControlHeader = function(res, accessibility, ttl) { | ||
const setCacheControlHeader = (res, accessibility, ttl) => { | ||
if (ttl) { | ||
@@ -57,8 +55,8 @@ if (accessibility) { | ||
var handleCacheHit = function(res, key, value) { | ||
const handleCacheHit = (res, key, value) => { | ||
if (!value) { | ||
return Promise.resolve(false); | ||
return P.resolve(false); | ||
} | ||
if (_.get(options, "callbacks.onHit")) { | ||
if (_get(options, "callbacks.onHit")) { | ||
options.callbacks.onHit(key, value); | ||
@@ -72,3 +70,3 @@ } | ||
try { | ||
var obj = JSON.parse(value.body); | ||
const obj = JSON.parse(value.body); | ||
res.status(value.statusCode).json(obj); | ||
@@ -82,16 +80,16 @@ } catch (err) { | ||
var handleCacheMiss = function(res, key) { | ||
if (_.get(options, "callbacks.onMiss")) { | ||
const handleCacheMiss = (res, key) => { | ||
if (_get(options, "callbacks.onMiss")) { | ||
options.callbacks.onMiss(key); | ||
} | ||
var send = res.send.bind(res); | ||
const send = res.send.bind(res); | ||
res.send = function(body) { | ||
var ret = send(body); | ||
res.send = body => { | ||
const ret = send(body); | ||
if (/^2/.test(res.statusCode)) { | ||
var cachingStrategy = getCachingStrategy(res); | ||
if (/^2/.test(res.statusCode) || /^304$/.test(res.statusCode)) { | ||
const cachingStrategy = getCachingStrategy({ response: res }); | ||
if (cachingStrategy) { | ||
var cacheSet = Promise.promisify(cache.set); | ||
var cacheValue = { | ||
const cacheSet = P.promisify(cache.set); | ||
const cacheValue = { | ||
statusCode: res.statusCode, | ||
@@ -106,3 +104,3 @@ body: body, | ||
} | ||
if (_.get(options, "callbacks.onError")) { | ||
if (_get(options, "callbacks.onError")) { | ||
options.callbacks.onError(err, key); | ||
@@ -118,3 +116,3 @@ } | ||
var middleware = function(req, res, next) { | ||
const middleware = (req, res, next) => { | ||
if (!cache) { | ||
@@ -125,3 +123,3 @@ next(); | ||
var key = getCacheKey(req, _.get(options, "prefix"), _.get(options, "defaults")); | ||
const key = getCacheKey({ request: req, options }); | ||
getValue(key) | ||
@@ -128,0 +126,0 @@ .then(value => handleCacheHit(res, key, value)) |
@@ -1,32 +0,28 @@ | ||
var _ = require("lodash"), | ||
assert = require("chai").assert, | ||
chai = require("chai"), | ||
cacheManagerExpress = require("../index.js"), | ||
expect = require("chai").expect, | ||
Promise = require("bluebird"), | ||
spies = require("chai-spies"), | ||
uuid = require("node-uuid"); | ||
const _isNil = require("lodash.isnil"), | ||
assert = require("chai").assert, | ||
chai = require("chai"), | ||
cacheManagerExpress = require("../index.js"), | ||
expect = require("chai").expect, | ||
P = require("bluebird"), | ||
spies = require("chai-spies"), | ||
uuid = require("uuid/v4"); | ||
chai.use(spies); | ||
describe("CacheManagerExpress", function() { | ||
var context; | ||
describe("CacheManagerExpress", () => { | ||
let context; | ||
beforeEach(function() { | ||
context = { }; | ||
beforeEach(() => { | ||
context = {}; | ||
context.cache = { }; | ||
context.cache = {}; | ||
context.ttl = 600; | ||
context.cacheWrapper = { | ||
get: chai.spy(function(key, cb) { | ||
cb(undefined, context.cache[key]); | ||
}), | ||
set: chai.spy(function(key, value, options, cb) { | ||
get: chai.spy((key, cb) => cb(undefined, context.cache[key])), | ||
set: chai.spy((key, value, options, cb) => { | ||
context.cache[key] = value; | ||
cb(); | ||
return cb(); | ||
}), | ||
ttl: chai.spy(function(key, cb) { | ||
cb(undefined, 600); | ||
}) | ||
ttl: chai.spy((key, cb) => cb(undefined, 600)) | ||
}; | ||
@@ -36,17 +32,15 @@ | ||
callbacks: { | ||
onHit: chai.spy(function() { }), | ||
onMiss: chai.spy(function() { }), | ||
onError: chai.spy(function() { }), | ||
onAttempt: chai.spy(function() { }) | ||
onHit: chai.spy(() => { }), | ||
onMiss: chai.spy(() => { }), | ||
onError: chai.spy(() => { }), | ||
onAttempt: chai.spy(() => { }) | ||
} | ||
}; | ||
context.cachingMiddleware = cacheManagerExpress(context.cacheWrapper, context.options); | ||
context.cachingMiddleware = cacheManagerExpress({ cache: context.cacheWrapper, options: context.options }); | ||
context.request = { method: "GET", path: "/a/b/c" }; | ||
context.send = chai.spy(function() { | ||
context.isDone = true; | ||
}); | ||
context.status = chai.spy(function(statusCode) { | ||
context.send = chai.spy(() => context.isDone = true); | ||
context.status = chai.spy(statusCode => { | ||
context.response.statusCode = statusCode; | ||
@@ -59,8 +53,4 @@ return context.response; | ||
context.response = { | ||
get: chai.spy(function() { | ||
return `${context.accessibility}, max-age=${context.maxAge}`; | ||
}), | ||
set: chai.spy(function(header, value) { | ||
context.cacheControlHeaderValue = value; | ||
}), | ||
get: chai.spy(() => `${context.accessibility}, max-age=${context.maxAge}`), | ||
set: chai.spy((header, value) => context.cacheControlHeaderValue = value), | ||
send: context.send, | ||
@@ -71,15 +61,11 @@ status: context.status | ||
context.statusCode = 200; | ||
context.body = JSON.stringify({ id: uuid.v4() }); | ||
context.next = chai.spy(function() { | ||
context.response.status(context.statusCode).send(context.body); | ||
}); | ||
context.body = JSON.stringify({ id: uuid() }); | ||
context.next = chai.spy(() => context.response.status(context.statusCode).send(context.body)); | ||
context.doneCondition = function() { | ||
return context.isDone; | ||
}; | ||
context.doneCondition = () => context.isDone; | ||
}); | ||
describe("Getting a request when there is no cache", function() { | ||
it("should result in no interaction with the cache", function() { | ||
context.cachingMiddleware = cacheManagerExpress(null, context.options); | ||
describe("Getting a request when there is no cache", () => { | ||
it("should result in no interaction with the cache", () => { | ||
context.cachingMiddleware = cacheManagerExpress({ options: context.options }); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -108,4 +94,4 @@ return checkDone(context.doneCondition) | ||
describe("Getting a request that has not been cached before", function() { | ||
it("should cache the response successfully", function() { | ||
describe("Getting a request that has not been cached before", () => { | ||
it("should cache the response successfully", () => { | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -135,4 +121,82 @@ return checkDone(context.doneCondition) | ||
describe("Getting a request that has not been cached before and options is undefined", function() { | ||
it("should cache the response successfully", function() { | ||
describe("Getting a request that has not been cached before and the service returns a 304", () => { | ||
it("should cache the response successfully", () => { | ||
context.statusCode = 304; | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
return checkDone(context.doneCondition) | ||
.then(() => { | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context).to.not.have.property("cacheControlHeaderValue"); | ||
expect(context.response.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.set).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cache).to.exist.and.be.an("object"); | ||
expect(context.cache).to.have.property("GET:/a/b/c").and.deep | ||
.equal({ statusCode: context.statusCode, body: context.body, accessibility: context.accessibility }); | ||
expect(context.status).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.send).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.next).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.options.callbacks.onHit).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onMiss).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.options.callbacks.onError).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onAttempt).to.be.a.spy.and.to.have.been.called(); | ||
}); | ||
}); | ||
}); | ||
describe("Getting a request that has not been cached before and the service returns a 500", () => { | ||
it("should not cache the response", () => { | ||
context.statusCode = 500; | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
return checkDone(context.doneCondition) | ||
.then(() => { | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context).to.not.have.property("cacheControlHeaderValue"); | ||
expect(context.response.get).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.cacheWrapper.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.cache).to.exist.and.be.an("object"); | ||
expect(context.cache).to.not.have.property("GET:/a/b/c"); | ||
expect(context.status).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.send).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.next).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.options.callbacks.onHit).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onMiss).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.options.callbacks.onError).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onAttempt).to.be.a.spy.and.to.have.been.called(); | ||
}); | ||
}); | ||
}); | ||
describe("Getting a request that has not been cached before and no callbacks are defined", () => { | ||
it("should not cause an error", () => { | ||
context.options.callbacks = {}; | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
return checkDone(context.doneCondition) | ||
.then(() => { | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context).to.not.have.property("cacheControlHeaderValue"); | ||
expect(context.response.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.set).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cache).to.exist.and.be.an("object"); | ||
expect(context.cache).to.have.property("GET:/a/b/c").and.deep | ||
.equal({ statusCode: context.statusCode, body: context.body, accessibility: context.accessibility }); | ||
expect(context.status).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.send).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.next).to.be.a.spy.and.to.have.been.called(); | ||
}); | ||
}); | ||
}); | ||
describe("Getting a request that has not been cached before and options is undefined", () => { | ||
it("should cache the response successfully", () => { | ||
context.options = undefined; | ||
@@ -158,4 +222,6 @@ context.cachingMiddleware(context.request, context.response, context.next); | ||
describe("Getting a request that has been cached before", function() { | ||
it("should return the cached response successfully", function() { | ||
describe("Getting a request that has been cached before and no callbacks are defined", () => { | ||
it("should not cause an error", () => { | ||
context.options.callbacks = {}; | ||
context.cache["GET:/a/b/c"] = { | ||
@@ -182,7 +248,2 @@ statusCode: context.statusCode, | ||
expect(context.next).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onHit).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.options.callbacks.onMiss).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onError).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.options.callbacks.onAttempt).to.be.a.spy.and.to.have.been.called(); | ||
}); | ||
@@ -192,4 +253,4 @@ }); | ||
describe("Getting a request that has been cached before and options in undefined", function() { | ||
it("should return the cached response successfully", function() { | ||
describe("Getting a request that has been cached before and options in undefined", () => { | ||
it("should return the cached response successfully", () => { | ||
context.options = undefined; | ||
@@ -221,7 +282,5 @@ context.cache["GET:/a/b/c"] = { | ||
describe("Handling a response without a cache control header when it has not been cached", function() { | ||
it("should return but not cache the response", function() { | ||
context.response.get = chai.spy(function() { | ||
return null; | ||
}); | ||
describe("Handling a response without a cache control header when it has not been cached", () => { | ||
it("should return but not cache the response", () => { | ||
context.response.get = chai.spy(() => { }); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -250,7 +309,5 @@ return checkDone(context.doneCondition) | ||
describe("Getting an error when accessing the cache on a get", function() { | ||
it("should return the response successfully", function() { | ||
context.cacheWrapper.get = chai.spy(function(key, cb) { | ||
cb("The cache could not be reached."); | ||
}); | ||
describe("Getting an error when accessing the cache on a get", () => { | ||
it("should return the response successfully", () => { | ||
context.cacheWrapper.get = chai.spy((key, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -280,4 +337,28 @@ return checkDone(context.doneCondition) | ||
describe("Getting an error when accessing the cache on retrieving the ttl", function() { | ||
it("should return the response successfully", function() { | ||
describe("Getting an error when accessing the cache on a get and no callbacks are defined", () => { | ||
it("should not cause an error", () => { | ||
context.options.callbacks = {}; | ||
context.cacheWrapper.get = chai.spy((key, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
return checkDone(context.doneCondition) | ||
.then(() => { | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context).to.not.have.property("cacheControlHeaderValue"); | ||
expect(context.response.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.set).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cache).to.exist.and.be.an("object"); | ||
expect(context.cache).to.have.property("GET:/a/b/c").and.deep | ||
.equal({ statusCode: context.statusCode, body: context.body, accessibility: context.accessibility }); | ||
expect(context.status).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.send).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.next).to.be.a.spy.and.to.have.been.called(); | ||
}); | ||
}); | ||
}); | ||
describe("Getting an error when accessing the cache on retrieving the ttl", () => { | ||
it("should return the response successfully", () => { | ||
context.cache["GET:/a/b/c"] = { | ||
@@ -288,5 +369,3 @@ statusCode: context.statusCode, | ||
}; | ||
context.cacheWrapper.ttl = chai.spy(function(key, cb) { | ||
cb("The cache could not be reached."); | ||
}); | ||
context.cacheWrapper.ttl = chai.spy((key, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -316,7 +395,12 @@ return checkDone(context.doneCondition) | ||
describe("Getting an error when accessing the cache on a set", function() { | ||
it("should return the response successfully", function() { | ||
context.cacheWrapper.set = chai.spy(function(key, value, options, cb) { | ||
cb("The cache could not be reached."); | ||
}); | ||
describe("Getting an error when accessing the cache on retrieving the ttl and no callbacks are defined", () => { | ||
it("should not cause an error", () => { | ||
context.options.callbacks = {}; | ||
context.cache["GET:/a/b/c"] = { | ||
statusCode: context.statusCode, | ||
body: context.body, | ||
accessibility: context.accessibility | ||
}; | ||
context.cacheWrapper.ttl = chai.spy((key, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -326,2 +410,24 @@ return checkDone(context.doneCondition) | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context).to.not.have.property("cacheControlHeaderValue"); | ||
expect(context.response.get).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.cacheWrapper.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.cache).to.exist.and.be.an("object"); | ||
expect(context.cache).to.have.property("GET:/a/b/c").and.deep | ||
.equal({ statusCode: context.statusCode, body: context.body, accessibility: context.accessibility }); | ||
expect(context.status).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.send).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.next).to.be.a.spy.and.to.not.have.been.called(); | ||
}); | ||
}); | ||
}); | ||
describe("Getting an error when accessing the cache on a set", () => { | ||
it("should return the response successfully", () => { | ||
context.cacheWrapper.set = chai.spy((key, value, options, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
return checkDone(context.doneCondition) | ||
.then(() => { | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.not.have.been.called(); | ||
@@ -346,10 +452,7 @@ expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
describe("Getting an error when accessing the cache on a get and a set", function() { | ||
it("should return the response successfully", function() { | ||
context.cacheWrapper.get = chai.spy(function(key, cb) { | ||
cb("The cache could not be reached."); | ||
}); | ||
context.cacheWrapper.set = chai.spy(function(key, value, options, cb) { | ||
cb("The cache could not be reached."); | ||
}); | ||
describe("Getting an error when accessing the cache on a set and no callbacks are defined", () => { | ||
it("should not cause an error", () => { | ||
context.options.callbacks = {}; | ||
context.cacheWrapper.set = chai.spy((key, value, options, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -369,3 +472,25 @@ return checkDone(context.doneCondition) | ||
expect(context.next).to.be.a.spy.and.to.have.been.called(); | ||
}); | ||
}); | ||
}); | ||
describe("Getting an error when accessing the cache on a get and a set", () => { | ||
it("should return the response successfully", () => { | ||
context.cacheWrapper.get = chai.spy((key, cb) => cb("The cache could not be reached.")); | ||
context.cacheWrapper.set = chai.spy((key, value, options, cb) => cb("The cache could not be reached.")); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
return checkDone(context.doneCondition) | ||
.then(() => { | ||
expect(context.cacheWrapper.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.ttl).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context.response.set).to.be.a.spy.and.to.not.have.been.called(); | ||
expect(context).to.not.have.property("cacheControlHeaderValue"); | ||
expect(context.response.get).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cacheWrapper.set).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.cache).to.exist.and.be.an("object"); | ||
expect(context.cache).to.not.have.property("GET:/a/b/c"); | ||
expect(context.status).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.send).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.next).to.be.a.spy.and.to.have.been.called(); | ||
expect(context.options.callbacks.onHit).to.be.a.spy.and.to.not.have.been.called(); | ||
@@ -379,7 +504,5 @@ expect(context.options.callbacks.onMiss).to.be.a.spy.and.to.have.been.called(); | ||
describe("Getting a request that has not been cached before with no accessibility on the response", function() { | ||
it("should cache the response successfully", function() { | ||
context.response.get = chai.spy(function() { | ||
return `max-age=${context.ttl}`; | ||
}); | ||
describe("Getting a request that has not been cached before with no accessibility on the response", () => { | ||
it("should cache the response successfully", () => { | ||
context.response.get = chai.spy(() => `max-age=${context.ttl}`); | ||
context.cachingMiddleware(context.request, context.response, context.next); | ||
@@ -408,4 +531,4 @@ return checkDone(context.doneCondition) | ||
describe("Getting a request that has been cached with no accessibility on the response", function() { | ||
it("should return the cached response successfully", function() { | ||
describe("Getting a request that has been cached with no accessibility on the response", () => { | ||
it("should return the cached response successfully", () => { | ||
context.cache["GET:/a/b/c"] = { | ||
@@ -440,4 +563,4 @@ statusCode: context.statusCode, | ||
describe("Getting a request that has been cached but the cache does not support retrieving the ttl", function() { | ||
it("should return the cached response successfully but without a cache control header", function() { | ||
describe("Getting a request that has been cached but the cache does not support retrieving the ttl", () => { | ||
it("should return the cached response successfully but without a cache control header", () => { | ||
context.cache["GET:/a/b/c"] = { | ||
@@ -472,10 +595,10 @@ statusCode: context.statusCode, | ||
var checkDone = function(condition, maxCount, delay) { | ||
var result = condition(); | ||
var _delay = delay || 20; | ||
var _maxCount = !_.isNil(maxCount) ? maxCount : 5; | ||
const checkDone = (condition, maxCount, delay) => { | ||
const result = condition(); | ||
const _delay = delay || 20; | ||
const _maxCount = !_isNil(maxCount) ? maxCount : 5; | ||
if (!result) { | ||
if (_maxCount > 0) { | ||
return Promise.delay(_delay) | ||
return P.delay(_delay) | ||
.then(() => checkDone(condition, _maxCount - 1, _delay)); | ||
@@ -487,4 +610,4 @@ } | ||
return Promise.resolve(result); | ||
return P.resolve(result); | ||
}; | ||
}); |
@@ -1,19 +0,29 @@ | ||
var getCacheKey = require("../../helpers/getcachekey.js"), | ||
expect = require("chai").expect; | ||
const expect = require("chai").expect, | ||
getCacheKey = require("../../helpers/getcachekey.js"); | ||
describe("GetCacheKey", function() { | ||
var context; | ||
describe("GetCacheKey", () => { | ||
let context; | ||
beforeEach(function() { | ||
context = { }; | ||
beforeEach(() => { | ||
context = {}; | ||
context.request = { | ||
method: "GET", | ||
path: "/a/b/c" | ||
path: "/a/b/c", | ||
get: (header) => { | ||
switch (header) { | ||
case "accept": | ||
return "application/json"; | ||
case "authorization": | ||
return "Bearer abc123"; | ||
default: | ||
return; | ||
} | ||
} | ||
}; | ||
}); | ||
describe("Getting a cache key for a request", function() { | ||
it("should return the expected key", function() { | ||
var key = getCacheKey(context.request); | ||
describe("Getting a cache key for a request", () => { | ||
it("should return the expected key", () => { | ||
const key = getCacheKey({ request: context.request }); | ||
expect(key).to.equal("GET:/a/b/c"); | ||
@@ -23,5 +33,5 @@ }); | ||
describe("Getting a cache key for a request with a prefix", function() { | ||
it("should return the expected key", function() { | ||
var key = getCacheKey(context.request, "MyPrefix"); | ||
describe("Getting a cache key for a request with a prefix", () => { | ||
it("should return the expected key", () => { | ||
const key = getCacheKey({ request: context.request, options: { prefix: "MyPrefix" } }); | ||
expect(key).to.equal("MyPrefix:GET:/a/b/c"); | ||
@@ -31,5 +41,5 @@ }); | ||
describe("Getting a cache key for a request with a prefix with a colon suffix", function() { | ||
it("should return the expected key", function() { | ||
var key = getCacheKey(context.request, "MyPrefix:"); | ||
describe("Getting a cache key for a request with a prefix with a colon suffix", () => { | ||
it("should return the expected key", () => { | ||
const key = getCacheKey({ request: context.request, options: { prefix: "MyPrefix:" } }); | ||
expect(key).to.equal("MyPrefix:GET:/a/b/c"); | ||
@@ -39,6 +49,6 @@ }); | ||
describe("Getting a cache key for a request with a query string", function() { | ||
it("should return the expected key", function() { | ||
describe("Getting a cache key for a request with a query string", () => { | ||
it("should return the expected key", () => { | ||
context.request.query = { def: 123 }; | ||
var key = getCacheKey(context.request); | ||
const key = getCacheKey({ request: context.request }); | ||
expect(key).to.equal("GET:/a/b/c?def=123"); | ||
@@ -48,6 +58,6 @@ }); | ||
describe("Getting a cache key for a request with a query string with no values", function() { | ||
it("should return the expected key", function() { | ||
describe("Getting a cache key for a request with a query string with no values", () => { | ||
it("should return the expected key", () => { | ||
context.request.query = { def: null }; | ||
var key = getCacheKey(context.request); | ||
const key = getCacheKey({ request: context.request }); | ||
expect(key).to.equal("GET:/a/b/c"); | ||
@@ -57,15 +67,29 @@ }); | ||
describe("Getting a cache key for a request with a query string and a default value", function() { | ||
it("should return the expected key", function() { | ||
describe("Getting a cache key for a request with a query string and a default value", () => { | ||
it("should return the expected key", () => { | ||
context.request.query = { def: 123 }; | ||
var key = getCacheKey(context.request, null, { ghi: false }); | ||
const key = getCacheKey({ request: context.request, options: { defaults: { ghi: false } } }); | ||
expect(key).to.equal("GET:/a/b/c?def=123&ghi=false"); | ||
}); | ||
it("should not be overwritten by the default value if present", function() { | ||
it("should not be overwritten by the default value if present", () => { | ||
context.request.query = { def: 123 }; | ||
var key = getCacheKey(context.request, null, { def: false }); | ||
const key = getCacheKey({ request: context.request, options: { defaults: { def: false } } }); | ||
expect(key).to.equal("GET:/a/b/c?def=123"); | ||
}); | ||
}); | ||
describe("Getting a cache key for a request when a single header should be part of the key", () => { | ||
it("should return the expected key", () => { | ||
const key = getCacheKey({ request: context.request, options: { headers: "Authorization" } }); | ||
expect(key).to.equal("GET:authorization:Bearer abc123:/a/b/c"); | ||
}); | ||
}); | ||
describe("Getting a cache key for a request when headers should be part of the key", () => { | ||
it("should return the expected key", () => { | ||
const key = getCacheKey({ request: context.request, options: { headers: [ "Authorization", "Accept" ] } }); | ||
expect(key).to.equal("GET:accept:application/json:authorization:Bearer abc123:/a/b/c"); | ||
}); | ||
}); | ||
}); |
@@ -1,20 +0,18 @@ | ||
var getCachingStrategy = require("../../helpers/getcachingstrategy.js"), | ||
expect = require("chai").expect; | ||
const expect = require("chai").expect, | ||
getCachingStrategy = require("../../helpers/getcachingstrategy.js"); | ||
describe("GetCachingStrategy", function() { | ||
var context; | ||
describe("GetCachingStrategy", () => { | ||
let context; | ||
beforeEach(function() { | ||
context = { }; | ||
beforeEach(() => { | ||
context = {}; | ||
context.response = { | ||
get: function() { | ||
return "private, max-age=12345"; | ||
} | ||
get: () => "private, max-age=12345" | ||
}; | ||
}); | ||
describe("Getting the caching strategy from a response", function() { | ||
it("should return the appropriate strategy", function() { | ||
var strategy = getCachingStrategy(context.response); | ||
describe("Getting the caching strategy from a response", () => { | ||
it("should return the appropriate strategy", () => { | ||
const strategy = getCachingStrategy({ response: context.response }); | ||
expect(strategy).to.exist.and.be.an("object"); | ||
@@ -26,8 +24,6 @@ expect(strategy).to.have.property("accessibility").and.equal("private"); | ||
describe("Getting the caching strategy from a response without a cache-control header", function() { | ||
it("should return undefined", function() { | ||
context.response.get = function() { | ||
return; | ||
}; | ||
var strategy = getCachingStrategy(context.response); | ||
describe("Getting the caching strategy from a response without a cache-control header", () => { | ||
it("should return undefined", () => { | ||
context.response.get = () => { }; | ||
const strategy = getCachingStrategy({ response: context.response }); | ||
expect(strategy).to.be.undefined; | ||
@@ -37,8 +33,6 @@ }); | ||
describe("Getting the caching strategy from a cache-control header missing accessibility", function() { | ||
it("should return only the max age", function() { | ||
context.response.get = function() { | ||
return "max-age=12345"; | ||
}; | ||
var strategy = getCachingStrategy(context.response); | ||
describe("Getting the caching strategy from a cache-control header missing accessibility", () => { | ||
it("should return only the max age", () => { | ||
context.response.get = () => "max-age=12345"; | ||
const strategy = getCachingStrategy({ response: context.response }); | ||
expect(strategy).to.exist.and.be.an("object"); | ||
@@ -50,8 +44,6 @@ expect(strategy).to.not.have.property("accessibility"); | ||
describe("Getting the caching strategy from a cache-control header missing the max age", function() { | ||
it("should return undefined", function() { | ||
context.response.get = function() { | ||
return "public"; | ||
}; | ||
var strategy = getCachingStrategy(context.response); | ||
describe("Getting the caching strategy from a cache-control header missing the max age", () => { | ||
it("should return undefined", () => { | ||
context.response.get = () => "public"; | ||
const strategy = getCachingStrategy({ response: context.response }); | ||
expect(strategy).to.be.undefined; | ||
@@ -61,8 +53,6 @@ }); | ||
describe("Getting the caching strategy from a cache-control header with invalid accessibility", function() { | ||
it("should return only the max age", function() { | ||
context.response.get = function() { | ||
return "protected, max-age=12345"; | ||
}; | ||
var strategy = getCachingStrategy(context.response); | ||
describe("Getting the caching strategy from a cache-control header with invalid accessibility", () => { | ||
it("should return only the max age", () => { | ||
context.response.get = () => "protected, max-age=12345"; | ||
const strategy = getCachingStrategy({ response: context.response }); | ||
expect(strategy).to.exist.and.be.an("object"); | ||
@@ -69,0 +59,0 @@ expect(strategy).to.not.have.property("accessibility"); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
193242
8
22
915
62
0
13
+ Addedlodash.defaults@^4.2.0
+ Addedlodash.endswith@^4.2.1
+ Addedlodash.get@^4.4.2
+ Addedlodash.isempty@^4.4.0
+ Addedlodash.isnil@^4.0.0
+ Addedlodash.isstring@^4.0.1
+ Addedlodash.keys@^4.2.0
+ Addedlodash.map@^4.6.0
+ Addedlodash.omitby@^4.6.0
+ Addedlodash.tointeger@^4.0.4
+ Addedlodash.tolower@^4.1.2
+ Addedlodash.trim@^4.5.1
+ Addedlodash.defaults@4.2.0(transitive)
+ Addedlodash.endswith@4.2.1(transitive)
+ Addedlodash.get@4.4.2(transitive)
+ Addedlodash.isempty@4.4.0(transitive)
+ Addedlodash.isnil@4.0.0(transitive)
+ Addedlodash.isstring@4.0.1(transitive)
+ Addedlodash.keys@4.2.0(transitive)
+ Addedlodash.map@4.6.0(transitive)
+ Addedlodash.omitby@4.6.0(transitive)
+ Addedlodash.tointeger@4.0.4(transitive)
+ Addedlodash.tolower@4.1.2(transitive)
+ Addedlodash.trim@4.5.1(transitive)
- Removedlodash@^4.15.0
- Removedlodash@4.17.21(transitive)