route-cache
Advanced tools
Comparing version 0.4.7 to 0.5.0
230
index.js
'use strict' | ||
const LRU = require('lru-cache') | ||
const LruStore = require('./lruStore') | ||
const debug = require('debug')('route-cache') | ||
@@ -16,9 +16,17 @@ const queues = Object.create(null) | ||
} | ||
let cacheStore = new LRU(defaults) | ||
let cacheStore = new LruStore(defaults) | ||
module.exports.config = function (opts) { | ||
if (opts && opts.max) { | ||
defaults.max = opts.max | ||
if (opts) { | ||
if (opts.max) { | ||
defaults.max = opts.max | ||
} | ||
if (opts.cacheStore) { | ||
cacheStore = opts.cacheStore | ||
} else { | ||
cacheStore = new LruStore(defaults) | ||
} | ||
module.exports.cacheStore = cacheStore | ||
} | ||
cacheStore = new LRU(defaults) | ||
return this | ||
@@ -49,123 +57,139 @@ } | ||
const redirectKey = cacheStore.get('redirect:' + key) | ||
if (redirectKey) { | ||
return res.redirect(redirectKey.status, redirectKey.url) | ||
} | ||
const value = cacheStore.get(key) | ||
if (value) { | ||
// returns the value immediately | ||
debug('hit!!', key) | ||
if (value.isJson) { | ||
res.json(value.body) | ||
} else { | ||
res.send(value.body) | ||
cacheStore.get('redirect:' + key).then((redirectKey) => { | ||
if (redirectKey) { | ||
res.redirect(redirectKey.status, redirectKey.url) | ||
return true | ||
} | ||
return | ||
} | ||
return false | ||
}).then((handledByRedirect) => { | ||
if (handledByRedirect) return true | ||
return cacheStore.get(key).then((value) => { | ||
if (value) { | ||
// returns the value immediately | ||
debug('hit!!', key) | ||
if (value.isJson) { | ||
res.json(value.body) | ||
} else { | ||
res.send(value.body) | ||
} | ||
return true | ||
} | ||
return false | ||
}) | ||
}).then((handledByCache) => { | ||
if (handledByCache) return true | ||
res.original_send = res.send | ||
res.original_end = res.end | ||
res.original_json = res.json | ||
res.original_redirect = res.redirect | ||
res.original_send = res.send | ||
res.original_end = res.end | ||
res.original_json = res.json | ||
res.original_redirect = res.redirect | ||
if (!queues[key]) { | ||
queues[key] = [] | ||
} | ||
if (!queues[key]) { | ||
queues[key] = [] | ||
} | ||
let didHandle = false | ||
let didHandle = false | ||
function rawSend (data, isJson) { | ||
debug('rawSend', typeof data, data ? data.length : 0) | ||
// pass-through for Buffer - not supported | ||
if (typeof data === 'object') { | ||
if (Buffer.isBuffer(data)) { | ||
queues[key] = [] // clear queue | ||
res.set('Content-Length', data.length) | ||
res.original_send(data) | ||
return | ||
function rawSend (data, isJson) { | ||
debug('rawSend', typeof data, data ? data.length : 0) | ||
// pass-through for Buffer - not supported | ||
if (typeof data === 'object') { | ||
if (Buffer.isBuffer(data)) { | ||
queues[key] = [] // clear queue | ||
res.set('Content-Length', data.length) | ||
res.original_send(data) | ||
return | ||
} | ||
} | ||
} | ||
didHandle = true | ||
const body = data instanceof Buffer ? data.toString() : data | ||
if (res.statusCode < 400) cacheStore.set(key, { body: body, isJson: isJson }, ttl) | ||
didHandle = true | ||
const body = data instanceof Buffer ? data.toString() : data | ||
if (res.statusCode < 400) cacheStore.set(key, { body: body, isJson: isJson }, ttl) | ||
// send this response to everyone in the queue | ||
drainQueue(key) | ||
// send this response to everyone in the queue | ||
drainQueue(key) | ||
if (isJson) { | ||
debug('res.original_json') | ||
res.original_json(body) | ||
} else { | ||
debug('res.original_send') | ||
res.original_send(body) | ||
} | ||
} | ||
// first request will get rendered output | ||
if (queues[key].length === 0) { | ||
debug('miss:', key) | ||
queues[key].push(function noop () {}) | ||
didHandle = false | ||
res.send = function (data) { | ||
// debug('res.send() >>', data.length) | ||
if (didHandle) { | ||
res.original_send(data) | ||
if (isJson) { | ||
debug('res.original_json') | ||
res.original_json(body) | ||
} else { | ||
rawSend(data, false) | ||
debug('res.original_send') | ||
res.original_send(body) | ||
} | ||
} | ||
res.end = (data) => { | ||
res.original_end(data) | ||
drainQueue(key) | ||
} | ||
// first request will get rendered output | ||
if (queues[key].length === 0) { | ||
debug('miss:', key) | ||
queues[key].push(function noop () {}) | ||
res.json = function (data) { | ||
rawSend(data, true) | ||
} | ||
didHandle = false | ||
// If response happens to be a redirect -- store it to redirect all subsequent requests. | ||
res.redirect = function (url) { | ||
let address = url | ||
let status = 302 | ||
// allow statusCode for 301 redirect. See: https://github.com/expressjs/express/blob/master/lib/response.js#L857 | ||
if (arguments.length === 2) { | ||
if (typeof arguments[0] === 'number') { | ||
status = arguments[0] | ||
address = arguments[1] | ||
res.send = function (data) { | ||
// debug('res.send() >>', data.length) | ||
if (didHandle) { | ||
res.original_send(data) | ||
} else { | ||
console.log('res.redirect(url, status): Use res.redirect(status, url) instead') | ||
status = arguments[1] | ||
rawSend(data, false) | ||
} | ||
} | ||
cacheStore.set('redirect:' + key, { url: address, status: status }, ttl) | ||
res.original_redirect(status, address) | ||
return drainQueue(key) | ||
} | ||
res.end = (data) => { | ||
res.original_end(data) | ||
drainQueue(key) | ||
} | ||
next() | ||
// subsequent requests will batch while the first computes | ||
} else { | ||
debug(key, '>> has queue.length:', queues[key].length) | ||
queues[key].push(function () { | ||
const redirectKey = cacheStore.get('redirect:' + key) | ||
if (redirectKey) { | ||
return res.redirect(redirectKey.status, redirectKey.url) | ||
res.json = function (data) { | ||
rawSend(data, true) | ||
} | ||
const value = cacheStore.get(key) || {} | ||
debug('>> queued hit:', key, value.length) | ||
if (value.isJson) { | ||
res.json(value.body) | ||
} else { | ||
res.send(value.body) | ||
// If response happens to be a redirect -- store it to redirect all subsequent requests. | ||
res.redirect = function (url) { | ||
let address = url | ||
let status = 302 | ||
// allow statusCode for 301 redirect. See: https://github.com/expressjs/express/blob/master/lib/response.js#L857 | ||
if (arguments.length === 2) { | ||
if (typeof arguments[0] === 'number') { | ||
status = arguments[0] | ||
address = arguments[1] | ||
} else { | ||
console.log('res.redirect(url, status): Use res.redirect(status, url) instead') | ||
status = arguments[1] | ||
} | ||
} | ||
cacheStore.set('redirect:' + key, { url: address, status: status }, ttl) | ||
res.original_redirect(status, address) | ||
return drainQueue(key) | ||
} | ||
}) | ||
} | ||
next() | ||
// subsequent requests will batch while the first computes | ||
} else { | ||
debug(key, '>> has queue.length:', queues[key].length) | ||
queues[key].push(function () { | ||
cacheStore.get('redirect:' + key) | ||
.then((redirectKey) => { | ||
if (redirectKey) { | ||
res.redirect(redirectKey.status, redirectKey.url) | ||
return true | ||
} | ||
return false | ||
}) | ||
.then((handledByRedirect) => { | ||
if (handledByRedirect) return | ||
return cacheStore.get(key).then((cachedValue) => { | ||
const value = cachedValue || {} | ||
debug('>> queued hit:', key, value.length) | ||
if (value.isJson) { | ||
res.json(value.body) | ||
} else { | ||
res.send(value.body) | ||
} | ||
}) | ||
}) | ||
}) | ||
} | ||
}) | ||
} | ||
@@ -172,0 +196,0 @@ } |
{ | ||
"name": "route-cache", | ||
"version": "0.4.7", | ||
"version": "0.5.0", | ||
"description": "express middleware for caching your routes", | ||
@@ -30,2 +30,3 @@ "main": "index.js", | ||
"mocha": "^9.1.4", | ||
"sinon": "^14.0.0", | ||
"standard": "^16.0.4", | ||
@@ -32,0 +33,0 @@ "supertest": "^4.0.2" |
@@ -73,5 +73,15 @@ # Route-Cache | ||
## Use a distributed cache | ||
```javascript | ||
const Redis = require('ioredis') | ||
const IoRedisStore = require('route-cache/ioRedisStore') | ||
const redisClient = new Redis(6379, '127.0.0.1')) | ||
const cacheStore = new IoRedisStore(redisClient) | ||
routeCache.config({cacheStore}) | ||
``` | ||
## Future plans / todos | ||
- client-side Cache-Control | ||
- support for distributed caches (redis or memcache) | ||
@@ -78,0 +88,0 @@ ------ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38928
22
1071
113
6