move towards full hotloading
This commit is contained in:
		
							parent
							
								
									d5a7ab6049
								
							
						
					
					
						commit
						be2c73ef08
					
				| @ -10,21 +10,7 @@ var connect         = require('connect'); | ||||
| var vhost           = require('vhost'); | ||||
| 
 | ||||
| module.exports.create = function (securePort, certsPath, vhostsdir) { | ||||
|     // connect / express app
 | ||||
|   var app             = connect(); | ||||
| 
 | ||||
|     // SSL Server
 | ||||
|   var secureContexts  = {}; | ||||
|   var dummyCerts; | ||||
|   var secureOpts; | ||||
|   var secureServer; | ||||
| 
 | ||||
|     // the ssl domains I have
 | ||||
|     // TODO read vhosts minus 
 | ||||
|   var domains         = fs.readdirSync(vhostsdir).filter(function (node) { | ||||
|                           // not a hidden or private file
 | ||||
|                           return '.' !== node[0] && '_' !== node[0]; | ||||
|                         }).map(function (apppath) { | ||||
|   function getDomainInfo(apppath) { | ||||
|     var parts = apppath.split(/[#%]+/); | ||||
|     var hostname = parts.shift(); | ||||
|     var pathname = parts.join('/').replace(/\/+/g, '/').replace(/^\//, ''); | ||||
| @ -32,10 +18,76 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { | ||||
|     return { | ||||
|       hostname: hostname | ||||
|     , pathname: pathname | ||||
|     , dirpathname: parts.join('#') | ||||
|     , dirname: apppath | ||||
|     , isRoot: apppath === hostname | ||||
|     }; | ||||
|                         }).sort(function (a, b) { | ||||
|   } | ||||
| 
 | ||||
|   function loadDomainMounts(domaininfo) { | ||||
|     var appContext; | ||||
| 
 | ||||
|     // should order and group by longest domain, then longest path
 | ||||
|     if (!domainMergeMap[domaininfo.hostname]) { | ||||
|       // create an connect / express app exclusive to this domain
 | ||||
|       // TODO express??
 | ||||
|       domainMergeMap[domaininfo.hostname] = { | ||||
|         hostname: domaininfo.hostname | ||||
|       , apps: connect() | ||||
|       , mountsMap: {} | ||||
|       }; | ||||
|       domainMerged.push(domainMergeMap[domaininfo.hostname]); | ||||
|     } | ||||
| 
 | ||||
|     if (domainMergeMap[domaininfo.hostname].mountsMap['/' + domaininfo.dirpathname]) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     domainMergeMap[domaininfo.hostname].mountsMap['/' + domaininfo.dirpathname] = function (req, res, next) { | ||||
|       if (appContext) { | ||||
|         appContext(req, res, next); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       console.log('[log] LOADING "' + domaininfo.hostname + '/' + domaininfo.pathname + '"'); | ||||
|       getAppContext(domaininfo).then(function (localApp) { | ||||
|         // Note: pathname should NEVER have a leading '/' on its own
 | ||||
|         // we always add it explicitly
 | ||||
|         try { | ||||
|           domainMergeMap[domaininfo.hostname].apps.use('/' + domaininfo.pathname, localApp); | ||||
|           console.info('Loaded ' + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname); | ||||
|           appContext = localApp; | ||||
|           appContext(req, res, next); | ||||
|         } catch(e) { | ||||
|           console.error('[ERROR] ' + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname); | ||||
|           console.error(e); | ||||
|           res.send('{ "error": { "message": "[ERROR] could not load ' | ||||
|             + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname | ||||
|             + 'or default error app." } }'); | ||||
|         } | ||||
|       }); | ||||
|     }; | ||||
|     domainMergeMap[domaininfo.hostname].apps.use( | ||||
|       '/' + domaininfo.pathname | ||||
|     , domainMergeMap[domaininfo.hostname].mountsMap['/' + domaininfo.dirpathname]  | ||||
|     ); | ||||
| 
 | ||||
|     return PromiseA.resolve(); | ||||
|   } | ||||
| 
 | ||||
|   function loadDomainVhosts() { | ||||
|     domainMerged.forEach(function (domainApp) { | ||||
|       console.log('[log] merged ' + domainApp.hostname); | ||||
|       app.use(vhost(domainApp.hostname, domainApp.apps)); | ||||
|       app.use(vhost('www.' + domainApp.hostname, domainApp.apps)); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function readNewVhosts() { | ||||
|     return fs.readdirSync(vhostsdir).filter(function (node) { | ||||
|       // not a hidden or private file
 | ||||
|       return '.' !== node[0] && '_' !== node[0]; | ||||
|     }).map(getDomainInfo).sort(function (a, b) { | ||||
|       var hlen = b.hostname.length - a.hostname.length; | ||||
|       var plen = b.pathname.length - a.pathname.length; | ||||
| 
 | ||||
| @ -50,9 +102,22 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { | ||||
|       } | ||||
|       return plen; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|     // connect / express app
 | ||||
|   var app             = connect(); | ||||
| 
 | ||||
|     // SSL Server
 | ||||
|   var secureContexts  = {}; | ||||
|   var dummyCerts; | ||||
|   var secureOpts; | ||||
|   var secureServer; | ||||
| 
 | ||||
|   /* | ||||
|   var rootDomains     = domains.filter(function (domaininfo) { | ||||
|                           return domaininfo.isRoot; | ||||
|                         }); | ||||
|   */ | ||||
|   var domainMergeMap  = {}; | ||||
|   var domainMerged    = []; | ||||
| 
 | ||||
| @ -66,6 +131,7 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { | ||||
|   } | ||||
| 
 | ||||
|   function getDummyAppContext(err, msg) { | ||||
|     console.error('[ERROR] getDummyAppContext'); | ||||
|     console.error(err); | ||||
|     console.error(msg); | ||||
|     return function (req, res) { | ||||
| @ -163,62 +229,30 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { | ||||
|     return secureContexts[domainname]; | ||||
|   } | ||||
| 
 | ||||
|   app.use(function (req, res, next) { | ||||
|     console.log('[log] request for ' + req.headers.host + req.url); | ||||
|     next(); | ||||
|   }); | ||||
| 
 | ||||
|   // TODO load these once the server has started
 | ||||
|   // TODO pre-cache these once the server has started?
 | ||||
|   // return forEachAsync(rootDomains, loadCerts);
 | ||||
|   return forEachAsync(domains, function (domaininfo) { | ||||
|     var appContext; | ||||
|   // TODO load these even more lazily
 | ||||
|   return forEachAsync(readNewVhosts(), loadDomainMounts).then(loadDomainVhosts).then(runServer); | ||||
| 
 | ||||
|     // should order and group by longest domain, then longest path
 | ||||
|   function hotloadApp(req, res, next) { | ||||
|     var vhost = (req.headers.host || '').split(':')[0]; | ||||
| 
 | ||||
|     if (!domainMergeMap[vhost]) { | ||||
|       // TODO reread directories
 | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|     // TODO loop through mounts and see if any fit
 | ||||
|     domainMergeMap[vhost].mountsMap['/' + domaininfo.dirpathname] | ||||
|     if (!domainMergeMap[domaininfo.hostname]) { | ||||
|       // create an connect / express app exclusive to this domain
 | ||||
|       // TODO express??
 | ||||
|       domainMergeMap[domaininfo.hostname] = { hostname: domaininfo.hostname, apps: connect() }; | ||||
|       domainMerged.push(domainMergeMap[domaininfo.hostname]); | ||||
|       // TODO reread directories
 | ||||
|     } | ||||
|     */ | ||||
|     // TODO hot load all-the-things
 | ||||
|     next(); | ||||
|   } | ||||
| 
 | ||||
|     domainMergeMap[domaininfo.hostname].apps.use( | ||||
|       '/' + domaininfo.pathname | ||||
|     , function (req, res, next) { | ||||
|         if (appContext) { | ||||
|           console.log('[log] has appContext'); | ||||
|           appContext(req, res, next); | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         console.log('[log] no appContext'); | ||||
|         getAppContext(domaininfo).then(function (localApp) { | ||||
|           // Note: pathname should NEVER have a leading '/' on its own
 | ||||
|           // we always add it explicitly
 | ||||
|           try { | ||||
|             domainMergeMap[domaininfo.hostname].apps.use('/' + domaininfo.pathname, localApp); | ||||
|             console.info('Loaded ' + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname); | ||||
|             appContext = localApp; | ||||
|             appContext(req, res, next); | ||||
|           } catch(e) { | ||||
|             console.error('[ERROR] ' + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname); | ||||
|             console.error(e); | ||||
|             res.send('{ "error": { "message": "[ERROR] could not load ' | ||||
|               + domaininfo.hostname + ':' + securePort + '/' + domaininfo.pathname | ||||
|               + 'or default error app." } }'); | ||||
|           } | ||||
|         }); | ||||
| 
 | ||||
|       } | ||||
|     ); | ||||
| 
 | ||||
|     return PromiseA.resolve(); | ||||
|   }).then(function () { | ||||
|     domainMerged.forEach(function (domainApp) { | ||||
|       console.log('[log] merged ' + domainApp.hostname); | ||||
|       app.use(vhost(domainApp.hostname, domainApp.apps)); | ||||
|       app.use(vhost('www.' + domainApp.hostname, domainApp.apps)); | ||||
|     }); | ||||
|   }).then(runServer); | ||||
|   app.use(hotloadApp); | ||||
| 
 | ||||
|   function runServer() { | ||||
|     //provide a SNICallback when you create the options for the https server
 | ||||
| @ -268,7 +302,6 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { | ||||
| 
 | ||||
|     secureServer = https.createServer(secureOpts); | ||||
|     secureServer.on('request', function (req, res) { | ||||
|       console.log('[log] request'); | ||||
|       app(req, res); | ||||
|     }); | ||||
|     secureServer.listen(securePort, function () { | ||||
|  | ||||
							
								
								
									
										26
									
								
								walnut.js
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								walnut.js
									
									
									
									
									
								
							| @ -1,4 +1,5 @@ | ||||
| //var holepunch = require('./holepunch/beacon');
 | ||||
| 'use strict'; | ||||
| 
 | ||||
| //var config = require('./device.json');
 | ||||
| var securePort = process.argv[2] || 443; | ||||
| var insecurePort = process.argv[3] || 80; | ||||
| @ -10,32 +11,33 @@ var certsPath = path.join(__dirname, 'certs'); | ||||
| // require('ssl-root-cas').inject();
 | ||||
| var vhostsdir = path.join(__dirname, 'vhosts'); | ||||
| 
 | ||||
| require('./lib/insecure-server').create(securePort, insecurePort, redirects); | ||||
| require('./lib/vhost-sni-server.js').create(securePort, certsPath, vhostsdir).then(function () { | ||||
| function phoneHome() { | ||||
|   var holepunch = require('./holepunch/beacon'); | ||||
|   var ports; | ||||
| 
 | ||||
|   ports = [ | ||||
|     { private: 22 | ||||
|     , public: 22 | ||||
|     { private: 65022 | ||||
|     , public: 65022 | ||||
|     , protocol: 'tcp' | ||||
|     , ttl: 0 | ||||
|     , test: { service: 'ssh' } | ||||
|     , testable: false | ||||
|     } | ||||
|   , { private: 443 | ||||
|     , public: 443 | ||||
|   , { private: 650443 | ||||
|     , public: 650443 | ||||
|     , protocol: 'tcp' | ||||
|     , ttl: 0 | ||||
|     , test: { service: 'https' } | ||||
|     } | ||||
|   , { private: 80 | ||||
|     , public: 80 | ||||
|   , { private: 65080 | ||||
|     , public: 65080 | ||||
|     , protocol: 'tcp' | ||||
|     , ttl: 0 | ||||
|     , test: { service: 'http' } | ||||
|     } | ||||
|   ]; | ||||
| 
 | ||||
|   //
 | ||||
|   /* | ||||
|   // TODO return a middleware
 | ||||
|   holepunch.run(require('./redirects.json').reduce(function (all, redirect) { | ||||
| @ -52,5 +54,7 @@ require('./lib/vhost-sni-server.js').create(securePort, certsPath, vhostsdir).th | ||||
|   }, []), ports).catch(function () { | ||||
|     console.error("Couldn't phone home. Oh well"); | ||||
|   }); | ||||
|   */ | ||||
| }); | ||||
|   //*/
 | ||||
| } | ||||
| require('./lib/insecure-server').create(securePort, insecurePort, redirects); | ||||
| require('./lib/vhost-sni-server.js').create(securePort, certsPath, vhostsdir).then(phoneHome); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user