| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  | module.exports.create = function (app, xconfx, apiFactories, apiDeps, errorIfApi) { | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							|  |  |  |       redirectSetup(req.hostname, req, res); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!setupApp) { | 
					
						
							| 
									
										
										
										
											2017-05-19 06:15:14 +00:00
										 |  |  |       //setupApp = express.static(path.join(xconfx.staticpath, 'com.daplie.walnut'));
 | 
					
						
							|  |  |  |       setupApp = express.static(path.join('lib', 'com.daplie.walnut')); | 
					
						
							| 
									
										
										
										
											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-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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       nodes.forEach(function (name) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |         console.log('[all apps]', name); | 
					
						
							| 
									
										
										
										
											2016-04-09 19:14:00 -04:00
										 |  |  |         if (!localCache.statics[name]) { | 
					
						
							| 
									
										
										
										
											2017-05-19 07:40:20 +00:00
										 |  |  |           console.log('[load this app]', name); | 
					
						
							| 
									
										
										
										
											2017-05-20 04:34:17 +00:00
										 |  |  |           localCache.statics[name] = { handler: loadSiteHandler(name), createdAt: Date.now() }; | 
					
						
							| 
									
										
										
										
											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#
 | 
					
						
							|  |  |  |       nodes.some(function (name) { | 
					
						
							|  |  |  |         if (0 === (name + '#').indexOf(appId + '#')) { | 
					
						
							|  |  |  |           if (appId !== name) { | 
					
						
							|  |  |  |             localCache.statics[appId] = localCache.statics[name]; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           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-20 00:09:48 +00:00
										 |  |  |   app.use('/', function (req, res, next) { | 
					
						
							| 
									
										
										
										
											2017-05-19 23:37:28 +00:00
										 |  |  |     // If this doesn't look like an API we can move along
 | 
					
						
							| 
									
										
										
										
											2017-05-20 00:09:48 +00:00
										 |  |  |     if (!/\/api(\/|$)/.test(req.url)) { | 
					
						
							|  |  |  |       // /^api\./.test(req.hostname) &&
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     apiApp(req, res, next); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   app.use('/', errorIfApi); | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  | }; |