Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ var logger = require('./src/server/logging').logger;

var ControlService = require('./src/services/control');

ControlService.update(null, function (ok) {
if (!ok) {
ControlService.update(function (err) {
if (err) {
logger.warn('Unable to perform initial control repository load');
}

Expand Down
145 changes: 145 additions & 0 deletions src/control-repo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;

var async = require('async');
var npm = require('npm');

var logger = require('./server/logging').logger;

var NPMInstallInProgress = false;


var NPMUtils = {
getInstance: function (callback) {
return npm.load({}, callback);
},
cleanCache: function (callback) {
logger.debug('Cleaning control repo module from NPM cache', {
moduleName: process.env.CONTROL_REPO_MODULE_NAME
});

this.getInstance(function (err, npm) {
npm.commands.cache(['clean', process.env.CONTROL_REPO_MODULE_NAME], callback);
});
}
};

var RequireUtils = {
cleanCache: function (callback) {
logger.debug('Cleaning control repo and children from CommonJS module cache', {
moduleName: process.env.CONTROL_REPO_MODULE_NAME
});

// Invalidate the cache for the control repo and all of its children
var ControlRepoPath = path.resolve(require.resolve(process.env.CONTROL_REPO_MODULE_NAME), '..');
var controlRepoModulePaths = [ControlRepoPath];

async.waterfall([
function (callback) {
fs.readFile(path.resolve(ControlRepoPath, 'package.json'), 'utf-8', callback);
},
function (file, callback) {
var jsonDocument;
try {
jsonDocument = JSON.parse(file);
} catch (e) {
return callback(e);
}

for(var moduleName in jsonDocument.dependencies) {
controlRepoModulePaths.push(path.resolve(require.resolve(moduleName), '..'));
}

return callback(null);
}
], function (err, result) {
var pathStartsWithAny = function (path, prefixes) {
var match = false;
Array.prototype.forEach.call(prefixes, function (prefix) {
if(path.indexOf(prefix) === 0) {
match = true;
}
});

return match;
};

var modulesToCacheBust = [];
for(var moduleName in require.cache) {
if(pathStartsWithAny(moduleName, controlRepoModulePaths)) {
modulesToCacheBust.push(moduleName);
}
}

logger.debug('Clearing cached control repo modules', {
modules: modulesToCacheBust
});

modulesToCacheBust.forEach(function (module) {
delete require.cache[module];
});

return callback(err);
});
}
};

var ControlRepo = {
loaded: function () {
try {
require.resolve(process.env.CONTROL_REPO_MODULE_NAME);
return true;
} catch (e) {
return false;
}
},
// We want this to be as idempotent as possible
reload: function (callback) {
callback = callback || function () {};
var startTime = Date.now();
logger.debug('Beginning control repo reload', {});

async.waterfall([
function (callback) {
if(NPMInstallInProgress) {
return callback('NPM Install already in progress');
}

NPMInstallInProgress = true;
logger.debug('Running npm install ' + process.env.CONTROL_REPO_MODULE);
var npmInstall = spawn('npm', ['install', process.env.CONTROL_REPO_MODULE]);

npmInstall.on('close', function (code) {
NPMInstallInProgress = false;
if(code !== 0) {
return callback('npm install exited with code ' + code);
}

return callback(null);
});
},
function (callback) {
return RequireUtils.cleanCache(arguments[arguments.length - 1]);
}
], function (err, result) {
if (err) {
logger.warn('Control repo reload aborted', {
error: err,
duration: Date.now() - startTime
});
} else {
logger.debug('Finished control repo reload', {
duration: Date.now() - startTime
});
}

return callback(err, result);
});
},
getInstance: function () {
return require(process.env.CONTROL_REPO_MODULE_NAME);
}
};

module.exports = ControlRepo;
24 changes: 13 additions & 11 deletions src/routers/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,19 @@ module.exports = function (req, res) {
return callback(null, toc.envelope.body);
});
},
control: function (callback) {
ContentService.getControlSHA(context, function (err, sha) {
if (err) return callback(err);

// No need to hold up the current request for the control repository update.
// Kick it off here but don't wait for it to complete.
if (sha && sha !== ControlService.getControlSHA()) ControlService.update(sha);

callback(null, sha);
});
}
// control: function (callback) {
// ContentService.getControlSHA(context, function (err, sha) {
// if (err) return callback(err);
//
// // No need to hold up the current request for the control repository update.
// // Kick it off here but don't wait for it to complete.
// if (sha && sha !== ControlService.getControlSHA()) {
// ControlService.update(sha);
// }
//
// callback(null, sha);
// });
// }
}, function (err, output) {
if (err || capturedError) {
return context.handleError(err || capturedError);
Expand Down
9 changes: 8 additions & 1 deletion src/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ var logging = require('./logging');
var proxies = require('./proxies');
var rewrites = require('./rewrites');
var routes = require('../routers');
var config = require('../config');

var PathService = require('../services/path');

exports.create = function () {
var app = express();

app.use('/assets', express.static(PathService.getAssetPath()));
// Serve assets from the appropriate site in the control repo
app.use('/assets', function (req, res, next) {
var domain = config.presented_url_domain() || req.hostname;
var assetsPath = PathService.getAssetPath(domain);

return express.static(assetsPath).apply(this, arguments);
});

app.use(logging.requestLogger());
app.set('trust proxy', true);
Expand Down
18 changes: 15 additions & 3 deletions src/server/proxies.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ var request = require('request');

function makeProxyRoute (site, path, target) {
return function (req, res, next) {
var host = config.presented_url_domain() || req.get('Host');
if (host !== site) {
return next();
if(site) {
var host = config.presented_url_domain() || req.get('Host');
if (host !== site) {
return next();
}
}

var suffix = url.parse(req.originalUrl).path.replace(path, '');
Expand All @@ -24,6 +26,16 @@ function makeProxyRoute (site, path, target) {
module.exports = function (app) {
var proxies = ContentRoutingService.getAllProxies();

// This __local_asset__ path is returned when the content service is memory-backed.
// This little patch probably belongs over there, but I'm here right now so
// this will do for now.
// See also: https://github.com/deconst/content-service/issues/66
app.use('/__local_asset__', makeProxyRoute(
null,
'__local_asset__/',
url.resolve(config.content_service_url(), '/assets')
));

proxies.forEach(function (each) {
for (var path in each.proxy) {
app.use(path + '*', makeProxyRoute(each.site, path, each.proxy[path]));
Expand Down
Loading