deduplicate server code for caching rendered API endpoints

pull/1/head
ansuz 4 years ago
parent 49528ca8ee
commit 34e02a23e7

@ -201,46 +201,14 @@ app.use("/customize.dist", Express.static(__dirname + '/customize.dist'));
app.use(/^\/[^\/]*$/, Express.static('customize')); app.use(/^\/[^\/]*$/, Express.static('customize'));
app.use(/^\/[^\/]*$/, Express.static('customize.dist')); app.use(/^\/[^\/]*$/, Express.static('customize.dist'));
var serveConfig = (function () { // if dev mode: never cache
// if dev mode: never cache var cacheString = function () {
var cacheString = function () { return (Env.FRESH_KEY? '-' + Env.FRESH_KEY: '') + (Env.DEV_MODE? '-' + (+new Date()): '');
return (Env.FRESH_KEY? '-' + Env.FRESH_KEY: '') + (Env.DEV_MODE? '-' + (+new Date()): ''); };
};
var template = function (host) {
return [
'define(function(){',
'var obj = ' + JSON.stringify({
requireConf: {
waitSeconds: 600,
urlArgs: 'ver=' + Package.version + cacheString(),
},
removeDonateButton: (config.removeDonateButton === true),
allowSubscriptions: (config.allowSubscriptions === true),
websocketPath: config.externalWebsocketURL,
httpUnsafeOrigin: config.httpUnsafeOrigin,
adminEmail: Env.adminEmail,
adminKeys: Env.admins,
inactiveTime: Env.inactiveTime,
supportMailbox: Env.supportMailbox,
defaultStorageLimit: Env.defaultStorageLimit,
maxUploadSize: Env.maxUploadSize,
premiumUploadSize: Env.premiumUploadSize,
}, null, '\t'),
'obj.httpSafeOrigin = ' + (function () {
if (config.httpSafeOrigin) { return '"' + config.httpSafeOrigin + '"'; }
if (config.httpSafePort) {
return "(function () { return window.location.origin.replace(/\:[0-9]+$/, ':" +
config.httpSafePort + "'); }())";
}
return 'window.location.origin';
}()),
'return obj',
'});'
].join(';\n')
};
var makeRouteCache = function (template, cacheName) {
var cleanUp = {}; var cleanUp = {};
var cache = Env[cacheName] = Env[cacheName] || {};
return function (req, res) { return function (req, res) {
var host = req.headers.host.replace(/\:[0-9]+/, ''); var host = req.headers.host.replace(/\:[0-9]+/, '');
@ -255,73 +223,71 @@ var serveConfig = (function () {
// FIXME mutable // FIXME mutable
// we must be able to clear the cache when updating any mutable key // we must be able to clear the cache when updating any mutable key
// if there's nothing cached for that key... // if there's nothing cached for that key...
if (!Env.configCache[cacheKey]) { if (!cache[cacheKey]) {
// generate the response and cache it in memory // generate the response and cache it in memory
Env.configCache[cacheKey] = template(host); cache[cacheKey] = template(host);
// and create a function to conditionally evict cache entries // and create a function to conditionally evict cache entries
// which have not been accessed in the last 20 seconds // which have not been accessed in the last 20 seconds
cleanUp[cacheKey] = Util.throttle(function () { cleanUp[cacheKey] = Util.throttle(function () {
delete cleanUp[cacheKey]; delete cleanUp[cacheKey];
delete Env.configCache[cacheKey]; delete cache[cacheKey];
}, 20000); }, 20000);
} }
// successive calls to this function // successive calls to this function
cleanUp[cacheKey](); cleanUp[cacheKey]();
return void res.send(Env.configCache[cacheKey]); return void res.send(cache[cacheKey]);
};
}());
var serveBroadcast = (function () { // XXX deduplicate
var cacheString = function () {
return (Env.FRESH_KEY? '-' + Env.FRESH_KEY: '') + (Env.DEV_MODE? '-' + (+new Date()): '');
};
var template = function (host) {
var maintenance = Env.maintenance;
if (maintenance && maintenance.end && maintenance.end < (+new Date())) {
maintenance = undefined;
}
return [
'define(function(){', // XXX maybe this could just be JSON
'return ' + JSON.stringify({
lastBroadcastHash: Env.lastBroadcastHash,
surveyURL: Env.surveyURL,
maintenance: maintenance
}, null, '\t'),
'});'
].join(';\n')
}; };
};
var cleanUp = {}; var serveConfig = makeRouteCache(function (host) {
return [
return function (req, res) { 'define(function(){',
var host = req.headers.host.replace(/\:[0-9]+/, ''); 'var obj = ' + JSON.stringify({
res.setHeader('Content-Type', 'text/javascript'); requireConf: {
// don't cache anything if you're in dev mode waitSeconds: 600,
if (Env.DEV_MODE) { urlArgs: 'ver=' + Package.version + cacheString(),
return void res.send(template(host)); },
} removeDonateButton: (config.removeDonateButton === true),
// generate a lookup key for the cache allowSubscriptions: (config.allowSubscriptions === true),
var cacheKey = host + ':' + cacheString(); websocketPath: config.externalWebsocketURL,
httpUnsafeOrigin: config.httpUnsafeOrigin,
// XXX do we need a cache for /api/broadcast? adminEmail: Env.adminEmail,
if (!Env.broadcastCache[cacheKey]) { adminKeys: Env.admins,
// generate the response and cache it in memory inactiveTime: Env.inactiveTime,
Env.broadcastCache[cacheKey] = template(host); supportMailbox: Env.supportMailbox,
// and create a function to conditionally evict cache entries defaultStorageLimit: Env.defaultStorageLimit,
// which have not been accessed in the last 20 seconds maxUploadSize: Env.maxUploadSize,
cleanUp[cacheKey] = Util.throttle(function () { premiumUploadSize: Env.premiumUploadSize,
delete cleanUp[cacheKey]; }, null, '\t'),
delete Env.broadcastCache[cacheKey]; 'obj.httpSafeOrigin = ' + (function () {
}, 20000); if (config.httpSafeOrigin) { return '"' + config.httpSafeOrigin + '"'; }
} if (config.httpSafePort) {
return "(function () { return window.location.origin.replace(/\:[0-9]+$/, ':" +
// successive calls to this function config.httpSafePort + "'); }())";
cleanUp[cacheKey](); }
return void res.send(Env.broadcastCache[cacheKey]); return 'window.location.origin';
}; }()),
}()); 'return obj',
'});'
].join(';\n')
}, 'configCache');
var serveBroadcast = makeRouteCache(function (host) {
var maintenance = Env.maintenance;
if (maintenance && maintenance.end && maintenance.end < (+new Date())) {
maintenance = undefined;
}
return [
'define(function(){',
'return ' + JSON.stringify({
lastBroadcastHash: Env.lastBroadcastHash,
surveyURL: Env.surveyURL,
maintenance: maintenance
}, null, '\t'),
'});'
].join(';\n')
}, 'broadcastCache');
app.get('/api/config', serveConfig); app.get('/api/config', serveConfig);
app.get('/api/broadcast', serveBroadcast); app.get('/api/broadcast', serveBroadcast);

Loading…
Cancel
Save