UNPKG

simple-node-framework

Version:

Simple nodeJs framework that provides easy ways to use log, cache, database, session, redis, share request scope and more.

112 lines (92 loc) 4.01 kB
const Loggable = require('./base/loggable'); const config = require('./config'); const redis = require('./redis').instance; const errorHandler = require('./error').instance; const objectHash = require('object-hash'); // abstracts the request/response cache concept class Cache extends Loggable { constructor() { super({ module: 'SNF Cache' }); this.config = config; this.redis = redis; this.errorHandler = errorHandler; } // save response to cache saveResponse(status, body, headers, req, ttl) { // build the key to save in cache const key = this.getCacheKey(req); // dont store in cache if no-store if (this.hasCacheControl(req.headers, 'no-store')) { this.log.debug(`The cache will not be saved because no-store was defined [${key}]`); return Promise.resolve(false); } const _status = status || 200; const saveTtl = ttl || this.config.cache.ttl || 60 * 60; const cache = { body, headers, status: _status }; return this.redis.set(key, cache, saveTtl); } // load response from de cache loadResponse(req, res, next) { // build the key to sabe in cache const key = this.getCacheKey(req); // dont get from cache if no-cache if (this.hasCacheControl(req.headers, 'no-cache')) { this.log.debug(`The cache will not be loaded because no-cache was defined [${key}]`); return next(); } if(this.config.cache.logHit) this.log.debug(`Trying get from cache [${key}]`); return this.redis .get(key) .then( (cache) => { if(this.config.cache.logHits) this.log.debug(`Hit from cache [${key}]`); res.status(cache.status).set(cache.headers).send(cache.body); }, (err) => { if(this.config.cache.logHit) this.log.debug(`Error on Trying get from cache [${key}]`, err); if (err.code === 'no_key_found') return next(); return next(this.errorHandler.throw(`Error on loading [${key}] from cache`, 'InternalServerError')); } ) .catch((err) => { if(this.config.cache.logHit) this.log.debug(`Error on Trying get from cache [${key}]`, err); return this.errorHandler.send(req, res, err, this.errorHandler.throw(`Unexpected error on cache [${key}]`, 'InternalServerError')); }).finally(() =>{ if(this.config.cache.logHit) this.log.debug(`Finishing get from cache [${key}]`); }); } // load response to use add this to your routes file: Cache.loadResponse static loadResponse(req, res, next) { req.cache.loadResponse(req, res, next); } // only a alias for redis set save(key, value, ttl) { return this.redis.set(key, value, ttl); } // only a alias for redis get load(key) { return this.redis.get(key); } // get an cache key like "simple-node-framework:cache:my-application:get:api/sample-module" getCacheKey(req) { const { method } = req; const route = `${req.url.replace(/^\/|\/$/g, '')}`; const prefix = this.config.cache.prefix || 'simple-node-framework'; const appName = this.config.app.name; const headerKey = this.config.cache.headerKey ? `${req.headers[this.config.cache.headerKey]}:` : ''; const body = objectHash(req.body) return `${prefix}:${headerKey}cache:${appName}:${method}:${route}:${body}`.toLowerCase(); } // verify if a key its in cache-control header hasCacheControl(headers, key) { const cacheControl = headers && headers['cache-control'] ? headers['cache-control'] : ''; return cacheControl.toLowerCase().includes(key); } } module.exports = Cache;