tellform/config/express.js

372 lines
9.9 KiB
JavaScript
Raw Permalink Normal View History

2015-06-29 22:51:29 +00:00
'use strict';
/**
* Module dependencies.
*/
2017-10-11 05:07:13 +00:00
var fs = require('fs'),
2015-06-29 22:51:29 +00:00
https = require('https'),
express = require('express'),
morgan = require('morgan'),
logger = require('./logger'),
bodyParser = require('body-parser'),
session = require('express-session'),
compression = require('compression'),
methodOverride = require('method-override'),
cookieParser = require('cookie-parser'),
helmet = require('helmet'),
passport = require('passport'),
2015-07-13 22:11:40 +00:00
raven = require('raven'),
2016-04-21 20:25:29 +00:00
MongoStore = require('connect-mongo')(session),
2015-06-29 22:51:29 +00:00
config = require('./config'),
consolidate = require('consolidate'),
path = require('path'),
client = new raven.Client(config.DSN),
i18n = require('i18n');
2016-06-09 03:32:33 +00:00
var mongoose = require('mongoose');
2015-06-29 22:51:29 +00:00
2016-06-07 00:37:09 +00:00
/**
* Configure Socket.io
*/
var configureSocketIO = function (app, db) {
// Load the Socket.io configuration
var server = require('./socket.io')(app, db);
2015-08-07 21:02:44 +00:00
2016-06-07 00:37:09 +00:00
// Return server object
return server;
};
2015-07-13 22:11:40 +00:00
2017-10-28 03:46:00 +00:00
var supportedLanguages = ['en', 'de', 'fr', 'it', 'es'];
function containsAnySupportedLanguages(preferredLanguages){
for (var i = 0; i < preferredLanguages.length; i++) {
var currIndex = supportedLanguages.indexOf(preferredLanguages[i]);
if (currIndex > -1) {
return supportedLanguages[currIndex];
}
}
return null;
}
2015-06-29 22:51:29 +00:00
module.exports = function(db) {
// Initialize express app
var app = express();
2016-06-09 03:32:33 +00:00
var url = require('url');
2016-05-10 07:25:00 +00:00
2016-04-11 23:12:05 +00:00
// Globbing model files
config.getGlobbedFiles('./app/models/**/*.js').forEach(function(modelPath) {
require(path.resolve(modelPath));
});
2015-06-29 22:51:29 +00:00
// Setting application local variables
2016-04-24 18:41:27 +00:00
app.locals.google_analytics_id = config.app.google_analytics_id;
2015-06-29 22:51:29 +00:00
app.locals.title = config.app.title;
2016-05-10 07:25:00 +00:00
app.locals.signupDisabled = config.signupDisabled;
2015-06-29 22:51:29 +00:00
app.locals.description = config.app.description;
app.locals.keywords = config.app.keywords;
2017-03-28 00:04:03 +00:00
app.locals.subdomainsDisabled = config.subdomainsDisabled;
2017-10-10 23:27:07 +00:00
if(config.socketPortExternallyVisible){
app.locals.socketPort = config.socketPort;
} else {
app.locals.socketPort = '';
}
2017-03-27 20:32:06 +00:00
if(config.socketUrl){
app.locals.socketUrl = config.socketUrl;
}
app.locals.bowerJSFiles = config.getBowerJSAssets();
app.locals.bowerCssFiles = config.getBowerCSSAssets();
app.locals.bowerOtherFiles = config.getBowerOtherAssets();
2015-06-29 22:51:29 +00:00
app.locals.jsFiles = config.getJavaScriptAssets();
2016-06-09 03:32:33 +00:00
app.locals.formJSFiles = config.getFormJavaScriptAssets();
2015-06-29 22:51:29 +00:00
app.locals.cssFiles = config.getCSSAssets();
2016-06-09 03:32:33 +00:00
app.use(function (req, res, next) {
var urlPath;
2017-03-28 00:04:03 +00:00
if(!config.subdomainsDisabled) {
var User = mongoose.model('User');
var subdomainPath = '/subdomain/';
2017-03-28 00:04:03 +00:00
var subdomains = req.subdomains;
2017-03-28 00:04:03 +00:00
if (subdomains.slice(0, 4).join('.') + '' === '1.0.0.127') {
subdomains = subdomains.slice(4);
2016-06-09 03:32:33 +00:00
}
2017-03-28 00:04:03 +00:00
// continue if no subdomains
if (!subdomains.length) {
return next();
}
urlPath = url.parse(req.url).path.split('/');
2017-03-28 00:04:03 +00:00
if (urlPath.indexOf('static') > -1) {
urlPath.splice(1, 1);
req.root = req.protocol + '://' + config.baseUrl + urlPath.join('/');
2017-03-28 00:04:03 +00:00
return next();
2016-06-09 03:32:33 +00:00
}
2017-03-28 00:04:03 +00:00
if (urlPath.indexOf('users') > -1 && urlPath.indexOf('me') > -1) {
return next();
}
2016-06-09 03:32:33 +00:00
2017-03-28 00:04:03 +00:00
if (subdomains.indexOf('stage') > -1 || subdomains.indexOf('admin') > -1) {
return next();
}
2016-06-09 03:32:33 +00:00
2017-03-28 00:04:03 +00:00
if (subdomains.indexOf('api') > -1) {
// rebuild url
subdomainPath += 'api' + req.url;
2017-03-28 00:04:03 +00:00
// TODO: check path and query strings are preserved
// reassign url
req.url = subdomainPath;
2017-03-28 00:04:03 +00:00
return next();
}
2017-03-27 20:32:06 +00:00
2017-03-28 00:04:03 +00:00
User.findOne({username: req.subdomains.reverse()[0]}).exec(function (err, user) {
if (err) {
req.subdomains = null;
// Error page
return res.status(404).render('404', {
error: 'Page Does Not Exist'
});
}
if (user === null) {
// Error page
return res.status(404).render('404', {
error: 'Page Does Not Exist'
});
}
// rebuild url
subdomainPath += subdomains.join('/') + req.url;
2017-03-28 00:04:03 +00:00
// TODO: check path and query strings are preserved
// reassign url
req.url = subdomainPath;
2017-03-28 00:04:03 +00:00
// Q.E.D.
return next();
2017-03-28 00:04:03 +00:00
});
} else {
urlPath = url.parse(req.url).path.split('/');
2017-03-28 00:04:03 +00:00
if (urlPath.indexOf('static') > -1 && urlPath.indexOf('view') === urlPath.indexOf('static')-1) {
urlPath.splice(1, 1);
req.url = urlPath.join('/');
}
2016-06-09 03:32:33 +00:00
2017-03-28 00:04:03 +00:00
return next();
}
2016-06-09 03:32:33 +00:00
});
2016-04-23 04:00:44 +00:00
//Setup Prerender.io
app.use(require('prerender-node').set('prerenderToken', process.env.PRERENDER_TOKEN));
2016-05-10 07:25:00 +00:00
2017-04-11 07:10:36 +00:00
2015-06-29 22:51:29 +00:00
// Passing the request url to environment locals
app.use(function(req, res, next) {
2015-07-27 18:11:43 +00:00
if(config.baseUrl === ''){
config.baseUrl = req.protocol + '://' + req.headers.host;
}
res.locals.url = req.protocol + '://' + req.headers.host + req.url;
2015-06-29 22:51:29 +00:00
next();
});
// Should be placed before express.static
app.use(compression({
// only compress files for the following content types
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
// zlib option for compression level
2017-04-11 07:10:36 +00:00
level: 9
2015-06-29 22:51:29 +00:00
}));
//Setup i18n
i18n.configure({
locales: supportedLanguages,
directory: __dirname + '/locales',
defaultLocale: 'en',
cookie: 'userLang'
});
app.use(i18n.init);
app.use(function(req, res, next) {
// express helper for natively supported engines
res.locals.__ = res.__ = function() {
return i18n.__.apply(req, arguments);
};
next();
});
2015-06-29 22:51:29 +00:00
// Set template engine as defined in the config files
app.engine('server.view.pug', consolidate.pug);
2015-06-29 22:51:29 +00:00
// Set views path and view engine
app.set('view engine', 'server.view.pug');
2015-06-29 22:51:29 +00:00
app.set('views', './app/views');
// Enable logger (morgan)
2017-07-20 23:09:21 +00:00
app.use(morgan(logger.getLogFormat(), logger.getMorganOptions()));
2015-06-29 22:51:29 +00:00
// Environment dependent middleware
2017-11-02 18:14:25 +00:00
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
2015-06-29 22:51:29 +00:00
// Disable views cache
app.set('view cache', false);
} else if (process.env.NODE_ENV === 'production') {
app.locals.cache = 'memory';
app.set('view cache', true);
2015-06-29 22:51:29 +00:00
}
// Request body parsing middleware should be above methodOverride
app.use(bodyParser.urlencoded({
2017-03-06 19:43:42 +00:00
extended: true,
limit: '100mb'
2015-06-29 22:51:29 +00:00
}));
2017-10-28 03:46:00 +00:00
2017-03-06 19:43:42 +00:00
app.use(bodyParser.json({ limit: '100mb' }));
2015-06-29 22:51:29 +00:00
app.use(methodOverride());
2016-03-30 03:45:16 +00:00
// Use helmet to secure Express headers
app.use(helmet.frameguard());
2016-03-30 03:45:16 +00:00
app.use(helmet.xssFilter());
app.use(helmet.noSniff());
app.use(helmet.ieNoOpen());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.hidePoweredBy());
2016-03-30 03:45:16 +00:00
2016-05-10 07:25:00 +00:00
2015-06-29 22:51:29 +00:00
// Setting the app router and static folder
2016-06-09 03:32:33 +00:00
app.use('/static', express.static(path.resolve('./public')));
2015-07-27 18:11:43 +00:00
app.use('/uploads', express.static(path.resolve('./uploads')));
2015-06-29 22:51:29 +00:00
// CookieParser should be above session
app.use(cookieParser());
// Express MongoDB session storage
app.use(session({
saveUninitialized: true,
resave: true,
secret: config.sessionSecret,
2015-11-05 22:07:56 +00:00
store: new MongoStore({
mongooseConnection: db.connection,
collection: config.sessionCollection
}),
2015-06-29 22:51:29 +00:00
cookie: config.sessionCookie,
2015-11-03 19:55:11 +00:00
name: config.sessionName
2015-06-29 22:51:29 +00:00
}));
2016-05-10 07:25:00 +00:00
2016-04-11 23:12:05 +00:00
// use passport session
app.use(passport.initialize());
app.use(passport.session());
2017-10-28 03:46:00 +00:00
//Visitor Language Detection
app.use(function(req, res, next) {
var acceptLanguage = req.headers['accept-language'];
2017-11-02 18:14:25 +00:00
var languages, supportedLanguage;
if(acceptLanguage){
languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || [];
supportedLanguage = containsAnySupportedLanguages(languages);
}
2017-10-28 03:46:00 +00:00
if(!req.user && supportedLanguage !== null){
var currLanguage = res.cookie('userLang');
if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){
res.clearCookie('userLang');
res.cookie('userLang', supportedLanguage, { maxAge: 90000, httpOnly: true });
}
2017-10-28 07:45:04 +00:00
} else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies['userLang'] !== req.user.language) ){
res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true });
2017-10-28 03:46:00 +00:00
}
next();
});
2016-04-11 23:12:05 +00:00
// Globbing routing files
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
2015-06-29 22:51:29 +00:00
// Add headers for Sentry
2015-08-07 21:02:44 +00:00
app.use(function (req, res, next) {
// Website you wish to allow to connect
2017-11-02 18:14:25 +00:00
res.setHeader('Access-Control-Allow-Origin', 'https://sentry.io');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
2016-06-07 00:37:09 +00:00
// Sentry (Raven) middleware
2016-06-09 03:32:33 +00:00
app.use(raven.middleware.express.requestHandler(config.DSN));
// Should come before any other error middleware
2016-06-09 03:32:33 +00:00
app.use(raven.middleware.express.errorHandler(config.DSN));
2015-06-29 22:51:29 +00:00
// Assume 'not found' in the error msgs is a 404. this is somewhat silly, but valid, you can do whatever you like, set properties, use instanceof etc.
app.use(function(err, req, res, next) {
// If the error object doesn't exists
if (!err) {
return next();
}
2015-06-29 22:51:29 +00:00
// Log it
client.captureError(err);
2015-06-29 22:51:29 +00:00
2017-11-02 18:14:25 +00:00
// Error page
res.status(500).render('500', {
__: i18n.__,
error: err.stack
2017-11-02 18:14:25 +00:00
});
2015-06-29 22:51:29 +00:00
});
// Assume 404 since no middleware responded
app.use(function(req, res) {
client.captureError(new Error('Page Not Found'));
2015-06-29 22:51:29 +00:00
res.status(404).render('404', {
url: req.originalUrl,
error: 'Not Found',
__: i18n.__
2015-06-29 22:51:29 +00:00
});
});
if (process.env.NODE_ENV === 'secure') {
// Load SSL key and certificate
var privateKey = fs.readFileSync('./config/sslcerts/key.pem', 'utf8');
var certificate = fs.readFileSync('./config/sslcerts/cert.pem', 'utf8');
// Create HTTPS Server
var httpsServer = https.createServer({
key: privateKey,
cert: certificate
}, app);
// Return HTTPS server instance
return httpsServer;
}
2016-06-09 03:32:33 +00:00
2016-06-07 00:37:09 +00:00
app = configureSocketIO(app, db);
2015-06-29 22:51:29 +00:00
// Return Express server instance
return app;
};