reworking vhost routes
This commit is contained in:
parent
dd8f8b426f
commit
1bb21f5a07
|
@ -3,6 +3,7 @@
|
||||||
var cluster = require('cluster');
|
var cluster = require('cluster');
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
var memstore;
|
var memstore;
|
||||||
|
var sqlstore;
|
||||||
// TODO
|
// TODO
|
||||||
// var rootMasterKey;
|
// var rootMasterKey;
|
||||||
|
|
||||||
|
@ -26,24 +27,24 @@ function init(conf/*, state*/) {
|
||||||
if (!conf.ipcKey) {
|
if (!conf.ipcKey) {
|
||||||
conf.ipcKey = require('crypto').randomBytes(16).toString('base64');
|
conf.ipcKey = require('crypto').randomBytes(16).toString('base64');
|
||||||
}
|
}
|
||||||
|
if (!conf.sqlite3Sock) {
|
||||||
|
conf.sqlite3Sock = '/tmp/sqlite3.' + require('crypto').randomBytes(4).toString('hex') + '.sock';
|
||||||
|
}
|
||||||
|
if (!conf.memstoreSock) {
|
||||||
|
conf.memstoreSock = '/tmp/memstore.' + require('crypto').randomBytes(4).toString('hex') + '.sock';
|
||||||
|
}
|
||||||
|
|
||||||
var memstoreOpts = {
|
|
||||||
sock: conf.memstoreSock || '/tmp/memstore.sock'
|
|
||||||
|
|
||||||
// If left 'null' or 'undefined' this defaults to a similar memstore
|
|
||||||
// with no special logic for 'cookie' or 'expires'
|
|
||||||
, store: cluster.isMaster && null //new require('express-session/session/memory')()
|
|
||||||
|
|
||||||
// a good default to use for instances where you might want
|
|
||||||
// to cluster or to run standalone, but with the same API
|
|
||||||
, serve: cluster.isMaster
|
|
||||||
, connect: cluster.isWorker
|
|
||||||
//, standalone: (1 === numCores) // overrides serve and connect
|
|
||||||
// TODO implement
|
|
||||||
, key: conf.ipcKey
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
require('fs').unlinkSync(memstoreOpts.sock);
|
require('fs').unlinkSync(conf.memstoreSock);
|
||||||
|
} catch(e) {
|
||||||
|
if ('ENOENT' !== e.code) {
|
||||||
|
console.error(e.stack);
|
||||||
|
console.error(JSON.stringify(e));
|
||||||
|
}
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
require('fs').unlinkSync(conf.sqlite3Sock);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if ('ENOENT' !== e.code) {
|
if ('ENOENT' !== e.code) {
|
||||||
console.error(e.stack);
|
console.error(e.stack);
|
||||||
|
@ -53,8 +54,35 @@ function init(conf/*, state*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cstore = require('cluster-store');
|
var cstore = require('cluster-store');
|
||||||
var memstorePromise = cstore.create(memstoreOpts).then(function (_memstore) {
|
var sqlite3 = require('sqlite3-cluster/server');
|
||||||
memstore = _memstore;
|
var promise = PromiseA.all([
|
||||||
|
cstore.create({
|
||||||
|
sock: conf.memstoreSock
|
||||||
|
, serve: cluster.isMaster && conf.memstoreSock
|
||||||
|
, store: cluster.isMaster && null //new require('express-session/session/memory')()
|
||||||
|
// TODO implement
|
||||||
|
, key: conf.ipcKey
|
||||||
|
}).then(function (_memstore) {
|
||||||
|
memstore = _memstore;
|
||||||
|
return memstore;
|
||||||
|
})
|
||||||
|
, sqlite3.createServer({
|
||||||
|
verbose: null
|
||||||
|
, sock: conf.sqlite3Sock
|
||||||
|
, ipcKey: conf.ipcKey
|
||||||
|
}).then(function (_sqlstore) {
|
||||||
|
sqlstore = _sqlstore;
|
||||||
|
return sqlstore;
|
||||||
|
})
|
||||||
|
]).then(function (/*args*/) {
|
||||||
|
return conf;
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
conf: conf
|
||||||
|
, memstore: memstore // args[0]
|
||||||
|
, sqlstore: sqlstore // args[1]
|
||||||
|
};
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO check the IP every 5 minutes and update it every hour
|
// TODO check the IP every 5 minutes and update it every hour
|
||||||
|
@ -62,7 +90,7 @@ function init(conf/*, state*/) {
|
||||||
// we don't want this to load right away (extra procesing time)
|
// we don't want this to load right away (extra procesing time)
|
||||||
setTimeout(updateIps, 1);
|
setTimeout(updateIps, 1);
|
||||||
|
|
||||||
return memstorePromise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function touch(conf, state) {
|
function touch(conf, state) {
|
||||||
|
@ -88,6 +116,7 @@ function touch(conf, state) {
|
||||||
//var config = require('./device.json');
|
//var config = require('./device.json');
|
||||||
|
|
||||||
// require('ssl-root-cas').inject();
|
// require('ssl-root-cas').inject();
|
||||||
|
// TODO try SNI loopback.example.com as result of api.ipify.com with loopback token
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function phoneHome() {
|
function phoneHome() {
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function deserialize(results) {
|
||||||
|
var config = { apis: {}, apps: {}, domains: {} };
|
||||||
|
results.apis.forEach(function (api) {
|
||||||
|
config.apis[api.id] = api;
|
||||||
|
api.domains = [];
|
||||||
|
api.domainIds = [];
|
||||||
|
api.domainsMap = {};
|
||||||
|
});
|
||||||
|
results.apps.forEach(function (app) {
|
||||||
|
config.apps[app.id] = app;
|
||||||
|
app.domains = [];
|
||||||
|
app.domainIds = [];
|
||||||
|
app.domainsMap = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
results.domains.forEach(function (domain) {
|
||||||
|
config.domains[domain.id] = domain;
|
||||||
|
// as it currently stands each of these will only have one
|
||||||
|
/*
|
||||||
|
domain.apis = [];
|
||||||
|
domain.apiIds = [];
|
||||||
|
domain.apisMap = {};
|
||||||
|
domain.apps = [];
|
||||||
|
domain.appIds = [];
|
||||||
|
domain.appsMap = {};
|
||||||
|
*/
|
||||||
|
domain.api = null;
|
||||||
|
domain.apiId = null;
|
||||||
|
domain.app = null;
|
||||||
|
domain.appId = null;
|
||||||
|
domain.appsMap = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
results.apisDomains.forEach(function (ad) {
|
||||||
|
var api = config.apis[ad.apiId];
|
||||||
|
var domain = config.domains[ad.domainId];
|
||||||
|
if (api && !api.domainsMap[domain.id]) {
|
||||||
|
api.domainIds.push(domain.id);
|
||||||
|
api.domainsMap[domain.id] = domain;
|
||||||
|
api.domains.push(domain);
|
||||||
|
}
|
||||||
|
if (domain) {
|
||||||
|
if (domain.api) {
|
||||||
|
console.error("[SANITY FAIL] single domain has multiple frontends in db: '" + domain.id + "'");
|
||||||
|
}
|
||||||
|
domain.apiId = api.id;
|
||||||
|
domain.api = api;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
results.appsDomains.forEach(function (ad) {
|
||||||
|
var app = config.apps[ad.appId];
|
||||||
|
var domain = config.domains[ad.domainId];
|
||||||
|
if (app && !app.domainsMap[domain.id]) {
|
||||||
|
app.domainIds.push(domain.id);
|
||||||
|
app.domainsMap[domain.id] = domain;
|
||||||
|
app.domains.push(domain);
|
||||||
|
}
|
||||||
|
if (domain) {
|
||||||
|
if (domain.app) {
|
||||||
|
console.error("[SANITY FAIL] single domain has multiple frontends in db: '" + domain.id + "'");
|
||||||
|
}
|
||||||
|
domain.appId = app.id;
|
||||||
|
domain.app = app;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.deserialize = deserialize;
|
||||||
|
module.exports.create = function (db) {
|
||||||
|
console.log('[DB -1]');
|
||||||
|
var wrap = require('dbwrap');
|
||||||
|
|
||||||
|
var dir = [
|
||||||
|
//
|
||||||
|
// Collections
|
||||||
|
//
|
||||||
|
{ tablename: 'apis'
|
||||||
|
, idname: 'id' // io.lds.auth, com.daplie.radio
|
||||||
|
, unique: ['id']
|
||||||
|
// name // LDS Account, Radio
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'revokedAt', 'name']
|
||||||
|
}
|
||||||
|
, { tablename: 'apps'
|
||||||
|
, idname: 'id' // io.lds.auth, com.daplie.radio
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'revokedAt', 'name']
|
||||||
|
}
|
||||||
|
, { tablename: 'domains'
|
||||||
|
, idname: 'id' // api.coolaj86.com#radio
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'revokedAt', 'name', 'token', 'accountId']
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Joins
|
||||||
|
//
|
||||||
|
, { tablename: 'apis_domains'
|
||||||
|
, idname: 'id' // hash(api_id + domain_id)
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'apiId', 'domainId']
|
||||||
|
// TODO auto-form relations
|
||||||
|
, hasMany: ['apis', 'domains']
|
||||||
|
}
|
||||||
|
, { tablename: 'apps_domains'
|
||||||
|
, idname: 'id' // hash(domain_id + app_id)
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'appId', 'domainId']
|
||||||
|
// TODO auto-form relations
|
||||||
|
, hasMany: ['apps', 'domains']
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
, { tablename: 'accounts_apis'
|
||||||
|
, idname: 'id' // hash(account_id + api_id)
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'accountId', 'apiId']
|
||||||
|
// TODO auto-form relations
|
||||||
|
, hasMany: ['accounts', 'apis']
|
||||||
|
}
|
||||||
|
, { tablename: 'accounts_domains'
|
||||||
|
, idname: 'id' // hash(account_id + domain_id)
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'accountId', 'domainId']
|
||||||
|
// TODO auto-form relations
|
||||||
|
, hasMany: ['accounts', 'domains']
|
||||||
|
}
|
||||||
|
, { tablename: 'accounts_apps'
|
||||||
|
, idname: 'id' // hash(account_id + static_id)
|
||||||
|
, unique: ['id']
|
||||||
|
, indices: ['createdAt', 'updatedAt', 'deletedAt', 'accountId', 'staticId']
|
||||||
|
// TODO auto-form relations
|
||||||
|
, hasMany: ['accounts', 'apps']
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
];
|
||||||
|
|
||||||
|
return wrap.wrap(db, dir).then(function (models) {
|
||||||
|
models.Config = {
|
||||||
|
get: function () {
|
||||||
|
var PromiseA = require('bluebird');
|
||||||
|
|
||||||
|
return PromiseA.all([
|
||||||
|
models.Apis.find(null, { limit: 10000 })
|
||||||
|
, models.Apps.find(null, { limit: 10000 })
|
||||||
|
, models.Domains.find(null, { limit: 10000 })
|
||||||
|
, models.ApisDomains.find(null, { limit: 10000 })
|
||||||
|
, models.AppsDomains.find(null, { limit: 10000 })
|
||||||
|
]).then(function (args) {
|
||||||
|
var results = {
|
||||||
|
apis: args[0]
|
||||||
|
, apps: args[1]
|
||||||
|
, domains: args[2]
|
||||||
|
, apisDomains: args[3]
|
||||||
|
, appsDomains: args[4]
|
||||||
|
};
|
||||||
|
|
||||||
|
// create fixture with which to test
|
||||||
|
// console.log(JSON.stringify(results));
|
||||||
|
|
||||||
|
var config = deserialize(results);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return models;
|
||||||
|
});
|
||||||
|
};
|
|
@ -3,7 +3,7 @@
|
||||||
module.exports.getDomainInfo = function (apppath) {
|
module.exports.getDomainInfo = function (apppath) {
|
||||||
var parts = apppath.split(/[#%]+/);
|
var parts = apppath.split(/[#%]+/);
|
||||||
var hostname = parts.shift();
|
var hostname = parts.shift();
|
||||||
var pathname = parts.join('/').replace(/\/+/g, '/').replace(/^\//, '');
|
var pathname = parts.join('/').replace(/\/+/g, '/').replace(/\/$/g, '').replace(/^\//g, '');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hostname: hostname
|
hostname: hostname
|
||||||
|
|
|
@ -1,10 +1,40 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports.create = function (webserver, info) {
|
module.exports.create = function (webserver, info, state) {
|
||||||
|
if (!state) {
|
||||||
|
state = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var PromiseA = state.Promise || require('bluebird');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var vhostsdir = path.join(__dirname, 'vhosts');
|
var vhostsdir = path.join(__dirname, 'vhosts');
|
||||||
var app = require('express')();
|
var app = require('express')();
|
||||||
var apiHandler;
|
var apiHandler;
|
||||||
|
var memstore;
|
||||||
|
var sqlstores = {};
|
||||||
|
var models = {};
|
||||||
|
var systemFactory = require('sqlite3-cluster/client').createClientFactory({
|
||||||
|
dirname: path.join(__dirname, '..', 'var') // TODO info.conf
|
||||||
|
, prefix: 'com.daplie.'
|
||||||
|
//, dbname: 'config'
|
||||||
|
, suffix: ''
|
||||||
|
, ext: '.sqlite3'
|
||||||
|
, sock: info.conf.sqlite3Sock
|
||||||
|
, ipcKey: info.conf.ipcKey
|
||||||
|
});
|
||||||
|
var clientFactory = require('sqlite3-cluster/client').createClientFactory({
|
||||||
|
algorithm: 'aes'
|
||||||
|
, bits: 128
|
||||||
|
, mode: 'cbc'
|
||||||
|
, dirname: path.join(__dirname, '..', 'var') // TODO info.conf
|
||||||
|
, prefix: 'com.daplie.'
|
||||||
|
//, dbname: 'cluster'
|
||||||
|
, suffix: ''
|
||||||
|
, ext: '.sqlcipher'
|
||||||
|
, sock: info.conf.sqlite3Sock
|
||||||
|
, ipcKey: info.conf.ipcKey
|
||||||
|
});
|
||||||
|
var cstore = require('cluster-store');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function unlockDevice(conf, state) {
|
function unlockDevice(conf, state) {
|
||||||
|
@ -58,6 +88,11 @@ module.exports.create = function (webserver, info) {
|
||||||
res.end(metaRedirect);
|
res.end(metaRedirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO handle insecure to actual redirect
|
||||||
|
// blog.coolaj86.com -> coolaj86.com/blog
|
||||||
|
// hmm... that won't really matter with hsts
|
||||||
|
// I guess I just needs letsencrypt
|
||||||
|
|
||||||
function scrubTheDub(req, res, next) {
|
function scrubTheDub(req, res, next) {
|
||||||
var host = req.hostname;
|
var host = req.hostname;
|
||||||
|
|
||||||
|
@ -115,5 +150,55 @@ module.exports.create = function (webserver, info) {
|
||||||
app.use('/', scrubTheDub);
|
app.use('/', scrubTheDub);
|
||||||
app.use('/', handleApi);
|
app.use('/', handleApi);
|
||||||
|
|
||||||
return app;
|
return PromiseA.all([
|
||||||
|
cstore.create({
|
||||||
|
sock: info.conf.memstoreSock
|
||||||
|
, connect: info.conf.memstoreSock
|
||||||
|
// TODO implement
|
||||||
|
, key: info.conf.ipcKey
|
||||||
|
}).then(function (_memstore) {
|
||||||
|
memstore = _memstore;
|
||||||
|
return memstore;
|
||||||
|
})
|
||||||
|
// TODO mark a device as lost, stolen, missing in DNS records
|
||||||
|
// (and in turn allow other devices to lock it, turn on location reporting, etc)
|
||||||
|
, systemFactory.create({
|
||||||
|
init: true
|
||||||
|
, dbname: 'config'
|
||||||
|
})
|
||||||
|
, clientFactory.create({
|
||||||
|
init: true
|
||||||
|
, key: '00000000000000000000000000000000'
|
||||||
|
// TODO only complain if the values are different
|
||||||
|
//, algo: 'aes'
|
||||||
|
, dbname: 'auth'
|
||||||
|
})
|
||||||
|
, clientFactory.create({
|
||||||
|
init: false
|
||||||
|
, dbname: 'system'
|
||||||
|
})
|
||||||
|
]).then(function (args) {
|
||||||
|
memstore = args[0];
|
||||||
|
sqlstores.config = args[1];
|
||||||
|
sqlstores.auth = args[2];
|
||||||
|
sqlstores.system = args[3];
|
||||||
|
sqlstores.create = clientFactory.create;
|
||||||
|
|
||||||
|
return require('../lib/schemes-config').create(sqlstores.config).then(function (tables) {
|
||||||
|
models.Config = tables;
|
||||||
|
models.Config.Config.get().then(function (circ) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
// todo getDomainInfo
|
||||||
|
var utils = require('./utils');
|
||||||
|
results.domains.forEach(function (domain) {
|
||||||
|
utils.getDomainInfo(domain.id);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
console.log(circ);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ console.log('\n\n\n[MASTER] Welcome to WALNUT!');
|
||||||
var cluster = require('cluster');
|
var cluster = require('cluster');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var minWorkers = 2;
|
var minWorkers = 2;
|
||||||
var numCores = Math.max(minWorkers, require('os').cpus().length);
|
var numCores = 1; // Math.max(minWorkers, require('os').cpus().length);
|
||||||
var workers = [];
|
var workers = [];
|
||||||
var caddypath = '/usr/local/bin/caddy';
|
var caddypath = '/usr/local/bin/caddy';
|
||||||
var useCaddy = require('fs').existsSync(caddypath);
|
var useCaddy = require('fs').existsSync(caddypath);
|
||||||
|
@ -75,6 +75,8 @@ cluster.on('online', function (worker) {
|
||||||
require('./lib/master').touch(conf, state).then(function () {
|
require('./lib/master').touch(conf, state).then(function () {
|
||||||
info.type = 'com.daplie.walnut.webserver.onrequest';
|
info.type = 'com.daplie.walnut.webserver.onrequest';
|
||||||
info.conf.ipcKey = conf.ipcKey;
|
info.conf.ipcKey = conf.ipcKey;
|
||||||
|
info.conf.memstoreSock = conf.memstoreSock;
|
||||||
|
info.conf.sqlite3Sock = conf.sqlite3Sock;
|
||||||
worker.send(info);
|
worker.send(info);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -93,7 +95,8 @@ cluster.on('exit', function (worker, code, signal) {
|
||||||
return w;
|
return w;
|
||||||
});
|
});
|
||||||
|
|
||||||
fork();
|
console.log('WARNING: worker spawning turned off for debugging ');
|
||||||
|
//fork();
|
||||||
});
|
});
|
||||||
|
|
||||||
fork();
|
fork();
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
"ms": "^0.7.0",
|
"ms": "^0.7.0",
|
||||||
"negotiator": "^0.5.1",
|
"negotiator": "^0.5.1",
|
||||||
"node-pre-gyp": "^0.6.4",
|
"node-pre-gyp": "^0.6.4",
|
||||||
"node-uuid": "1.x",
|
"node-uuid": "^1.4.4",
|
||||||
"nodemailer": "^1.4.0",
|
"nodemailer": "^1.4.0",
|
||||||
"nodemailer-mailgun-transport": "1.x",
|
"nodemailer-mailgun-transport": "1.x",
|
||||||
"oauth": "0.9.x",
|
"oauth": "0.9.x",
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// var results = {"apis":[{"id":"oauth3-api","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"json":null}],"apps":[{"id":"oauth3-app","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"json":null},{"id":"hellabit-app","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"json":null},{"id":"ldsio-app","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"json":null},{"id":"ldsconnect-app","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"json":null}],"domains":[{"id":"oauth3.org","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"token":null,"accountId":null,"json":null},{"id":"lds.io","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"token":null,"accountId":null,"json":null},{"id":"ldsconnect.org","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"token":null,"accountId":null,"json":null},{"id":"hellabit.com","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"token":null,"accountId":null,"json":null},{"id":"hellabit.com#connect","createdAt":null,"updatedAt":null,"deletedAt":null,"revokedAt":null,"name":null,"token":null,"accountId":null,"json":null}],"apisDomains":[{"id":"oauth3-api_oauth3.org","createdAt":null,"updatedAt":null,"deletedAt":null,"apiId":"oauth3-api","domainId":"oauth3.org","json":null}],"appsDomains":[{"id":"oauth3-app_oauth3.org","createdAt":null,"updatedAt":null,"deletedAt":null,"appId":"oauth3-app","domainId":"oauth3.org","json":null},{"id":"hellabit-app_hellabit.com","createdAt":null,"updatedAt":null,"deletedAt":null,"appId":"hellabit-app","domainId":"hellabit.com","json":null},{"id":"ldsio-app_lds.io","createdAt":null,"updatedAt":null,"deletedAt":null,"appId":"ldsio-app","domainId":"lds.io","json":null},{"id":"ldsconnect-app_ldsconnect.org","createdAt":null,"updatedAt":null,"deletedAt":null,"appId":"ldsconnect-app","domainId":"ldsconnect.org","json":null}]};
|
||||||
|
var results = {
|
||||||
|
"apis":[
|
||||||
|
{"id":"oauth3-api"}
|
||||||
|
]
|
||||||
|
, "apps":[
|
||||||
|
{"id":"oauth3-app"}
|
||||||
|
, {"id":"hellabit-app"}
|
||||||
|
, {"id":"ldsio-app"}
|
||||||
|
, {"id":"ldsconnect-app"}
|
||||||
|
]
|
||||||
|
, "domains":[
|
||||||
|
{"id":"oauth3.org"}
|
||||||
|
, {"id":"lds.io"}
|
||||||
|
, {"id":"ldsconnect.org"}
|
||||||
|
, {"id":"hellabit.com#####"}
|
||||||
|
, {"id":"hellabit.com"}
|
||||||
|
, {"id":"hellabit.com###"}
|
||||||
|
, {"id":"hellabit.com#connect###"}
|
||||||
|
, {"id":"hellabit.com#connect"}
|
||||||
|
, {"id":"hellabit.com#connect#too"}
|
||||||
|
]
|
||||||
|
, "apisDomains":[
|
||||||
|
{"id":"oauth3-api_oauth3.org","apiId":"oauth3-api","domainId":"oauth3.org"}
|
||||||
|
]
|
||||||
|
,"appsDomains":[
|
||||||
|
{"id":"oauth3-app_oauth3.org","appId":"oauth3-app","domainId":"oauth3.org"}
|
||||||
|
, {"id":"hellabit-app_hellabit.com","appId":"hellabit-app","domainId":"hellabit.com"}
|
||||||
|
, {"id":"hellabit-app_hellabit.com###","appId":"hellabit-app","domainId":"hellabit.com#connect###"}
|
||||||
|
, {"id":"ldsio-app_lds.io","appId":"ldsio-app","domainId":"lds.io"}
|
||||||
|
, {"id":"ldsconnect-app_ldsconnect.org","appId":"ldsconnect-app","domainId":"ldsconnect.org"}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
var deserialize = require('../lib/schemes-config').deserialize;
|
||||||
|
var getDomainInfo = require('../lib/utils').getDomainInfo;
|
||||||
|
var config = deserialize(results);
|
||||||
|
var req = { host: 'hellabit.com', url: '/connect' };
|
||||||
|
var vhosts = [];
|
||||||
|
var vhostsMap = {};
|
||||||
|
|
||||||
|
function sortApps(a, b) {
|
||||||
|
// hlen isn't important in this current use of the sorter,
|
||||||
|
// but is important for an alternate version
|
||||||
|
var hlen = b.hostname.length - a.hostname.length;
|
||||||
|
var plen = b.pathname.length - a.pathname.length;
|
||||||
|
|
||||||
|
// A directory could be named example.com, example.com# example.com##
|
||||||
|
// to indicate order of preference (for API addons, for example)
|
||||||
|
var dlen = (b.priority || b.dirname.length) - (a.priority || a.dirname.length);
|
||||||
|
|
||||||
|
if (!hlen) {
|
||||||
|
if (!plen) {
|
||||||
|
return dlen;
|
||||||
|
}
|
||||||
|
return plen;
|
||||||
|
}
|
||||||
|
return hlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(config.domains).forEach(function (domainname) {
|
||||||
|
var domain = config.domains[domainname];
|
||||||
|
var info = getDomainInfo(domainname);
|
||||||
|
|
||||||
|
domain.hostname = info.hostname;
|
||||||
|
domain.pathname = '/' + (info.pathname || '');
|
||||||
|
domain.dirname = info.dirname;
|
||||||
|
|
||||||
|
vhosts.push(domain);
|
||||||
|
});
|
||||||
|
|
||||||
|
vhosts.sort(sortApps);
|
||||||
|
|
||||||
|
vhosts.forEach(function (domain) {
|
||||||
|
console.log(domain.hostname, domain.pathname, domain.dirname);
|
||||||
|
|
||||||
|
if (!vhostsMap[domain.hostname]) {
|
||||||
|
vhostsMap[domain.hostname] = { pathnamesMap: {}, pathnames: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vhostsMap[domain.hostname].pathnamesMap[domain.pathname]) {
|
||||||
|
vhostsMap[domain.hostname].pathnamesMap[domain.pathname] = { pathname: domain.pathname, apps: [] };
|
||||||
|
vhostsMap[domain.hostname].pathnames.push(vhostsMap[domain.hostname].pathnamesMap[domain.pathname]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vhostsMap[domain.hostname].pathnamesMap[domain.pathname].apps.push(domain);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!vhostsMap[req.host]) {
|
||||||
|
console.log("there's no app for this hostname");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log("load an app", vhosts[req.host]);
|
||||||
|
|
||||||
|
//console.log(vhosts[req.host]);
|
||||||
|
|
||||||
|
|
||||||
|
function getApp(route) {
|
||||||
|
var PromiseA = require('bluebird');
|
||||||
|
|
||||||
|
return new PromiseA(function (resolve, reject) {
|
||||||
|
console.log(route);
|
||||||
|
// route.hostname
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function api(req, res, next) {
|
||||||
|
var apps;
|
||||||
|
|
||||||
|
vhostsMap[req.host].pathnames.some(function (route) {
|
||||||
|
// /connect /
|
||||||
|
if (req.url.match(route.pathname) && route.pathname.match(req.url)) {
|
||||||
|
apps = route.apps;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//console.log(apps);
|
||||||
|
|
||||||
|
function nextify(err) {
|
||||||
|
var route;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
next(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shortest to longest
|
||||||
|
//route = apps.pop();
|
||||||
|
// longest to shortest
|
||||||
|
route = apps.shift();
|
||||||
|
if (!route) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route.route) {
|
||||||
|
route.route(req, res, nextify);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getApp(route).then(function (route) {
|
||||||
|
route.route = route;
|
||||||
|
try {
|
||||||
|
route.route(req, res, nextify);
|
||||||
|
} catch(e) {
|
||||||
|
console.error('[App Load Error]');
|
||||||
|
console.error(e.stack);
|
||||||
|
nextify(new Error("couldn't load app"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
nextify();
|
||||||
|
}
|
||||||
|
|
||||||
|
api(req);
|
17
walnut.js
17
walnut.js
|
@ -2,6 +2,23 @@
|
||||||
|
|
||||||
var cluster = require('cluster');
|
var cluster = require('cluster');
|
||||||
|
|
||||||
|
var crypto;
|
||||||
|
var stacks = {};
|
||||||
|
Math.random = function () {
|
||||||
|
var err = new Error("Math.random() was used");
|
||||||
|
|
||||||
|
if (!stacks[err.stack.toString()]) {
|
||||||
|
stacks[err.stack.toString()] = true;
|
||||||
|
console.warn(err.stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!crypto) {
|
||||||
|
crypto = require('crypto');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseFloat(('0.' + (parseInt(crypto.randomBytes(8).toString('hex'), 16))).replace(/(^0)|(0$)/g, ''));
|
||||||
|
};
|
||||||
|
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
require('./master');
|
require('./master');
|
||||||
} else {
|
} else {
|
||||||
|
|
15
worker.js
15
worker.js
|
@ -5,8 +5,8 @@ var id = cluster.worker.id.toString();
|
||||||
|
|
||||||
function waitForInit(message) {
|
function waitForInit(message) {
|
||||||
if ('com.daplie.walnut.init' !== message.type) {
|
if ('com.daplie.walnut.init' !== message.type) {
|
||||||
console.log('[Worker] 0 got unexpected message:');
|
console.warn('[Worker] 0 got unexpected message:');
|
||||||
console.log(message);
|
console.warn(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ function waitForInit(message) {
|
||||||
|
|
||||||
require('./lib/local-server').create(msg.certPaths, msg.localPort, function (err, webserver) {
|
require('./lib/local-server').create(msg.certPaths, msg.localPort, function (err, webserver) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log('[ERROR] worker.js');
|
console.error('[ERROR] worker.js');
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ function waitForInit(message) {
|
||||||
return new PromiseA(function (resolve) {
|
return new PromiseA(function (resolve) {
|
||||||
function initWebServer(srvmsg) {
|
function initWebServer(srvmsg) {
|
||||||
if ('com.daplie.walnut.webserver.onrequest' !== srvmsg.type) {
|
if ('com.daplie.walnut.webserver.onrequest' !== srvmsg.type) {
|
||||||
console.log('[Worker] 1 got unexpected message:');
|
console.warn('[Worker] 1 got unexpected message:');
|
||||||
console.log(srvmsg);
|
console.warn(srvmsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +63,10 @@ process.on('beforeExit', function (msg) {
|
||||||
process.on('unhandledRejection', function (err) {
|
process.on('unhandledRejection', function (err) {
|
||||||
// this should always throw
|
// this should always throw
|
||||||
// (it means somewhere we're not using bluebird by accident)
|
// (it means somewhere we're not using bluebird by accident)
|
||||||
console.error('[unhandledRejection]');
|
console.error('[caught] [unhandledRejection]');
|
||||||
|
console.error(Object.keys(err));
|
||||||
|
console.error(err);
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
throw err;
|
|
||||||
});
|
});
|
||||||
process.on('rejectionHandled', function (msg) {
|
process.on('rejectionHandled', function (msg) {
|
||||||
console.error('[rejectionHandled]');
|
console.error('[rejectionHandled]');
|
||||||
|
|
Loading…
Reference in New Issue