| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 17:47:31 +00:00
										 |  |  | module.exports.create = function (app, xconfx, apiFactories, apiDeps, errorIfApi, errorIfAssets) { | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |   var PromiseA = require('bluebird'); | 
					
						
							|  |  |  |   var path = require('path'); | 
					
						
							|  |  |  |   var fs = PromiseA.promisifyAll(require('fs')); | 
					
						
							|  |  |  |   // NOTE: each process has its own cache
 | 
					
						
							|  |  |  |   var localCache = { le: {}, statics: {} }; | 
					
						
							|  |  |  |   var express = require('express'); | 
					
						
							|  |  |  |   var setupDomain = xconfx.setupDomain = ('cloud.' + xconfx.primaryDomain); | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |   var apiApp; | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |   var setupApp; | 
					
						
							| 
									
										
										
										
											2016-06-08 14:05:10 -04:00
										 |  |  |   var CORS; | 
					
						
							|  |  |  |   var cors; | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |   function redirectSetup(reason, req, res) { | 
					
						
							| 
									
										
										
										
											2017-05-04 23:09:56 -06:00
										 |  |  |     console.log('xconfx', xconfx); | 
					
						
							| 
									
										
										
										
											2016-06-08 14:05:10 -04:00
										 |  |  |     var url = 'https://cloud.' + xconfx.primaryDomain; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (443 !== xconfx.externalPort) { | 
					
						
							|  |  |  |       url += ':' + xconfx.externalPort; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     url += '#referrer=' + reason; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res.statusCode = 302; | 
					
						
							|  |  |  |     res.setHeader('Location', url); | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |     res.end("The static pages for '" + reason + "' are not listed in '" + path.join(xconfx.sitespath, reason) + "'"); | 
					
						
							| 
									
										
										
										
											2016-06-08 14:05:10 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |   function disallowSymLinks(req, res) { | 
					
						
							|  |  |  |     res.end( | 
					
						
							|  |  |  |       "Symbolic Links are not supported on all platforms and are therefore disallowed." | 
					
						
							|  |  |  |     + " Instead, simply create a file of the same name as the link with a single line of text" | 
					
						
							|  |  |  |     + " which should be the relative or absolute path to the target directory." | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function disallowNonFiles(req, res) { | 
					
						
							|  |  |  |     res.end( | 
					
						
							|  |  |  |       "Pipes, Blocks, Sockets, FIFOs, and other such nonsense are not permitted." | 
					
						
							|  |  |  |     + " Instead please create a directory from which to read or create a file " | 
					
						
							|  |  |  |     + " with a single line of text which should be the target directory to read from." | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function securityError(req, res) { | 
					
						
							|  |  |  |     res.end("Security Error: Link points outside of packages/pages"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function notConfigured(req, res, next) { | 
					
						
							|  |  |  |     if (setupDomain !== req.hostname) { | 
					
						
							| 
									
										
										
										
											2017-05-24 04:27:52 +00:00
										 |  |  |       console.log('[notConfigured] req.hostname', req.hostname); | 
					
						
							| 
									
										
										
										
											2017-05-25 17:23:39 -06:00
										 |  |  |       if ('/' === req.url[req.url.length - 1] || /\.html\b/.test(req.url)) { | 
					
						
							| 
									
										
										
										
											2017-05-24 04:27:52 +00:00
										 |  |  |         redirectSetup(req.hostname, req, res); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!setupApp) { | 
					
						
							| 
									
										
										
										
											2017-07-31 22:46:03 +00:00
										 |  |  |       //setupApp = express.static(path.join(xconfx.staticpath, 'walnut@daplie.com'));
 | 
					
						
							|  |  |  |       setupApp = express.static(path.join(__dirname, 'walnut@daplie.com', 'setup')); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |     setupApp(req, res, function () { | 
					
						
							|  |  |  |       if ('/' === req.url) { | 
					
						
							|  |  |  |         res.end('Sanity Fail: Configurator not found'); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       next(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |   function loadSiteHandler(name) { | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     return function handler(req, res, next) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |       // path.join('packages/pages', 'com.daplie.hello') // package name (used as file-link)
 | 
					
						
							|  |  |  |       // path.join('packages/pages', 'domain.tld#hello') // dynamic exact url match
 | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |       var sitepath = path.join(xconfx.sitespath, name); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:27:52 +00:00
										 |  |  |       console.log('sitepath', sitepath); | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |       return fs.lstatAsync(sitepath).then(function (stat) { | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |         if (stat.isSymbolicLink()) { | 
					
						
							|  |  |  |           return disallowSymLinks; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (stat.isDirectory()) { | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |           return express.static(sitepath); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!stat.isFile()) { | 
					
						
							|  |  |  |           return disallowNonFiles; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |         // path.join('packages/pages', 'domain.tld#hello') // a file (not folder) which contains a list of roots
 | 
					
						
							|  |  |  |         // may look like this:
 | 
					
						
							|  |  |  |         //
 | 
					
						
							|  |  |  |         //   com.daplie.hello
 | 
					
						
							|  |  |  |         //   tld.domain.app
 | 
					
						
							|  |  |  |         //
 | 
					
						
							|  |  |  |         // this is basically a 'recursive mount' to signify that 'com.daplie.hello' should be tried first
 | 
					
						
							|  |  |  |         // and if no file matches that 'tld.domain.app' may be tried next, and so on
 | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |         //
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |         // this may well become a .htaccess type of situation allowing for redirects and such
 | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |         return fs.readFileAsync(sitepath, 'utf8').then(function (text) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |           // TODO allow cascading multiple lines
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |           text = text.trim().split(/\n/)[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // TODO rerun the above, disallowing link-style (or count or memoize to prevent infinite loop)
 | 
					
						
							|  |  |  |           // TODO make safe
 | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |           var packagepath = path.resolve(xconfx.staticpath, text); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |           if (0 !== packagepath.indexOf(xconfx.staticpath)) { | 
					
						
							|  |  |  |             return securityError; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |           // instead of actually creating new instances of express.static
 | 
					
						
							|  |  |  |           // this same effect could be managed by internally re-writing the url (and restoring it)
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |           return express.static(packagepath); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }, function (/*err*/) { | 
					
						
							|  |  |  |         return notConfigured; | 
					
						
							|  |  |  |       }).then(function (handler) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // keep object reference intact
 | 
					
						
							|  |  |  |         localCache.statics[name].handler = handler; | 
					
						
							|  |  |  |         handler(req, res, next); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function staticHelper(appId, opts) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |     console.log('[staticHelper]', appId); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     // TODO inter-process cache expirey
 | 
					
						
							|  |  |  |     // TODO add to xconfx.staticpath
 | 
					
						
							|  |  |  |     xconfx.staticpath = path.join(__dirname, '..', '..', 'packages', 'pages'); | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |     xconfx.sitespath = path.join(__dirname, '..', '..', 'packages', 'sites'); | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |     // Reads in each of the sites directives as 'nodes'
 | 
					
						
							|  |  |  |     return fs.readdirAsync(xconfx.sitespath).then(function (nodes) { | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |       if (opts && opts.clear) { | 
					
						
							|  |  |  |         localCache.statics = {}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |       // Order from longest (index length - 1) to shortest (index 0)
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |       function shortToLong(a, b) { | 
					
						
							|  |  |  |         return b.length - a.length; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       nodes.sort(shortToLong); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:27:52 +00:00
										 |  |  |       nodes = nodes.filter(function (pkgName) { | 
					
						
							|  |  |  |         console.log('[all apps]', pkgName); | 
					
						
							|  |  |  |         // load the apps that match this id's domain and could match the path
 | 
					
						
							|  |  |  |         // domain.daplie.me matches domain.daplie.me
 | 
					
						
							|  |  |  |         // daplie.me#path#to#thing matches daplie.me
 | 
					
						
							|  |  |  |         // daplie.me does NOT match daplie.me#path#to#thing
 | 
					
						
							|  |  |  |         var reqParts = appId.split('#'); | 
					
						
							|  |  |  |         var pkgParts = pkgName.split('#'); | 
					
						
							|  |  |  |         var reqDomain = reqParts.shift(); | 
					
						
							|  |  |  |         var pkgDomain = pkgParts.shift(); | 
					
						
							|  |  |  |         var reqPath = reqParts.join('#'); | 
					
						
							|  |  |  |         var pkgPath = pkgParts.join('#'); | 
					
						
							|  |  |  |         if (reqPath.length) { | 
					
						
							|  |  |  |           reqPath += '#'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (pkgPath.length) { | 
					
						
							|  |  |  |           pkgPath += '#'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!(reqDomain === pkgDomain && 0 === reqPath.indexOf(pkgPath))) { | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!localCache.statics[pkgName]) { | 
					
						
							|  |  |  |           console.log('[load this app]', pkgName); | 
					
						
							|  |  |  |           localCache.statics[pkgName] = { handler: loadSiteHandler(pkgName), createdAt: Date.now() }; | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-05-24 04:27:52 +00:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Secure Matching
 | 
					
						
							|  |  |  |       // apple.com#blah#  apple.com#blah#
 | 
					
						
							|  |  |  |       // apple.com.us#    apple.com#foo#
 | 
					
						
							|  |  |  |       // apple.com#       apple.com#foo#
 | 
					
						
							| 
									
										
										
										
											2017-05-24 06:23:40 +00:00
										 |  |  |       console.log('[lib/main.js] nodes', nodes); | 
					
						
							| 
									
										
										
										
											2017-05-24 04:27:52 +00:00
										 |  |  |       nodes.some(function (pkgName) { | 
					
						
							|  |  |  |         console.log('pkgName, appId', pkgName, appId); | 
					
						
							|  |  |  |         if (0 === (appId + '#').indexOf(pkgName + '#')) { | 
					
						
							|  |  |  |           if (appId !== pkgName) { | 
					
						
							|  |  |  |             localCache.statics[appId] = localCache.statics[pkgName]; | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |           } | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!localCache.statics[appId]) { | 
					
						
							|  |  |  |         localCache.statics[appId] = { handler: notConfigured, createdAt: Date.now() }; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       localCache.staticsKeys = Object.keys(localCache.statics).sort(shortToLong); | 
					
						
							|  |  |  |       return localCache.statics[appId]; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |   function serveStaticHelper(appId, opts, req, res, next) { | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     var appIdParts = appId.split('#'); | 
					
						
							|  |  |  |     var appIdPart; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:56:31 +00:00
										 |  |  |     // TODO for <domain.tld>/<path>/apps/<package> the Uri should be <domain.tld>/<path>
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:53:52 +00:00
										 |  |  |     res.setHeader('X-Walnut-Uri', appId.replace(/#/g, '/')); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     // TODO configuration for allowing www
 | 
					
						
							|  |  |  |     if (/^www\./.test(req.hostname)) { | 
					
						
							|  |  |  |       // NOTE: acme responder and appcache unbricker must come before scrubTheDub
 | 
					
						
							|  |  |  |       if (/\.(appcache|manifest)\b/.test(req.url)) { | 
					
						
							|  |  |  |         require('./unbrick-appcache').unbrick(req, res); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       require('./no-www').scrubTheDub(req, res); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     /* | 
					
						
							|  |  |  |     if (!redirectives && config.redirects) { | 
					
						
							|  |  |  |       redirectives = require('./hostname-redirects').compile(config.redirects); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |     /* | 
					
						
							|  |  |  |     // TODO assets.example.com/sub/assets/com.example.xyz/
 | 
					
						
							|  |  |  |     if (/^assets\./.test(req.hostname) && /\/assets(\/|$)/.test(req.url)) { | 
					
						
							|  |  |  |       ... | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // There may be some app folders named 'apple.com', 'apple.com#foo', and 'apple.com#foo#bar'
 | 
					
						
							|  |  |  |     // Here we're sorting an appId broken into parts like [ 'apple.com', 'foo', 'bar' ]
 | 
					
						
							|  |  |  |     // and wer're checking to see if this is perhaps '/' of 'apple.com/foo/bar' or '/foo/bar' of 'apple.com', etc
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     while (appIdParts.length) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |       // TODO needs IPC to expire cache when an API says the app mounts have been updated
 | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |       appIdPart = appIdParts.join('#'); | 
					
						
							|  |  |  |       if (localCache.statics[appIdPart]) { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       // TODO test via staticsKeys
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       appIdParts.pop(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!appIdPart || !localCache.statics[appIdPart]) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |       console.log('[serveStaticHelper] appId', appId); | 
					
						
							|  |  |  |       return staticHelper(appId).then(function (webapp) { | 
					
						
							|  |  |  |         //localCache.statics[appId].handler(req, res, next);
 | 
					
						
							|  |  |  |         webapp.handler(req, res, next); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |     console.log('[serveStaticHelper] appIdPart', appIdPart); | 
					
						
							| 
									
										
										
										
											2017-05-19 07:53:52 +00:00
										 |  |  |     if (opts && opts.rewrite && -1 !== req.url.indexOf(appIdPart.replace(/#/g, '/').replace(/\/$/, ''))) { | 
					
						
							|  |  |  |       req.url = req.url.slice(req.url.indexOf(appIdPart.replace(/#/g, '/').replace(/\/$/, '')) + appIdPart.replace(/(\/|#)$/, '').length); | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |       if (0 !== req.url.indexOf('/')) { | 
					
						
							|  |  |  |         req.url = '/' + req.url; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |     localCache.statics[appIdPart].handler(req, res, next); | 
					
						
							|  |  |  |     if (Date.now() - localCache.statics[appIdPart].createdAt > (5 * 60 * 1000)) { | 
					
						
							|  |  |  |       staticHelper(appId, { clear: true }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |   function serveStatic(req, res, next) { | 
					
						
							|  |  |  |     // We convert the URL that was sent in the browser bar from
 | 
					
						
							|  |  |  |     // 'https://domain.tld/foo/bar' to 'domain.tld#foo#bar'
 | 
					
						
							|  |  |  |     var appId = req.hostname + req.url.replace(/\/+/g, '#').replace(/#$/, ''); | 
					
						
							|  |  |  |     serveStaticHelper(appId, null, req, res, next); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function serveApps(req, res, next) { | 
					
						
							|  |  |  |     var appId = req.url.slice(1).replace(/\/+/g, '#').replace(/#$/, ''); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (/^apps\./.test(req.hostname)) { | 
					
						
							|  |  |  |       appId = appId.replace(/^apps#/, ''); | 
					
						
							|  |  |  |     } else if (/\bapps#/.test(appId)) { | 
					
						
							|  |  |  |       appId = appId.replace(/.*\bapps#/, ''); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       next(); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     console.log('[serveApps] appId', appId); | 
					
						
							|  |  |  |     serveStaticHelper(appId, { rewrite: true }, req, res, next); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TODO set header 'X-ExperienceId: domain.tld/sub/path'
 | 
					
						
							|  |  |  |   // This would let an app know whether its app is 'domain.tld' with a path of '/sub/path'
 | 
					
						
							|  |  |  |   // or if its app is 'domain.tld/sub' with a path of '/path'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TODO handle assets.example.com/sub/assets/com.example.xyz/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 06:23:40 +00:00
										 |  |  |   app.use('/api', require('connect-send-error').error()); | 
					
						
							| 
									
										
										
										
											2017-08-30 17:47:31 +00:00
										 |  |  |   app.use('/assets', require('connect-send-error').error()); | 
					
						
							| 
									
										
										
										
											2017-05-20 00:09:48 +00:00
										 |  |  |   app.use('/', function (req, res, next) { | 
					
						
							| 
									
										
										
										
											2017-08-30 17:47:31 +00:00
										 |  |  |     // If this doesn't look like an API or assets we can move along
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     console.log('.'); | 
					
						
							|  |  |  |     console.log('[main.js] req.url, req.hostname'); | 
					
						
							|  |  |  |     console.log(req.url); | 
					
						
							|  |  |  |     console.log(req.hostname); | 
					
						
							|  |  |  |     console.log('.'); | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!/\/(api|assets)(\/|$)/.test(req.url)) { | 
					
						
							|  |  |  |       //console.log('[main.js] api|assets');
 | 
					
						
							|  |  |  |       next(); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // keep https://assets.example.com/assets but skip https://example.com/assets
 | 
					
						
							|  |  |  |     if (/\/assets(\/|$)/.test(req.url) && !/(^|\.)(api|assets)(\.)/.test(req.hostname) && !/^[0-9\.]+$/.test(req.hostname)) { | 
					
						
							|  |  |  |       //console.log('[main.js] skip');
 | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |       next(); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // supports api.example.com/sub/app/api/com.example.xyz/
 | 
					
						
							|  |  |  |     if (!apiApp) { | 
					
						
							|  |  |  |       apiApp = require('./apis').create(xconfx, apiFactories, apiDeps); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (/^OPTIONS$/i.test(req.method)) { | 
					
						
							|  |  |  |       if (!cors) { | 
					
						
							|  |  |  |         CORS = require('connect-cors'); | 
					
						
							|  |  |  |         cors = CORS({ credentials: true, headers: [ | 
					
						
							|  |  |  |           'X-Requested-With' | 
					
						
							|  |  |  |         , 'X-HTTP-Method-Override' | 
					
						
							|  |  |  |         , 'Content-Type' | 
					
						
							|  |  |  |         , 'Accept' | 
					
						
							|  |  |  |         , 'Authorization' | 
					
						
							|  |  |  |         ], methods: [ "GET", "POST", "PATCH", "PUT", "DELETE" ] }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       cors(req, res, apiApp); | 
					
						
							| 
									
										
										
										
											2017-05-24 05:44:23 +00:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     apiApp(req, res, next); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   app.use('/', errorIfApi); | 
					
						
							| 
									
										
										
										
											2017-08-30 17:47:31 +00:00
										 |  |  |   app.use('/', errorIfAssets); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |   app.use('/', serveStatic); | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |   app.use('/', serveApps); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return PromiseA.resolve(); | 
					
						
							|  |  |  | }; |