From 47f6f2febecb3aea2b805ba77a0c8e1c8b095389 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Fri, 14 Aug 2015 11:50:09 +0200 Subject: [PATCH] refactor middlewares in their own folder, move buildFiles to libs/buildFiles --- config.json.example | 1 - website/src/i18n.js | 2 +- website/src/libs/buildManifest.js | 62 ++++++ website/src/middleware.js | 249 ------------------------ website/src/middlewares/apiThrottle.js | 21 ++ website/src/middlewares/cors.js | 7 + website/src/middlewares/domain.js | 39 ++++ website/src/middlewares/errorHandler.js | 24 +++ website/src/middlewares/forceRefresh.js | 9 + website/src/middlewares/locals.js | 51 +++++ website/src/middlewares/redirects.js | 43 ++++ website/src/routes/apiv1.js | 4 +- website/src/routes/apiv2.coffee | 5 +- website/src/routes/dataexport.js | 6 +- website/src/routes/pages.js | 6 +- website/src/server.js | 16 +- 16 files changed, 275 insertions(+), 270 deletions(-) create mode 100644 website/src/libs/buildManifest.js delete mode 100644 website/src/middleware.js create mode 100644 website/src/middlewares/apiThrottle.js create mode 100644 website/src/middlewares/cors.js create mode 100644 website/src/middlewares/domain.js create mode 100644 website/src/middlewares/errorHandler.js create mode 100644 website/src/middlewares/forceRefresh.js create mode 100644 website/src/middlewares/locals.js create mode 100644 website/src/middlewares/redirects.js diff --git a/config.json.example b/config.json.example index 55adbe801f..793dcc1f14 100644 --- a/config.json.example +++ b/config.json.example @@ -21,7 +21,6 @@ "NEW_RELIC_APPLICATION_ID":"NEW_RELIC_APPLICATION_ID", "NEW_RELIC_API_KEY":"NEW_RELIC_API_KEY", "GA_ID": "GA_ID", - "MIXPANEL_TOKEN": "MIXPANEL_TOKEN", "AMPLITUDE_KEY": "AMPLITUDE_KEY", "AMAZON_PAYMENTS": { "SELLER_ID": "SELLER_ID", diff --git a/website/src/i18n.js b/website/src/i18n.js index 82967213b9..2f0f14eeb6 100644 --- a/website/src/i18n.js +++ b/website/src/i18n.js @@ -148,7 +148,7 @@ module.exports = { // Export en strings only, temporary solution for mobile -// This is copied from middleware.js#module.exports.locals#t() +// This is copied from middlewares/locals#t() module.exports.enTranslations = function(){ // stringName and vars are the allowed parameters var language = _.find(avalaibleLanguages, {code: 'en'}); //language.momentLang = ((!isStaticPage && i18n.momentLangs[language.code]) || undefined); diff --git a/website/src/libs/buildManifest.js b/website/src/libs/buildManifest.js new file mode 100644 index 0000000000..ac4c35d19b --- /dev/null +++ b/website/src/libs/buildManifest.js @@ -0,0 +1,62 @@ +var fs = require('fs'); +var path = require('path'); +var nconf = require('nconf'); +var _ = require('lodash'); +var manifestFiles = require("../../public/manifest.json"); + +var IS_PROD = nconf.get('NODE_ENV') === 'production'; +var buildFiles = []; + +var walk = function(folder){ + var res = fs.readdirSync(folder); + var files = []; + + res.forEach(function(fileName){ + file = folder + '/' + fileName; + if(fs.statSync(file).isDirectory()){ + walk(file); + }else{ + var relFolder = path.relative(path.join(__dirname, "/../../build"), folder); + var old = fileName.replace(/-.{8}(\.[\d\w]+)$/, '$1'); + + if(relFolder){ + old = relFolder + '/' + old; + fileName = relFolder + '/' + fileName; + } + + buildFiles[old] = fileName + } + }); + + return files; +} + +walk(path.join(__dirname, "/../../build")); + +var getBuildUrl = module.exports.getBuildUrl = function(url){ + if(buildFiles[url]) return '/' + buildFiles[url]; + + return '/' + url; +} + +module.exports.getManifestFiles = function(page){ + var files = manifestFiles[page]; + + if(!files) throw new Error("Page not found!"); + + var code = ''; + + if(IS_PROD){ + code += ''; + code += ''; + }else{ + _.each(files.css, function(file){ + code += ''; + }); + _.each(files.js, function(file){ + code += ''; + }); + } + + return code; +} diff --git a/website/src/middleware.js b/website/src/middleware.js deleted file mode 100644 index d0e1579d6e..0000000000 --- a/website/src/middleware.js +++ /dev/null @@ -1,249 +0,0 @@ -var nconf = require('nconf'); -var _ = require('lodash'); -var fs = require('fs'); -var path = require('path'); -var User = require('./models/user').model -var limiter = require('connect-ratelimit'); -var logging = require('./logging'); -var domainMiddleware = require('domain-middleware'); -var cluster = require('cluster'); -var i18n = require('./i18n.js'); -var shared = require('../../common'); -var request = require('request'); -var os = require('os'); -var moment = require('moment'); -var utils = require('./utils'); - -var IS_PROD = nconf.get('NODE_ENV') === 'production'; -var BASE_URL = nconf.get("BASE_URL"); - -module.exports.apiThrottle = function(app) { - if (!IS_PROD) return; - app.use(limiter({ - end:false, - catagories:{ - normal: { - // 2 req/s, but split as minutes - totalRequests: 80, - every: 60000 - } - } - })).use(function(req,res,next){ - //logging.info(res.ratelimit); - if (res.ratelimit.exceeded) return res.json(429,{err:'Rate limit exceeded'}); - next(); - }); -} - -module.exports.domainMiddleware = function(server,mongoose) { - if (IS_PROD) { - var mins = 3, // how often to run this check - useAvg = false, // use average over 3 minutes, or simply the last minute's report - url = 'https://api.newrelic.com/v2/applications/'+nconf.get('NEW_RELIC_APPLICATION_ID')+'/metrics/data.json?names[]=Apdex&values[]=score'; - setInterval(function(){ - // see https://docs.newrelic.com/docs/apm/apis/api-v2-examples/average-response-time-examples-api-v2, https://rpm.newrelic.com/api/explore/applications/data - request({ - url: useAvg ? url+'&from='+moment().subtract({minutes:mins}).utc().format()+'&to='+moment().utc().format()+'&summarize=true' : url, - headers: {'X-Api-Key': nconf.get('NEW_RELIC_API_KEY')} - }, function(err, response, body){ - var ts = JSON.parse(body).metric_data.metrics[0].timeslices, - score = ts[ts.length-1].values.score, - apdexBad = score < .75 || score == 1, - memory = os.freemem() / os.totalmem(), - memoryHigh = memory < 0.1; - if (/*apdexBad || */memoryHigh) throw "[Memory Leak] Apdex="+score+" Memory="+parseFloat(memory).toFixed(3)+" Time="+moment().format(); - }) - }, mins*60*1000); - } - - return domainMiddleware({ - server: { - close:function(){ - server.close(); - mongoose.connection.close(); - } - }, - killTimeout: 10000 - }); -} - -module.exports.errorHandler = function(err, req, res, next) { - //res.locals.domain.emit('error', err); - // when we hit an error, send it to admin as an email. If no ADMIN_EMAIL is present, just send it to yourself (SMTP_USER) - var stack = (err.stack ? err.stack : err.message ? err.message : err) + - "\n ----------------------------\n" + - "\n\noriginalUrl: " + req.originalUrl + - "\n\nauth: " + req.headers['x-api-user'] + ' | ' + req.headers['x-api-key'] + - "\n\nheaders: " + JSON.stringify(req.headers) + - "\n\nbody: " + JSON.stringify(req.body) + - (res.locals.ops ? "\n\ncompleted ops: " + JSON.stringify(res.locals.ops) : ""); - logging.error(stack); - /*logging.loggly({ - error: "Uncaught error", - stack: (err.stack || err.message || err), - body: req.body, headers: req.header, - auth: req.headers['x-api-user'], - originalUrl: req.originalUrl - });*/ - var message = err.message ? err.message : err; - message = (message.length < 200) ? message : message.substring(0,100) + message.substring(message.length-100,message.length); - res.json(500,{err:message}); //res.end(err.message); -} - -function isHTTP(req) { - return ( - req.headers['x-forwarded-proto'] && - req.headers['x-forwarded-proto'] !== 'https' && - IS_PROD && - BASE_URL.indexOf('https') === 0 - ); -} - -function isProxied(req) { - return ( - req.headers['x-habitica-lb'] && - req.headers['x-habitica-lb'] === 'Yes' - ); -} - -module.exports.forceSSL = function(req, res, next){ - if(isHTTP(req) && !isProxied(req)) { - return res.redirect(BASE_URL + req.url); - } - - next(); -} - -// Redirect to habitica for non-api urls -// NOTE: Currently using a static 'habitica.com' string, rather than BASE_URL, -// to make rollback easy. Eventually, BASE_URL should be migrated. - -function nonApiUrl(req) { - return req.url.search(/\/api\//) === -1; -} - -module.exports.forceHabitica = function(req, res, next) { - var ignoreRedirect = nconf.get('IGNORE_REDIRECT'); - - if (IS_PROD && !ignoreRedirect && !isProxied(req) && nonApiUrl(req)) { - return res.redirect('https://habitica.com' + req.url); - } - next(); -}; - -module.exports.cors = function(req, res, next) { - res.header("Access-Control-Allow-Origin", req.headers.origin || "*"); - res.header("Access-Control-Allow-Methods", "OPTIONS,GET,POST,PUT,HEAD,DELETE"); - res.header("Access-Control-Allow-Headers", "Content-Type,Accept,Content-Encoding,X-Requested-With,x-api-user,x-api-key"); - if (req.method === 'OPTIONS') return res.send(200); - return next(); -}; - -var siteVersion = 1; - -module.exports.forceRefresh = function(req, res, next){ - if(req.query.siteVersion && req.query.siteVersion != siteVersion){ - return res.json(400, {needRefresh: true}); - } - - return next(); -}; - -var buildFiles = []; - -var walk = function(folder){ - var res = fs.readdirSync(folder); - - res.forEach(function(fileName){ - file = folder + '/' + fileName; - if(fs.statSync(file).isDirectory()){ - walk(file); - }else{ - var relFolder = path.relative(path.join(__dirname, "/../build"), folder); - var old = fileName.replace(/-.{8}(\.[\d\w]+)$/, '$1'); - - if(relFolder){ - old = relFolder + '/' + old; - fileName = relFolder + '/' + fileName; - } - - buildFiles[old] = fileName - } - }); -} - -walk(path.join(__dirname, "/../build")); - -var getBuildUrl = function(url){ - if(buildFiles[url]) return '/' + buildFiles[url]; - - return '/' + url; -} - -var manifestFiles = require("../public/manifest.json"); - -var getManifestFiles = function(page){ - var files = manifestFiles[page]; - - if(!files) throw new Error("Page not found!"); - - var code = ''; - - if(IS_PROD){ - code += ''; - code += ''; - }else{ - _.each(files.css, function(file){ - code += ''; - }); - _.each(files.js, function(file){ - code += ''; - }); - } - - return code; -} - -module.exports.locals = function(req, res, next) { - var language = _.find(i18n.avalaibleLanguages, {code: req.language}); - var isStaticPage = req.url.split('/')[1] === 'static'; // If url contains '/static/' - - // Load moment.js language file only when not on static pages - language.momentLang = ((!isStaticPage && i18n.momentLangs[language.code]) || undefined); - - var tavern = require('./models/group').tavern; - var envVars = _.pick(nconf.get(), 'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY AMPLITUDE_KEY'.split(' ')); - res.locals.habitrpg = _.merge(envVars, { - IS_MOBILE: /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')), - getManifestFiles: getManifestFiles, - getBuildUrl: getBuildUrl, - avalaibleLanguages: i18n.avalaibleLanguages, - language: language, - isStaticPage: isStaticPage, - translations: i18n.translations[language.code], - t: function(){ // stringName and vars are the allowed parameters - var args = Array.prototype.slice.call(arguments, 0); - args.push(language.code); - return shared.i18n.t.apply(null, args); - }, - siteVersion: siteVersion, - Content: shared.content, - mods: require('./models/user').mods, - tavern: tavern, // for world boss - worldDmg: (tavern && tavern.quest && tavern.quest.extra && tavern.quest.extra.worldDmg) || {}, - _: _, - MP_ID: nconf.get('MP_ID'), - AMAZON_PAYMENTS: { - SELLER_ID: nconf.get('AMAZON_PAYMENTS:SELLER_ID'), - CLIENT_ID: nconf.get('AMAZON_PAYMENTS:CLIENT_ID') - } - }); - - // Put query-string party (& guild but use partyInvite for backward compatibility) - // invitations into session to be handled later - try{ - req.session.partyInvite = JSON.parse(utils.decrypt(req.query.partyInvite)) - } catch(e){} - - next(); -} diff --git a/website/src/middlewares/apiThrottle.js b/website/src/middlewares/apiThrottle.js new file mode 100644 index 0000000000..44acad4fa2 --- /dev/null +++ b/website/src/middlewares/apiThrottle.js @@ -0,0 +1,21 @@ +var nconf = require('nconf'); + +var IS_PROD = nconf.get('NODE_ENV') === 'production'; + +module.exports = function(app) { + if (!IS_PROD) return; + app.use(limiter({ + end:false, + catagories:{ + normal: { + // 2 req/s, but split as minutes + totalRequests: 80, + every: 60000 + } + } + })).use(function(req,res,next){ + //logging.info(res.ratelimit); + if (res.ratelimit.exceeded) return res.json(429,{err:'Rate limit exceeded'}); + next(); + }); +} diff --git a/website/src/middlewares/cors.js b/website/src/middlewares/cors.js new file mode 100644 index 0000000000..b694aff2af --- /dev/null +++ b/website/src/middlewares/cors.js @@ -0,0 +1,7 @@ +module.exports = function(req, res, next) { + res.header("Access-Control-Allow-Origin", req.headers.origin || "*"); + res.header("Access-Control-Allow-Methods", "OPTIONS,GET,POST,PUT,HEAD,DELETE"); + res.header("Access-Control-Allow-Headers", "Content-Type,Accept,Content-Encoding,X-Requested-With,x-api-user,x-api-key"); + if (req.method === 'OPTIONS') return res.send(200); + return next(); +}; diff --git a/website/src/middlewares/domain.js b/website/src/middlewares/domain.js new file mode 100644 index 0000000000..3178dc6188 --- /dev/null +++ b/website/src/middlewares/domain.js @@ -0,0 +1,39 @@ +var nconf = require('nconf'); +var moment = require('moment'); +var domainMiddleware = require('domain-middleware'); +var os = require('os'); +var request = require('request'); + +var IS_PROD = nconf.get('NODE_ENV') === 'production'; + +module.exports = function(server,mongoose) { + if (IS_PROD) { + var mins = 3, // how often to run this check + useAvg = false, // use average over 3 minutes, or simply the last minute's report + url = 'https://api.newrelic.com/v2/applications/'+nconf.get('NEW_RELIC_APPLICATION_ID')+'/metrics/data.json?names[]=Apdex&values[]=score'; + setInterval(function(){ + // see https://docs.newrelic.com/docs/apm/apis/api-v2-examples/average-response-time-examples-api-v2, https://rpm.newrelic.com/api/explore/applications/data + request({ + url: useAvg ? url+'&from='+moment().subtract({minutes:mins}).utc().format()+'&to='+moment().utc().format()+'&summarize=true' : url, + headers: {'X-Api-Key': nconf.get('NEW_RELIC_API_KEY')} + }, function(err, response, body){ + var ts = JSON.parse(body).metric_data.metrics[0].timeslices, + score = ts[ts.length-1].values.score, + apdexBad = score < .75 || score == 1, + memory = os.freemem() / os.totalmem(), + memoryHigh = memory < 0.1; + if (/*apdexBad || */memoryHigh) throw "[Memory Leak] Apdex="+score+" Memory="+parseFloat(memory).toFixed(3)+" Time="+moment().format(); + }) + }, mins*60*1000); + } + + return domainMiddleware({ + server: { + close:function(){ + server.close(); + mongoose.connection.close(); + } + }, + killTimeout: 10000 + }); +} diff --git a/website/src/middlewares/errorHandler.js b/website/src/middlewares/errorHandler.js new file mode 100644 index 0000000000..d07476e76f --- /dev/null +++ b/website/src/middlewares/errorHandler.js @@ -0,0 +1,24 @@ +var logging = require('../logging'); + +module.exports = function(err, req, res, next) { + //res.locals.domain.emit('error', err); + // when we hit an error, send it to admin as an email. If no ADMIN_EMAIL is present, just send it to yourself (SMTP_USER) + var stack = (err.stack ? err.stack : err.message ? err.message : err) + + "\n ----------------------------\n" + + "\n\noriginalUrl: " + req.originalUrl + + "\n\nauth: " + req.headers['x-api-user'] + ' | ' + req.headers['x-api-key'] + + "\n\nheaders: " + JSON.stringify(req.headers) + + "\n\nbody: " + JSON.stringify(req.body) + + (res.locals.ops ? "\n\ncompleted ops: " + JSON.stringify(res.locals.ops) : ""); + logging.error(stack); + /*logging.loggly({ + error: "Uncaught error", + stack: (err.stack || err.message || err), + body: req.body, headers: req.header, + auth: req.headers['x-api-user'], + originalUrl: req.originalUrl + });*/ + var message = err.message ? err.message : err; + message = (message.length < 200) ? message : message.substring(0,100) + message.substring(message.length-100,message.length); + res.json(500,{err:message}); //res.end(err.message); +} diff --git a/website/src/middlewares/forceRefresh.js b/website/src/middlewares/forceRefresh.js new file mode 100644 index 0000000000..e022aed2f6 --- /dev/null +++ b/website/src/middlewares/forceRefresh.js @@ -0,0 +1,9 @@ +module.exports.siteVersion = 1; + +module.exports.middleware = function(req, res, next){ + if(req.query.siteVersion && req.query.siteVersion != module.exports.siteVersion){ + return res.json(400, {needRefresh: true}); + } + + return next(); +}; diff --git a/website/src/middlewares/locals.js b/website/src/middlewares/locals.js new file mode 100644 index 0000000000..c77fe6cd90 --- /dev/null +++ b/website/src/middlewares/locals.js @@ -0,0 +1,51 @@ +var nconf = require('nconf'); +var _ = require('lodash'); +var utils = require('../utils'); +var shared = require('../../../common'); +var i18n = require('../i18n.js'); +var buildManifest = require('../libs/buildManifest'); +var shared = require('../../../common'); +var forceRefresh = require('./forceRefresh'); + +module.exports = function(req, res, next) { + var language = _.find(i18n.avalaibleLanguages, {code: req.language}); + var isStaticPage = req.url.split('/')[1] === 'static'; // If url contains '/static/' + + // Load moment.js language file only when not on static pages + language.momentLang = ((!isStaticPage && i18n.momentLangs[language.code]) || undefined); + + var tavern = require('../models/group').tavern; + var envVars = _.pick(nconf.get(), 'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY AMPLITUDE_KEY'.split(' ')); + res.locals.habitrpg = _.merge(envVars, { + IS_MOBILE: /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')), + getManifestFiles: buildManifest.getManifestFiles, + getBuildUrl: buildManifest.getBuildUrl, + avalaibleLanguages: i18n.avalaibleLanguages, + language: language, + isStaticPage: isStaticPage, + translations: i18n.translations[language.code], + t: function(){ // stringName and vars are the allowed parameters + var args = Array.prototype.slice.call(arguments, 0); + args.push(language.code); + return shared.i18n.t.apply(null, args); + }, + siteVersion: forceRefresh.siteVersion, + Content: shared.content, + mods: require('../models/user').mods, + tavern: tavern, // for world boss + worldDmg: (tavern && tavern.quest && tavern.quest.extra && tavern.quest.extra.worldDmg) || {}, + _: _, + AMAZON_PAYMENTS: { + SELLER_ID: nconf.get('AMAZON_PAYMENTS:SELLER_ID'), + CLIENT_ID: nconf.get('AMAZON_PAYMENTS:CLIENT_ID') + } + }); + + // Put query-string party (& guild but use partyInvite for backward compatibility) + // invitations into session to be handled later + try{ + req.session.partyInvite = JSON.parse(utils.decrypt(req.query.partyInvite)) + } catch(e){} + + next(); +} diff --git a/website/src/middlewares/redirects.js b/website/src/middlewares/redirects.js new file mode 100644 index 0000000000..8a334c7401 --- /dev/null +++ b/website/src/middlewares/redirects.js @@ -0,0 +1,43 @@ +var nconf = require('nconf'); +var IS_PROD = nconf.get('NODE_ENV') === 'production'; +var ignoreRedirect = nconf.get('IGNORE_REDIRECT'); +var BASE_URL = nconf.get("BASE_URL"); + +function isHTTP(req) { + return ( + req.headers['x-forwarded-proto'] && + req.headers['x-forwarded-proto'] !== 'https' && + IS_PROD && + BASE_URL.indexOf('https') === 0 + ); +} + +function isProxied(req) { + return ( + req.headers['x-habitica-lb'] && + req.headers['x-habitica-lb'] === 'Yes' + ); +} + +module.exports.forceSSL = function(req, res, next){ + if(isHTTP(req) && !isProxied(req)) { + return res.redirect(BASE_URL + req.url); + } + + next(); +} + +// Redirect to habitica for non-api urls +// NOTE: Currently using a static 'habitica.com' string, rather than BASE_URL, +// to make rollback easy. Eventually, BASE_URL should be migrated. + +function nonApiUrl(req) { + return req.url.search(/\/api\//) === -1; +} + +module.exports.forceHabitica = function(req, res, next) { + if (IS_PROD && !ignoreRedirect && !isProxied(req) && nonApiUrl(req)) { + return res.redirect('https://habitica.com' + req.url); + } + next(); +}; diff --git a/website/src/routes/apiv1.js b/website/src/routes/apiv1.js index f37619f195..5a28ef8f3b 100644 --- a/website/src/routes/apiv1.js +++ b/website/src/routes/apiv1.js @@ -5,9 +5,9 @@ var async = require('async'); var icalendar = require('icalendar'); var api = require('./../controllers/user'); var auth = require('./../controllers/auth'); -var middleware = require('../middleware'); var logging = require('./../logging'); var i18n = require('./../i18n'); +var forceRefresh = require('../middlewares/forceRefresh').middleware; /* ---------- Deprecated API ------------*/ @@ -161,7 +161,7 @@ router.post('/user/task', auth.auth, i18n.getUserLanguage, cron, api.addTask); // User router.get('/user', auth.auth, i18n.getUserLanguage, cron, api.getUser); router.post('/user/revive', auth.auth, i18n.getUserLanguage, cron, api.revive); -router.post('/user/batch-update', middleware.forceRefresh, auth.auth, i18n.getUserLanguage, cron, batchUpdate); +router.post('/user/batch-update', forceRefresh, auth.auth, i18n.getUserLanguage, cron, batchUpdate); function deprecated(req, res) { res.json(404, {err:'API v1 is no longer supported, please use API v2 instead (https://github.com/HabitRPG/habitrpg/blob/develop/API.md)'}); diff --git a/website/src/routes/apiv2.coffee b/website/src/routes/apiv2.coffee index 947979c8c2..082db2efa6 100644 --- a/website/src/routes/apiv2.coffee +++ b/website/src/routes/apiv2.coffee @@ -16,12 +16,11 @@ hall = require("../controllers/hall") challenges = require("../controllers/challenges") dataexport = require("../controllers/dataexport") nconf = require("nconf") -middleware = require("../middleware") cron = user.cron _ = require('lodash') content = require('../../../common').content i18n = require('../i18n') - +forceRefresh = require('../middlewares/forceRefresh').middleware module.exports = (swagger, v2) -> [path,body,query] = [swagger.pathParam, swagger.bodyParam, swagger.queryParam] @@ -326,7 +325,7 @@ module.exports = (swagger, v2) -> parameters:[ body '','The array of batch-operations to perform','object' ] - middleware: [middleware.forceRefresh, auth.auth, i18n.getUserLanguage, cron, user.sessionPartyInvite] + middleware: [forceRefresh, auth.auth, i18n.getUserLanguage, cron, user.sessionPartyInvite] action: user.batchUpdate # Tags diff --git a/website/src/routes/dataexport.js b/website/src/routes/dataexport.js index ba27957124..9fc2ded323 100644 --- a/website/src/routes/dataexport.js +++ b/website/src/routes/dataexport.js @@ -4,13 +4,13 @@ var dataexport = require('../controllers/dataexport'); var auth = require('../controllers/auth'); var nconf = require('nconf'); var i18n = require('../i18n'); -var middleware = require('../middleware.js'); +var locals = require('../middlewares/locals'); /* Data export */ router.get('/history.csv',auth.authWithSession,i18n.getUserLanguage,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes router.get('/userdata.xml',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.xml); router.get('/userdata.json',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.json); -router.get('/avatar-:uuid.html', i18n.getUserLanguage, middleware.locals, dataexport.avatarPage); -router.get('/avatar-:uuid.png', i18n.getUserLanguage, middleware.locals, dataexport.avatarImage); +router.get('/avatar-:uuid.html', i18n.getUserLanguage, locals, dataexport.avatarPage); +router.get('/avatar-:uuid.png', i18n.getUserLanguage, locals, dataexport.avatarImage); module.exports = router; diff --git a/website/src/routes/pages.js b/website/src/routes/pages.js index 4d72ad52ee..f3f59e3b9a 100644 --- a/website/src/routes/pages.js +++ b/website/src/routes/pages.js @@ -2,13 +2,13 @@ var nconf = require('nconf'); var express = require('express'); var router = new express.Router(); var _ = require('lodash'); -var middleware = require('../middleware'); +var locals = require('../middlewares/locals'); var user = require('../controllers/user'); var auth = require('../controllers/auth'); var i18n = require('../i18n'); // -------- App -------- -router.get('/', i18n.getUserLanguage, middleware.locals, function(req, res) { +router.get('/', i18n.getUserLanguage, locals, function(req, res) { if (!req.headers['x-api-user'] && !req.headers['x-api-key'] && !(req.session && req.session.userId)) return res.redirect('/static/front') @@ -23,7 +23,7 @@ router.get('/', i18n.getUserLanguage, middleware.locals, function(req, res) { var pages = ['front', 'privacy', 'terms', 'api', 'features', 'videos', 'contact', 'plans', 'new-stuff', 'community-guidelines', 'old-news', 'press-kit']; _.each(pages, function(name){ - router.get('/static/' + name, i18n.getUserLanguage, middleware.locals, function(req, res) { + router.get('/static/' + name, i18n.getUserLanguage, locals, function(req, res) { res.render('static/' + name, {env: res.locals.habitrpg}); }); }) diff --git a/website/src/server.js b/website/src/server.js index b108d13f2f..33bf720dcd 100644 --- a/website/src/server.js +++ b/website/src/server.js @@ -30,8 +30,6 @@ if (cores!==0 && cluster.isMaster && (isDev || isProd)) { // Setup translations var i18n = require('./i18n'); - var middleware = require('./middleware'); - var TWO_WEEKS = 1000 * 60 * 60 * 24 * 14; var app = express(); var server = http.createServer(); @@ -89,16 +87,18 @@ if (cores!==0 && cluster.isMaster && (isDev || isProd)) { var publicDir = path.join(__dirname, "/../public"); app.set("port", nconf.get('PORT')); - middleware.apiThrottle(app); - app.use(middleware.domainMiddleware(server,mongoose)); + require('./middlewares/apiThrottle')(app); + app.use(require('./middlewares/domain')(server,mongoose)); if (!isProd) app.use(express.logger("dev")); app.use(express.compress()); app.set("views", __dirname + "/../views"); app.set("view engine", "jade"); app.use(express.favicon(publicDir + '/favicon.ico')); - app.use(middleware.cors); - app.use(middleware.forceHabitica); - app.use(middleware.forceSSL); + app.use(require('./middlewares/cors')); + + var redirects = require('./middlewares/redirects'); + app.use(redirects.forceHabitica); + app.use(redirects.forceSSL); app.use(express.urlencoded()); app.use(express.json()); app.use(require('method-override')()); @@ -134,7 +134,7 @@ if (cores!==0 && cluster.isMaster && (isDev || isProd)) { app.use('/api/v1', require('./routes/apiv1').middleware); app.use('/export', require('./routes/dataexport').middleware); require('./routes/apiv2.coffee')(swagger, v2); - app.use(middleware.errorHandler); + app.use(require('./middlewares/errorHandler')); server.on('request', app); server.listen(app.get("port"), function() {