Files
directus/api/src/middleware/cache.ts
José Varela cc343fdf91 Improve cache performance by compressing records (#14833)
* Utils to compress/decompress data
Gzip was chosen because we want smaller data but quick algorithm since this will be ran for every request

* Compress system cache

* Decompress system cache

* Set/Get compressed cache for individual requests

* Switch from gzip to snappy, use json compression too

* Fix cache exp set/get

* Remove unused import

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
2022-08-04 17:35:27 -04:00

58 lines
1.9 KiB
TypeScript

import { RequestHandler } from 'express';
import { getCache, getCacheValue } from '../cache';
import env from '../env';
import asyncHandler from '../utils/async-handler';
import { getCacheControlHeader } from '../utils/get-cache-headers';
import { getCacheKey } from '../utils/get-cache-key';
import logger from '../logger';
const checkCacheMiddleware: RequestHandler = asyncHandler(async (req, res, next) => {
const { cache } = getCache();
if (req.method.toLowerCase() !== 'get' && req.path?.startsWith('/graphql') === false) return next();
if (env.CACHE_ENABLED !== true) return next();
if (!cache) return next();
if (req.headers['cache-control']?.includes('no-store') || req.headers['Cache-Control']?.includes('no-store')) {
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
return next();
}
const key = getCacheKey(req);
let cachedData;
try {
cachedData = await getCacheValue(cache, key);
} catch (err: any) {
logger.warn(err, `[cache] Couldn't read key ${key}. ${err.message}`);
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
return next();
}
if (cachedData) {
let cacheExpiryDate;
try {
cacheExpiryDate = (await getCacheValue(cache, `${key}__expires_at`))?.exp;
} catch (err: any) {
logger.warn(err, `[cache] Couldn't read key ${`${key}__expires_at`}. ${err.message}`);
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
return next();
}
const cacheTTL = cacheExpiryDate ? cacheExpiryDate - Date.now() : null;
res.setHeader('Cache-Control', getCacheControlHeader(req, cacheTTL));
res.setHeader('Vary', 'Origin, Cache-Control');
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'HIT');
return res.json(cachedData);
} else {
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
return next();
}
});
export default checkCacheMiddleware;