CachingMiddleware: Asyncify

This commit is contained in:
Richard Hansen 2021-02-27 00:08:29 -05:00 committed by webzwo0i
parent 0284d49522
commit f86df5322e
2 changed files with 99 additions and 112 deletions

View file

@ -31,7 +31,7 @@ const getTar = async () => {
exports.expressCreateServer = async (hookName, args) => { exports.expressCreateServer = async (hookName, args) => {
// Cache both minified and static. // Cache both minified and static.
const assetCache = new CachingMiddleware(); const assetCache = new CachingMiddleware();
args.app.all(/\/javascripts\/(.*)/, assetCache.handle); args.app.all(/\/javascripts\/(.*)/, assetCache.handle.bind(assetCache));
// Minify will serve static files compressed (minify enabled). It also has // Minify will serve static files compressed (minify enabled). It also has
// file-specific hacks for ace/require-kernel/etc. // file-specific hacks for ace/require-kernel/etc.

View file

@ -16,13 +16,14 @@
* limitations under the License. * limitations under the License.
*/ */
const async = require('async');
const Buffer = require('buffer').Buffer; const Buffer = require('buffer').Buffer;
const fs = require('fs'); const fs = require('fs');
const fsp = fs.promises;
const path = require('path'); const path = require('path');
const zlib = require('zlib'); const zlib = require('zlib');
const settings = require('./Settings'); const settings = require('./Settings');
const existsSync = require('./path_exists'); const existsSync = require('./path_exists');
const util = require('util');
/* /*
* The crypto module can be absent on reduced node installations. * The crypto module can be absent on reduced node installations.
@ -79,6 +80,10 @@ if (_crypto) {
module.exports = class CachingMiddleware { module.exports = class CachingMiddleware {
handle(req, res, next) { handle(req, res, next) {
this._handle(req, res, next).catch((err) => next(err || new Error(err)));
}
async _handle(req, res, next) {
if (!(req.method === 'GET' || req.method === 'HEAD') || !CACHE_DIR) { if (!(req.method === 'GET' || req.method === 'HEAD') || !CACHE_DIR) {
return next(undefined, req, res); return next(undefined, req, res);
} }
@ -92,12 +97,11 @@ module.exports = class CachingMiddleware {
const url = new URL(req.url, 'http://localhost'); const url = new URL(req.url, 'http://localhost');
const cacheKey = generateCacheKey(url.pathname + url.search); const cacheKey = generateCacheKey(url.pathname + url.search);
fs.stat(`${CACHE_DIR}minified_${cacheKey}`, (error, stats) => { const stats = await fsp.stat(`${CACHE_DIR}minified_${cacheKey}`).catch(() => {});
const modifiedSince = (req.headers['if-modified-since'] && const modifiedSince =
new Date(req.headers['if-modified-since'])); req.headers['if-modified-since'] && new Date(req.headers['if-modified-since']);
const lastModifiedCache = !error && stats.mtime; if (stats != null && stats.mtime && responseCache[cacheKey]) {
if (lastModifiedCache && responseCache[cacheKey]) { req.headers['if-modified-since'] = stats.mtime.toUTCString();
req.headers['if-modified-since'] = lastModifiedCache.toUTCString();
} else { } else {
delete req.headers['if-modified-since']; delete req.headers['if-modified-since'];
} }
@ -125,8 +129,7 @@ module.exports = class CachingMiddleware {
headers['content-encoding'] = 'gzip'; headers['content-encoding'] = 'gzip';
} }
const lastModified = (headers['last-modified'] && const lastModified = headers['last-modified'] && new Date(headers['last-modified']);
new Date(headers['last-modified']));
if (statusCode === 200 && lastModified <= modifiedSince) { if (statusCode === 200 && lastModified <= modifiedSince) {
res.writeHead(304, headers); res.writeHead(304, headers);
@ -174,30 +177,15 @@ module.exports = class CachingMiddleware {
res.write = (data, encoding) => { res.write = (data, encoding) => {
buffer += data.toString(encoding); buffer += data.toString(encoding);
}; };
res.end = (data, encoding) => { res.end = async (data, encoding) => {
async.parallel([ await Promise.all([
(callback) => { fsp.writeFile(`${CACHE_DIR}minified_${cacheKey}`, buffer).catch(() => {}),
const path = `${CACHE_DIR}minified_${cacheKey}`; util.promisify(zlib.gzip)(buffer)
fs.writeFile(path, buffer, (error, stats) => { .then((content) => fsp.writeFile(`${CACHE_DIR}minified_${cacheKey}.gz`, content))
callback(); .catch(() => {}),
}); ]);
},
(callback) => {
const path = `${CACHE_DIR}minified_${cacheKey}.gz`;
zlib.gzip(buffer, (error, content) => {
if (error) {
callback();
} else {
fs.writeFile(path, content, (error, stats) => {
callback();
});
}
});
},
], () => {
responseCache[cacheKey] = {statusCode: status, headers}; responseCache[cacheKey] = {statusCode: status, headers};
respond(); respond();
});
}; };
} else if (status === 304) { } else if (status === 304) {
// Nothing new changed from the cached version. // Nothing new changed from the cached version.
@ -211,6 +199,5 @@ module.exports = class CachingMiddleware {
}; };
next(undefined, req, res); next(undefined, req, res);
});
} }
}; };