From 5f9c95ed69768dbd8de915af06cfcdacf3b22767 Mon Sep 17 00:00:00 2001 From: Lloyd Hilaiel <lloyd@hilaiel.com> Date: Tue, 2 Aug 2011 06:19:46 -0600 Subject: [PATCH] erect a simple mechanism for deployment environment specific configuration --- browserid/app.js | 25 ++++++++----- browserid/run.js | 1 + libs/environment.js | 85 ++++++++++++++++++++++++++++++++++++++++++ run.js | 91 +++++++++++++++++++++------------------------ 4 files changed, 144 insertions(+), 58 deletions(-) create mode 100644 libs/environment.js diff --git a/browserid/app.js b/browserid/app.js index 6224de3f4..bef67d256 100644 --- a/browserid/app.js +++ b/browserid/app.js @@ -15,11 +15,12 @@ webfinger = require('./lib/webfinger.js'), sessions = require('cookie-sessions'), express = require('express'), secrets = require('./lib/secrets.js'), -db = require('./lib/db.js') +db = require('./lib/db.js'), +environment = require('../libs/environment.js'), +substitution = require('../libs/substitute.js'); // looks unused, see run.js // const STATIC_DIR = path.join(path.dirname(__dirname), "static"); - const COOKIE_SECRET = secrets.hydrateSecret('cookie_secret', VAR_DIR); const COOKIE_KEY = 'browserid_state'; @@ -33,7 +34,9 @@ function internal_redirector(new_url) { function router(app) { app.set("views", __dirname + '/views'); - app.set('view options', { production: exports.production }); + app.set('view options', { + production: app.enabled('use_minified_resources') + }); // this should probably be an internal redirect // as soon as relative paths are figured out. @@ -41,7 +44,7 @@ function router(app) { res.render('dialog.ejs', { title: 'A Better Way to Sign In', layout: false, - production: exports.production + production: app.enabled('use_minified_resources') }); }); @@ -109,9 +112,6 @@ function router(app) { }; exports.varDir = VAR_DIR; -exports.production = true; - - exports.setup = function(server) { server.use(express.cookieParser()); @@ -144,7 +144,7 @@ exports.setup = function(server) { // not awesome, but probably sufficient for now. req.session.csrf = crypto.createHash('md5').update('' + new Date().getTime()).digest('hex'); } - + next(); }); @@ -172,8 +172,15 @@ exports.setup = function(server) { } } - next(); + next(); }); + + // configure environment variables based on the deployment target ('NODE_ENV'); + environment.configure(server); + + // add middleware to re-write urls if needed + environment.performSubstitution(server); + // add the actual URL handlers other than static router(server); } diff --git a/browserid/run.js b/browserid/run.js index 94f0583de..ed8b03dbe 100755 --- a/browserid/run.js +++ b/browserid/run.js @@ -42,3 +42,4 @@ exports.stopServer = function(cb) { // when directly invoked from the command line, we'll start the server if (amMain) exports.runServer(); + diff --git a/libs/environment.js b/libs/environment.js new file mode 100644 index 000000000..3bbfec25b --- /dev/null +++ b/libs/environment.js @@ -0,0 +1,85 @@ +/* + * An abstraction which contains various pre-set deployment + * environments and adjusts runtime configuration appropriate for + * the current environmnet (specified via the NODE_ENV env var).. + * + * usage is + * exports.configure(app); + */ + +const substitution = require('./substitute.js'); + +if (undefined === process.env['NODE_ENV']) { + process.env['NODE_ENV'] = 'local'; +} + +exports.configure = function(app) { + if (!app) throw "configure requires express app as argument"; + + var known = false; + + app.enable('use_minified_resources'); + + app.configure('production', function() { + app.set('hostname', 'browserid.org'); + app.set('port', '443'); + app.set('scheme', 'https'); + known = true; + }); + + app.configure('development', function() { + app.set('hostname', 'dev.diresworb.org'); + app.set('port', '443'); + app.set('scheme', 'https'); + known = true; + }); + + app.configure('beta', function() { + app.set('hostname', 'diresworb.org'); + app.set('port', '443'); + app.set('scheme', 'https'); + known = true; + }); + + app.configure('local', function() { + app.set('hostname', '127.0.0.1'); + app.set('port', '10001'); + app.set('scheme', 'http'); + app.disable('use_minified_resources'); + known = true; + }); + + if (!known) throw "unknown environment: " + process.env('NODE_ENV'); + + function getPortForURL() { + if (app.set('scheme') === 'https' && app.set('port') === '443') return ""; + if (app.set('scheme') === 'http' && app.set('port') === '80') return ""; + return ":" + app.set('port'); + } + + app.set('URL', + app.set('scheme') + + '://' + + app.set('hostname') + + getPortForURL()); +}; + +/* + * Install middleware that will perform textual replacement on served output + * to re-write urls as needed for this particular environment. + * + * Note, for a 'local' environment, no re-write is needed because this is + * handled at a higher level. For a 'production' env no rewrite is necc cause + * all source files are written for that environment. + */ +exports.performSubstitution = function(app) { + if (process.env['NODE_ENV'] !== 'production' && + process.env['NODE_ENV'] !== 'local') { + app.use(substitution.substitute({ + 'https://browserid.org': app.set('URL'), + 'browserid.org:443': app.set('hostname') + ':' + app.set('port'), + 'browserid.org': app.set('hostname') + })); + } +}; + diff --git a/run.js b/run.js index 7f7654451..95046e55d 100755 --- a/run.js +++ b/run.js @@ -8,7 +8,8 @@ var sys = require("sys"), path = require("path"), fs = require("fs"), express = require("express"), -substitution = require('./libs/substitute.js'); +substitution = require('./libs/substitute.js'), + environment = require('./libs/environment.js'); var PRIMARY_HOST = "127.0.0.1"; @@ -58,58 +59,54 @@ function substitutionMiddleware(req, resp, next) { (substitution.substitute(subs))(req, resp, next); } - function createServer(obj) { - var app = express.createServer(); - app.use(express.logger()); + var app = express.createServer(); + + // configure the server based on the environment (NODE_ENV). + environment.configure(app); + + app.use(express.logger()); - // this file is a *test* harness, to make it go, we'll insert a little handler that - // substitutes output, changing production URLs to developement URLs. - app.use(substitutionMiddleware); + // this file is a *test* harness, to make it go, we'll insert a little + // handler that substitutes output, changing production URLs to + // developement URLs. + app.use(substitutionMiddleware); - // let the specific server interact directly with the express server to register their middleware, - // routes, etc... - if (obj.setup) obj.setup(app); + // let the specific server interact directly with the express server to + // register their middleware, routes, etc... + if (obj.setup) obj.setup(app); - // now set up the static resource servin' - var p = obj.path, ps = path.join(p, "static"); - try { if (fs.statSync(ps).isDirectory()) p = ps; } catch(e) { } - app.use(express.static(p)); + // now set up the static resource servin' + var p = obj.path, ps = path.join(p, "static"); + try { if (fs.statSync(ps).isDirectory()) p = ps; } catch(e) { } + app.use(express.static(p)); - // and listen! - app.listen(obj.port, PRIMARY_HOST); - return app; + // and listen! + app.listen(obj.port, PRIMARY_HOST); + return app; }; // start up webservers on ephemeral ports for each subdirectory here. var dirs = [ - // the reference verification server. A version is hosted at - // browserid.org and may be used, or the RP may perform their - // own verification. - { - name: "https://browserid.org/verify", - subPath: "/", - path: path.join(__dirname, "verifier") - }, - // An example relying party. - { - name: "http://rp.eyedee.me", - path: path.join(__dirname, "rp") - }, - - // disabled primary for now since it's not in working - // order. - /* // A reference primary identity provider. - { - name: "https://eyedee.me", - path: path.join(__dirname, "primary") - }, */ - - // BrowserID: the secondary + ip + more. - { - name: "https://browserid.org", - path: path.join(__dirname, "browserid") - } + // the reference verification server. A version is hosted at + // browserid.org and may be used, or the RP may perform their + // own verification. + { + name: "https://browserid.org/verify", + subPath: "/", + path: path.join(__dirname, "verifier") + }, + // An example relying party. + { + name: "http://rp.eyedee.me", + path: path.join(__dirname, "rp") + }, + + // BrowserID: the secondary + ip + more. + { + name: "https://browserid.org", + path: path.join(__dirname, "browserid") + } ]; function formatLink(server, extraPath) { @@ -132,11 +129,7 @@ dirs.forEach(function(dirObj) { try { var runJSExists = false; try { runJSExists = fs.statSync(handlerPath).isFile() } catch(e) {}; - if (runJSExists) { - var runJS = require(handlerPath); - // set to development mode - runJS.production = false; - } + if (runJSExists) runJS = require(handlerPath); } catch(e) { console.log("Error loading " + handlerPath + ": " + e); process.exit(1); -- GitLab