goldilocks.js/lib/app.js

269 satır
7.2 KiB
JavaScript

'use strict';
module.exports = function (opts) {
var express = require('express');
//var finalhandler = require('finalhandler');
var serveStatic = require('serve-static');
var serveIndex = require('serve-index');
//var assetServer = serveStatic(opts.assetsPath);
var path = require('path');
//var wellKnownServer = serveStatic(path.join(opts.assetsPath, 'well-known'));
var serveStaticMap = {};
var serveIndexMap = {};
var content = opts.content;
//var server;
var serveInit;
var app;
function _reloadWrite(data, enc, cb) {
/*jshint validthis: true */
if (this.headersSent) {
this.__write(data, enc, cb);
return;
}
if (!/html/i.test(this.getHeader('Content-Type'))) {
this.__write(data, enc, cb);
return;
}
if (this.getHeader('Content-Length')) {
this.setHeader('Content-Length', this.getHeader('Content-Length') + this.__my_addLen);
}
this.__write(this.__my_livereload);
this.__write(data, enc, cb);
}
function createServeInit() {
var PromiseA = require('bluebird');
var fs = PromiseA.promisifyAll(require('fs'));
var ownersPath = path.join(__dirname, '..', 'var', 'owners.json');
return require('../packages/apis/com.daplie.caddy').create({
PromiseA: PromiseA
, storage: {
owners: {
all: function () {
var owners;
try {
owners = require(ownersPath);
} catch(e) {
owners = {};
}
return PromiseA.resolve(Object.keys(owners).map(function (key) {
var owner = owners[key];
owner.id = key;
return owner;
}));
}
, set: function (id, obj) {
var owners;
try {
owners = require(ownersPath);
} catch(e) {
owners = {};
}
obj.id = id;
owners[id] = obj;
return fs.writeFileAsync(ownersPath, JSON.stringify(owners), 'utf8');
}
}
}
, recase: require('recase').create({})
, options: opts
});
}
app = express();
return app.use('/', function (req, res, next) {
if (!req.headers.host) {
next(new Error('missing HTTP Host header'));
return;
}
if (0 === req.url.indexOf('/api/com.daplie.caddy/')) {
if (!serveInit) {
serveInit = createServeInit();
}
}
if ('/api/com.daplie.caddy/init' === req.url) {
serveInit.init(req, res);
return;
}
if ('/api/com.daplie.caddy/config' === req.url) {
serveInit.config(req, res);
return;
}
if (content && '/' === req.url) {
// res.setHeader('Content-Type', 'application/octet-stream');
res.end(content);
return;
}
//var done = finalhandler(req, res);
var host = req.headers.host;
var hostname = (host||'').split(':')[0].toLowerCase();
console.log('opts.global', opts.global);
var sites = [ opts.global || {}, opts.sites[hostname] || {}, opts.defer || {} ];
var loadables = {
serve: function (config, hostname, pathname, req, res, next) {
config = config.slice(0);
var originalUrl = req.url;
function nextServe() {
var dirname = config.pop();
console.log('[serve]', req.url, hostname, pathname, dirname);
if (!dirname) {
req.url = originalUrl;
next();
return;
}
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) {
config = config.slice(0);
var originalUrl = req.url;
function nextIndex() {
var dirname = config.pop();
console.log('[indexes]', req.url, hostname, pathname, dirname);
if (!dirname) {
req.url = originalUrl;
next();
return;
}
if (!serveStaticMap[dirname]) {
serveIndexMap[dirname] = serveIndex(dirname);
}
serveIndexMap[dirname](req, res, nextIndex);
}
req.url = req.url.substr(pathname.length - 1);
nextIndex();
}
};
function runModule(config, hostname, pathname, modulename, req, res, next) {
if (!loadables[modulename]) {
next(new Error("no module '" + modulename + "' found"));
return;
}
loadables[modulename](config, hostname, pathname, req, res, next);
}
function iterModules(modules, hostname, pathname, req, res, next) {
var modulenames = Object.keys(modules);
function nextModule() {
var modulename = modulenames.pop();
if (!modulename) {
next();
return;
}
console.log('modules', modules);
runModule(modules[modulename], hostname, pathname, modulename, req, res, nextModule);
}
nextModule();
}
function iterPaths(site, hostname, req, res, next) {
var pathnames = Object.keys(site.paths || {});
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;
});
function nextPath() {
var pathname = pathnames.pop();
if (!pathname) {
next();
return;
}
console.log('iterPaths', hostname, pathname, req.url);
iterModules(site.paths[pathname], hostname, pathname, req, res, nextPath);
}
nextPath();
}
function nextSite() {
var site = sites.pop();
if (!site) {
next(); // 404
return;
}
iterPaths(site, hostname, req, res, nextSite);
}
nextSite();
/*
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) {
server.expressApp(req, res, serveTheStatic);
return;
}
serveTheStatic();
}
if (opts.livereload) {
res.__my_livereload = '<script src="//'
+ (host || opts.sites[0].name).split(':')[0]
+ ':35729/livereload.js?snipver=1"></script>';
res.__my_addLen = res.__my_livereload.length;
// TODO modify prototype instead of each instance?
res.__write = res.write;
res.write = _reloadWrite;
}
console.log('hostname:', hostname, opts.sites[0].paths);
addServer(hostname);
server = hostsMap[hostname] || hostsMap[opts.sites[0].name];
serveStaticly(server);
*/
});
};