diff --git a/lib/apis.js b/lib/apis.js index 24c1263..a1a79ca 100644 --- a/lib/apis.js +++ b/lib/apis.js @@ -220,33 +220,44 @@ module.exports.create = function (xconfx, apiFactories, apiDeps) { }; } + var CORS = require('connect-cors'); + var cors = CORS({ credentials: true, headers: [ + 'X-Requested-With' + , 'X-HTTP-Method-Override' + , 'Content-Type' + , 'Accept' + , 'Authorization' + ], methods: [ "GET", "POST", "PATCH", "PUT", "DELETE" ] }); + return function (req, res, next) { - var experienceId = req.hostname + req.url.replace(/\/api\/.*/, '/').replace(/\/+/g, '#').replace(/#$/, ''); - var apiId = req.url.replace(/.*\/api\//, '').replace(/\/.*/, ''); + cors(req, res, function () { + var experienceId = req.hostname + req.url.replace(/\/api\/.*/, '/').replace(/\/+/g, '#').replace(/#$/, ''); + var apiId = req.url.replace(/.*\/api\//, '').replace(/\/.*/, ''); - Object.defineProperty(req, 'experienceId', { - enumerable: true - , configurable: false - , writable: false - // TODO this identifier may need to be non-deterministic as to transfer if a domain name changes but is still the "same" app - // (i.e. a company name change. maybe auto vs manual register - just like oauth3?) - // NOTE: probably best to alias the name logically - , value: experienceId + Object.defineProperty(req, 'experienceId', { + enumerable: true + , configurable: false + , writable: false + // TODO this identifier may need to be non-deterministic as to transfer if a domain name changes but is still the "same" app + // (i.e. a company name change. maybe auto vs manual register - just like oauth3?) + // NOTE: probably best to alias the name logically + , value: experienceId + }); + Object.defineProperty(req, 'apiId', { + enumerable: true + , configurable: false + , writable: false + , value: apiId + }); + + if (!localCache.apis[experienceId]) { + localCache.apis[experienceId] = { handler: loadApiHandler(experienceId), createdAt: Date.now() }; + } + + localCache.apis[experienceId].handler(req, res, next); + if (Date.now() - localCache.apis[experienceId].createdAt > (5 * 60 * 1000)) { + localCache.apis[experienceId] = { handler: loadApiHandler(experienceId), createdAt: Date.now() }; + } }); - Object.defineProperty(req, 'apiId', { - enumerable: true - , configurable: false - , writable: false - , value: apiId - }); - - if (!localCache.apis[experienceId]) { - localCache.apis[experienceId] = { handler: loadApiHandler(experienceId), createdAt: Date.now() }; - } - - localCache.apis[experienceId].handler(req, res, next); - if (Date.now() - localCache.apis[experienceId].createdAt > (5 * 60 * 1000)) { - localCache.apis[experienceId] = { handler: loadApiHandler(experienceId), createdAt: Date.now() }; - } }; }; diff --git a/lib/bootstrap.js b/lib/bootstrap.js index f12a9a8..540e55e 100644 --- a/lib/bootstrap.js +++ b/lib/bootstrap.js @@ -48,10 +48,9 @@ module.exports.create = function (app, xconfx, models) { function errorIfNotApi(req, res, next) { // if it's not an ip address - if (/[a-z]+/.test(req.headers.host)) { - if (!/^api\./.test(req.headers.host)) { - console.log('req.headers.host'); - console.log(req.headers.host); + if (/[a-z]+/.test(req.hostname || req.headers.host)) { + if (!/^api\./.test(req.hostname || req.headers.host)) { + console.warn('not API req.headers.host:', req.hostname || req.headers.host); res.send({ error: { message: "no api. subdomain prefix" } }); return; } diff --git a/lib/main.js b/lib/main.js index ae14a8e..0f4d708 100644 --- a/lib/main.js +++ b/lib/main.js @@ -10,6 +10,8 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { var apiApp; var setupDomain = xconfx.setupDomain = ('cloud.' + xconfx.primaryDomain); var setupApp; + var CORS; + var cors; function redirectHttpsHelper(req, res) { var host = req.hostname || req.headers.host || ''; @@ -58,6 +60,20 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { res.end(metaRedirect); } + function redirectSetup(reason, req, res/*, next*/) { + var url = 'https://cloud.' + xconfx.primaryDomain; + + if (443 !== xconfx.externalPort) { + url += ':' + xconfx.externalPort; + } + + url += '#referrer=' + reason; + + res.statusCode = 302; + res.setHeader('Location', url); + res.end(); + } + function redirectHttps(req, res) { if (localCache.le[req.hostname]) { if (localCache.le[req.hostname].conf) { @@ -222,20 +238,6 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { }); } - function redirectSetup(reason, req, res/*, next*/) { - var url = 'https://cloud.' + xconfx.primaryDomain; - - if (443 !== xconfx.externalPort) { - url += ':' + xconfx.externalPort; - } - - url += '#referrer=' + reason; - - res.statusCode = 302; - res.setHeader('Location', url); - res.end(); - } - function serveStatic(req, res, next) { // If we get this far we can be pretty confident that // the domain was already set up because it's encrypted @@ -274,6 +276,21 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { 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; }