goldilocks.js/lib/app.js

326 lines
9.1 KiB
JavaScript
Raw Normal View History

2015-06-24 21:36:17 +00:00
'use strict';
module.exports = function (myDeps, conf, overrideHttp) {
2017-03-02 07:58:45 +00:00
var express = require('express');
//var finalhandler = require('finalhandler');
2015-06-24 21:36:17 +00:00
var serveStatic = require('serve-static');
var serveIndex = require('serve-index');
2017-03-02 07:58:45 +00:00
//var assetServer = serveStatic(opts.assetsPath);
2017-02-23 01:48:34 +00:00
var path = require('path');
2017-03-02 07:58:45 +00:00
//var wellKnownServer = serveStatic(path.join(opts.assetsPath, 'well-known'));
2017-03-02 07:58:45 +00:00
var serveStaticMap = {};
var serveIndexMap = {};
var content = conf.content;
2017-03-02 07:58:45 +00:00
//var server;
var goldilocksApis;
2017-03-02 07:58:45 +00:00
var app;
2017-04-13 22:50:48 +00:00
var request;
2015-06-24 21:36:17 +00:00
function createGoldilocksApis() {
2017-03-02 07:58:45 +00:00
var PromiseA = require('bluebird');
2017-04-06 01:02:51 +00:00
var OAUTH3 = require('../packages/assets/org.oauth3');
require('../packages/assets/org.oauth3/oauth3.domains.js');
require('../packages/assets/org.oauth3/oauth3.dns.js');
require('../packages/assets/org.oauth3/oauth3.tunnel.js');
OAUTH3._hooks = require('../packages/assets/org.oauth3/oauth3.node.storage.js');
2017-04-13 22:50:48 +00:00
request = request || PromiseA.promisify(require('request'));
2017-04-06 01:02:51 +00:00
myDeps.PromiseA = PromiseA;
myDeps.OAUTH3 = OAUTH3;
myDeps.recase = require('recase').create({});
myDeps.request = request;
return require('../packages/apis/com.daplie.goldilocks').create(myDeps, conf);
2017-03-02 07:58:45 +00:00
}
app = express();
var Sites = {
add: function (sitesMap, site) {
if (!sitesMap[site.$id]) {
sitesMap[site.$id] = site;
}
if (!site.paths) {
site.paths = [];
}
if (!site.paths._map) {
site.paths._map = {};
}
site.paths.forEach(function (path) {
site.paths._map[path.$id] = path;
if (!path.modules) {
path.modules = [];
}
if (!path.modules._map) {
path.modules._map = {};
}
path.modules.forEach(function (module) {
path.modules._map[module.$id] = module;
});
});
}
};
2017-04-27 22:50:03 +00:00
var opts = overrideHttp || conf.http;
if (!opts.defaults) {
opts.defaults = {};
}
if (!opts.global) {
opts.global = {};
}
2017-03-13 22:39:43 +00:00
if (!opts.sites) {
opts.sites = [];
}
opts.sites._map = {};
opts.sites.forEach(function (site) {
Sites.add(opts.sites._map, site);
2017-03-13 22:39:43 +00:00
});
function mapMap(el, i, arr) {
arr._map[el.$id] = el;
}
opts.global.modules._map = {};
opts.global.modules.forEach(mapMap);
opts.global.paths._map = {};
opts.global.paths.forEach(function (path, i, arr) {
mapMap(path, i, arr);
//opts.global.paths._map[path.$id] = path;
path.modules._map = {};
path.modules.forEach(mapMap);
});
opts.sites.forEach(function (site) {
site.paths._map = {};
site.paths.forEach(function (path, i, arr) {
mapMap(path, i, arr);
//site.paths._map[path.$id] = path;
path.modules._map = {};
path.modules.forEach(mapMap);
});
});
opts.defaults.modules._map = {};
opts.defaults.modules.forEach(mapMap);
opts.defaults.paths._map = {};
opts.defaults.paths.forEach(function (path, i, arr) {
mapMap(path, i, arr);
//opts.global.paths._map[path.$id] = path;
path.modules._map = {};
path.modules.forEach(mapMap);
});
function _goldApis(req, res, next) {
if (!goldilocksApis) {
goldilocksApis = createGoldilocksApis();
2017-03-02 07:58:45 +00:00
}
if (typeof goldilocksApis[req.params.name] === 'function') {
goldilocksApis[req.params.name](req, res);
} else {
next();
2017-04-06 01:02:51 +00:00
}
}
return app
.use('/api/com.daplie.goldilocks/:name', _goldApis)
.use('/api/goldilocks@daplie.com/:name', _goldApis)
.use('/', function (req, res, next) {
if (!req.headers.host) {
next(new Error('missing HTTP Host header'));
2017-03-18 20:48:49 +00:00
return;
}
2017-02-28 21:55:48 +00:00
2015-06-30 23:11:01 +00:00
if (content && '/' === req.url) {
// res.setHeader('Content-Type', 'application/octet-stream');
res.end(content);
return;
}
2017-03-02 07:58:45 +00:00
//var done = finalhandler(req, res);
var host = req.headers.host;
2017-03-02 07:58:45 +00:00
var hostname = (host||'').split(':')[0].toLowerCase();
console.log('opts.global', opts.global);
2017-03-13 22:39:43 +00:00
var sites = [ opts.global || null, opts.sites._map[hostname] || null, opts.defaults || null ];
2017-03-02 07:58:45 +00:00
var loadables = {
serve: function (config, hostname, pathname, req, res, next) {
var originalUrl = req.url;
2017-03-13 22:39:43 +00:00
var dirpaths = config.paths.slice(0);
2017-03-02 07:58:45 +00:00
function nextServe() {
2017-03-13 22:39:43 +00:00
var dirname = dirpaths.pop();
2017-03-02 07:58:45 +00:00
if (!dirname) {
req.url = originalUrl;
next();
return;
}
2017-03-13 22:39:43 +00:00
console.log('[serve]', req.url, hostname, pathname, dirname);
dirname = path.resolve(conf.cwd, dirname.replace(/:hostname/, hostname));
2017-03-02 07:58:45 +00:00
if (!serveStaticMap[dirname]) {
serveStaticMap[dirname] = serveStatic(dirname);
}
serveStaticMap[dirname](req, res, nextServe);
}
req.url = req.url.substr(pathname.length - 1);
nextServe();
}
, indexes: function (config, hostname, pathname, req, res, next) {
var originalUrl = req.url;
2017-03-13 22:39:43 +00:00
var dirpaths = config.paths.slice(0);
2017-03-02 07:58:45 +00:00
function nextIndex() {
2017-03-13 22:39:43 +00:00
var dirname = dirpaths.pop();
2017-03-02 07:58:45 +00:00
if (!dirname) {
req.url = originalUrl;
next();
return;
}
2017-03-13 22:39:43 +00:00
console.log('[indexes]', req.url, hostname, pathname, dirname);
dirname = path.resolve(conf.cwd, dirname.replace(/:hostname/, hostname));
2017-03-02 07:58:45 +00:00
if (!serveStaticMap[dirname]) {
serveIndexMap[dirname] = serveIndex(dirname);
}
serveIndexMap[dirname](req, res, nextIndex);
}
req.url = req.url.substr(pathname.length - 1);
nextIndex();
}
2017-03-13 22:39:43 +00:00
, app: function (config, hostname, pathname, req, res, next) {
//var appfile = path.resolve(/*process.cwd(), */config.path.replace(/:hostname/, hostname));
var appfile = config.path.replace(/:hostname/, hostname);
2017-06-12 17:39:02 +00:00
try {
var app = require(appfile);
app(req, res, next);
} catch (err) {
next();
}
2017-03-13 22:39:43 +00:00
}
2017-03-02 07:58:45 +00:00
};
2017-03-13 22:39:43 +00:00
function runModule(module, hostname, pathname, modulename, req, res, next) {
2017-03-02 07:58:45 +00:00
if (!loadables[modulename]) {
next(new Error("no module '" + modulename + "' found"));
return;
}
2017-03-13 22:39:43 +00:00
loadables[modulename](module, hostname, pathname, req, res, next);
2017-03-02 07:58:45 +00:00
}
function iterModules(modules, hostname, pathname, req, res, next) {
2017-03-13 22:39:43 +00:00
console.log('modules');
console.log(modules);
var modulenames = Object.keys(modules._map);
2017-03-02 07:58:45 +00:00
function nextModule() {
var modulename = modulenames.pop();
if (!modulename) {
next();
return;
}
console.log('modules', modules);
2017-03-13 22:39:43 +00:00
runModule(modules._map[modulename], hostname, pathname, modulename, req, res, nextModule);
2017-03-02 07:58:45 +00:00
}
nextModule();
}
function iterPaths(site, hostname, req, res, next) {
2017-03-13 22:39:43 +00:00
console.log('site', hostname);
console.log(site);
var pathnames = Object.keys(site.paths._map);
console.log('pathnames', pathnames);
2017-03-02 07:58:45 +00:00
pathnames = pathnames.filter(function (pathname) {
// TODO ensure that pathname has trailing /
return (0 === req.url.indexOf(pathname));
//return req.url.match(pathname);
});
pathnames.sort(function (a, b) {
return b.length - a.length;
});
2017-03-13 22:39:43 +00:00
console.log('pathnames', pathnames);
2017-03-02 07:58:45 +00:00
function nextPath() {
2017-03-13 22:39:43 +00:00
var pathname = pathnames.shift();
2017-03-02 07:58:45 +00:00
if (!pathname) {
next();
return;
}
console.log('iterPaths', hostname, pathname, req.url);
2017-03-13 22:39:43 +00:00
iterModules(site.paths._map[pathname].modules, hostname, pathname, req, res, nextPath);
2017-03-02 07:58:45 +00:00
}
nextPath();
}
function nextSite() {
2017-03-13 22:39:43 +00:00
console.log('hostname', hostname, sites);
var site;
if (!sites.length) {
2017-03-02 07:58:45 +00:00
next(); // 404
return;
}
2017-03-13 22:39:43 +00:00
site = sites.shift();
if (!site) {
nextSite();
return;
}
2017-03-02 07:58:45 +00:00
iterPaths(site, hostname, req, res, nextSite);
}
nextSite();
/*
2017-02-23 01:48:34 +00:00
function serveStaticly(server) {
function serveTheStatic() {
server.serve(req, res, function (err) {
if (err) { return done(err); }
server.index(req, res, function (err) {
if (err) { return done(err); }
req.url = req.url.replace(/\/assets/, '');
assetServer(req, res, function () {
if (err) { return done(err); }
req.url = req.url.replace(/\/\.well-known/, '');
wellKnownServer(req, res, done);
});
});
});
}
if (server.expressApp) {
2017-02-23 01:48:34 +00:00
server.expressApp(req, res, serveTheStatic);
return;
}
2017-02-23 01:48:34 +00:00
serveTheStatic();
}
2015-12-06 06:43:33 +00:00
if (opts.livereload) {
res.__my_livereload = '<script src="//'
2017-02-02 03:00:00 +00:00
+ (host || opts.sites[0].name).split(':')[0]
2015-12-06 06:43:33 +00:00
+ ':35729/livereload.js?snipver=1"></script>';
res.__my_addLen = res.__my_livereload.length;
2015-12-06 06:43:33 +00:00
// TODO modify prototype instead of each instance?
res.__write = res.write;
res.write = _reloadWrite;
}
2016-08-06 20:15:12 +00:00
2017-02-23 01:48:34 +00:00
console.log('hostname:', hostname, opts.sites[0].paths);
addServer(hostname);
server = hostsMap[hostname] || hostsMap[opts.sites[0].name];
2017-02-23 01:48:34 +00:00
serveStaticly(server);
2017-03-02 07:58:45 +00:00
*/
});
2015-06-24 21:36:17 +00:00
};